7#include <QtCore/QDateTime>
8#include <QtCore/QLoggingCategory>
9#include <QtCore/QtMath>
20 bool canCaptureImageInVideoMode,
21 bool canCaptureVideoInImageMode,
23 bool hasTrackingPoint,
24 bool hasTrackingRectangle)
28 uint32_t configuredFlags = 0;
29 if (captureVideo) configuredFlags |= CAMERA_CAP_FLAGS_CAPTURE_VIDEO;
30 if (captureImage) configuredFlags |= CAMERA_CAP_FLAGS_CAPTURE_IMAGE;
31 if (hasModes) configuredFlags |= CAMERA_CAP_FLAGS_HAS_MODES;
32 if (hasVideoStream) configuredFlags |= CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM;
33 if (canCaptureImageInVideoMode) configuredFlags |= CAMERA_CAP_FLAGS_CAN_CAPTURE_IMAGE_IN_VIDEO_MODE;
34 if (canCaptureVideoInImageMode) configuredFlags |= CAMERA_CAP_FLAGS_CAN_CAPTURE_VIDEO_IN_IMAGE_MODE;
35 if (hasBasicZoom) configuredFlags |= CAMERA_CAP_FLAGS_HAS_BASIC_ZOOM;
36 if (hasTrackingPoint) configuredFlags |= CAMERA_CAP_FLAGS_HAS_TRACKING_POINT;
37 if (hasTrackingRectangle) configuredFlags |= CAMERA_CAP_FLAGS_HAS_TRACKING_RECTANGLE;
40 _cameras[0].compId = MAV_COMP_ID_CAMERA;
41 _cameras[0].capFlags = configuredFlags;
42 _cameras[0].cameraMode = CAMERA_MODE_IMAGE;
43 if ((configuredFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM) && (configuredFlags & CAMERA_CAP_FLAGS_HAS_MODES)) {
44 _cameras[0].cameraMode = CAMERA_MODE_VIDEO;
48 _cameras[1].compId = MAV_COMP_ID_CAMERA2;
49 _cameras[1].capFlags = CAMERA_CAP_FLAGS_CAPTURE_IMAGE;
50 _cameras[1].cameraMode = CAMERA_MODE_IMAGE;
55 for (uint8_t i = 0; i < kNumCameras; i++) {
56 if (_cameras[i].compId == compId) {
63const char *MockLinkCamera::_imageCaptureStatusToString(uint8_t status)
70 default:
return "Unknown";
76 for (uint8_t i = 0; i < kNumCameras; i++) {
78 (void) mavlink_msg_heartbeat_pack_chan(
84 MAV_AUTOPILOT_INVALID,
96 QMutexLocker locker(&_camerasMutex);
97 const qint64 now = QDateTime::currentMSecsSinceEpoch();
99 for (uint8_t i = 0; i < kNumCameras; i++) {
108 qCDebug(MockLinkCameraLog) <<
"Camera" << cam->
compId <<
"single-shot complete, total:" << cam->
imagesCaptured;
109 _sendCameraImageCaptured(cam->
compId);
110 _sendCameraCaptureStatus(cam->
compId);
118 const double elapsed =
static_cast<double>(now - cam->
trackingStartMs) / 1000.0;
119 const float driftX = 0.05f *
static_cast<float>(qSin(elapsed * 0.7));
120 const float driftY = 0.05f *
static_cast<float>(qSin(elapsed * 1.1));
128 const float cx = std::clamp(cam->
trackAnchorX + driftX, halfW, 1.0f - halfW);
129 const float cy = std::clamp(cam->
trackAnchorY + driftY, halfH, 1.0f - halfH);
136 _sendCameraTrackingImageStatus(cam->
compId);
145 if (msg.msgid != MAVLINK_MSG_ID_COMMAND_LONG) {
150 mavlink_msg_command_long_decode(&msg, &request);
153 if (request.target_component < MAV_COMP_ID_CAMERA || request.target_component > MAV_COMP_ID_CAMERA6) {
157 const uint8_t targetCompId = request.target_component;
159 if (request.command == MAV_CMD_REQUEST_MESSAGE) {
160 return _handleRequestMessage(request, targetCompId);
163 return _handleCameraCommand(request, targetCompId);
171 QMutexLocker locker(&_camerasMutex);
172 CameraState *cam = _findCamera(targetCompId);
177 switch (request.command) {
178 case MAV_CMD_REQUEST_CAMERA_INFORMATION:
179 _sendCameraInformation(targetCompId);
180 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
183 case MAV_CMD_REQUEST_CAMERA_SETTINGS:
184 _sendCameraSettings(targetCompId);
185 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
188 case MAV_CMD_REQUEST_STORAGE_INFORMATION:
189 _sendStorageInformation(targetCompId);
190 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
193 case MAV_CMD_REQUEST_CAMERA_CAPTURE_STATUS:
194 _sendCameraCaptureStatus(targetCompId);
195 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
198 case MAV_CMD_REQUEST_VIDEO_STREAM_INFORMATION:
199 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM) {
200 const uint8_t streamId =
static_cast<uint8_t
>(request.param1);
203 for (uint8_t s = 1; s <= kNumStreams; s++) {
204 _sendVideoStreamInformation(targetCompId, s);
207 _sendVideoStreamInformation(targetCompId, streamId);
209 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
211 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
215 case MAV_CMD_REQUEST_VIDEO_STREAM_STATUS:
216 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM) {
217 const uint8_t streamId =
static_cast<uint8_t
>(request.param1);
219 for (uint8_t s = 1; s <= kNumStreams; s++) {
220 _sendVideoStreamStatus(targetCompId, s);
223 _sendVideoStreamStatus(targetCompId, streamId);
225 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
227 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
231 case MAV_CMD_SET_CAMERA_MODE:
232 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_MODES) {
233 const uint8_t requestedMode =
static_cast<uint8_t
>(request.param2);
235 if ((requestedMode != CAMERA_MODE_IMAGE) && (requestedMode != CAMERA_MODE_VIDEO)) {
236 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
240 const bool supportsImageMode =
241 (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_IMAGE) ||
242 (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM);
243 const bool supportsVideoMode =
244 (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_VIDEO) ||
245 (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM);
247 if ((requestedMode == CAMERA_MODE_IMAGE && !supportsImageMode) ||
248 (requestedMode == CAMERA_MODE_VIDEO && !supportsVideoMode)) {
249 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
253 cam->cameraMode = requestedMode;
254 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"mode set to" << cam->cameraMode;
255 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
257 _sendCameraSettings(targetCompId);
259 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
263 case MAV_CMD_IMAGE_START_CAPTURE:
264 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_IMAGE) {
265 if ((cam->capFlags & CAMERA_CAP_FLAGS_HAS_MODES) &&
266 (cam->cameraMode == CAMERA_MODE_VIDEO) &&
267 !(cam->capFlags & CAMERA_CAP_FLAGS_CAN_CAPTURE_IMAGE_IN_VIDEO_MODE)) {
268 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
272 const float interval = request.param2;
273 const int count =
static_cast<int>(request.param3);
279 cam->image_interval = interval;
280 cam->imagesCaptured += (count > 0) ? count : 1;
281 cam->singleShotStartMs = 0;
285 cam->image_interval = 0.0f;
286 cam->singleShotStartMs = QDateTime::currentMSecsSinceEpoch();
289 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"image capture started"
290 <<
"interval:" << interval <<
"count:" << count;
291 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
293 _sendCameraCaptureStatus(targetCompId);
295 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
299 case MAV_CMD_IMAGE_STOP_CAPTURE:
300 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_IMAGE) {
302 cam->image_interval = 0.0f;
303 cam->singleShotStartMs = 0;
304 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"image capture stopped";
305 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
306 _sendCameraCaptureStatus(targetCompId);
308 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
312 case MAV_CMD_VIDEO_START_CAPTURE:
313 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_VIDEO) {
314 if ((cam->capFlags & CAMERA_CAP_FLAGS_HAS_MODES) &&
315 (cam->cameraMode == CAMERA_MODE_IMAGE) &&
316 !(cam->capFlags & CAMERA_CAP_FLAGS_CAN_CAPTURE_VIDEO_IN_IMAGE_MODE)) {
317 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
321 cam->recording =
true;
322 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"video recording started";
323 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
324 _sendCameraCaptureStatus(targetCompId);
326 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
330 case MAV_CMD_VIDEO_STOP_CAPTURE:
331 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_VIDEO) {
332 cam->recording =
false;
333 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"video recording stopped";
334 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
335 _sendCameraCaptureStatus(targetCompId);
337 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
341 case MAV_CMD_STORAGE_FORMAT:
342 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"storage formatted";
343 cam->imagesCaptured = 0;
345 cam->image_interval = 0.0f;
346 cam->singleShotStartMs = 0;
347 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
348 _sendStorageInformation(targetCompId);
351 case MAV_CMD_SET_CAMERA_ZOOM:
352 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_BASIC_ZOOM) {
355 if (
static_cast<int>(request.param1) == ZOOM_TYPE_RANGE) {
356 cam->zoomLevel = request.param2;
357 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"zoom set to" << cam->zoomLevel;
361 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
363 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
367 case MAV_CMD_SET_CAMERA_FOCUS:
368 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
371 case MAV_CMD_RESET_CAMERA_SETTINGS:
372 cam->cameraMode = CAMERA_MODE_IMAGE;
373 cam->zoomLevel = 1.0f;
374 cam->focusLevel = 0.0f;
376 cam->image_interval = 0.0f;
377 cam->singleShotStartMs = 0;
378 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"settings reset";
379 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
380 _sendCameraSettings(targetCompId);
383 case MAV_CMD_CAMERA_TRACK_POINT:
384 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_TRACKING_POINT) {
385 cam->trackingMode = CAMERA_TRACKING_MODE_POINT;
386 cam->trackPointX = request.param1;
387 cam->trackPointY = request.param2;
388 cam->trackRadius = request.param3;
389 cam->trackAnchorX = request.param1;
390 cam->trackAnchorY = request.param2;
391 cam->trackingStartMs = QDateTime::currentMSecsSinceEpoch();
392 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"tracking point"
393 << cam->trackPointX << cam->trackPointY <<
"radius" << cam->trackRadius;
394 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
396 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
400 case MAV_CMD_CAMERA_TRACK_RECTANGLE:
401 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_TRACKING_RECTANGLE) {
402 cam->trackingMode = CAMERA_TRACKING_MODE_RECTANGLE;
403 cam->trackRecTopX = request.param1;
404 cam->trackRecTopY = request.param2;
405 cam->trackRecBottomX = request.param3;
406 cam->trackRecBottomY = request.param4;
407 cam->trackAnchorX = (request.param1 + request.param3) / 2.0f;
408 cam->trackAnchorY = (request.param2 + request.param4) / 2.0f;
409 cam->trackingStartMs = QDateTime::currentMSecsSinceEpoch();
410 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"tracking rectangle"
411 << cam->trackRecTopX << cam->trackRecTopY
412 <<
"->" << cam->trackRecBottomX << cam->trackRecBottomY;
413 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
415 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
419 case MAV_CMD_CAMERA_STOP_TRACKING:
420 cam->trackingMode = CAMERA_TRACKING_MODE_NONE;
421 cam->trackingStatusIntervalUs = -1;
422 cam->trackingStatusLastSentMs = 0;
423 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"tracking stopped";
424 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
427 case MAV_CMD_SET_MESSAGE_INTERVAL:
429 const int msgId =
static_cast<int>(request.param1);
430 if (msgId == MAVLINK_MSG_ID_CAMERA_TRACKING_IMAGE_STATUS) {
431 cam->trackingStatusIntervalUs =
static_cast<qint64
>(request.param2);
432 cam->trackingStatusLastSentMs = 0;
433 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId
434 <<
"tracking status interval" << cam->trackingStatusIntervalUs <<
"us";
435 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
438 _sendCommandAck(targetCompId, request.command, MAV_RESULT_UNSUPPORTED);
451 const CameraState *cam = _findCamera(targetCompId);
456 const int msgId =
static_cast<int>(request.param1);
459 case MAVLINK_MSG_ID_CAMERA_INFORMATION:
460 _sendCameraInformation(targetCompId);
461 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
464 case MAVLINK_MSG_ID_CAMERA_SETTINGS:
465 _sendCameraSettings(targetCompId);
466 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
469 case MAVLINK_MSG_ID_STORAGE_INFORMATION:
470 _sendStorageInformation(targetCompId);
471 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
474 case MAVLINK_MSG_ID_CAMERA_CAPTURE_STATUS:
475 _sendCameraCaptureStatus(targetCompId);
476 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
479 case MAVLINK_MSG_ID_VIDEO_STREAM_INFORMATION:
481 if (!(cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM)) {
482 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_DENIED, msgId);
485 const uint8_t streamId =
static_cast<uint8_t
>(request.param2);
487 for (uint8_t s = 1; s <= kNumStreams; s++) {
488 _sendVideoStreamInformation(targetCompId, s);
491 _sendVideoStreamInformation(targetCompId, streamId);
493 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
497 case MAVLINK_MSG_ID_VIDEO_STREAM_STATUS:
499 if (!(cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM)) {
500 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_DENIED, msgId);
503 const uint8_t streamId =
static_cast<uint8_t
>(request.param2);
505 for (uint8_t s = 1; s <= kNumStreams; s++) {
506 _sendVideoStreamStatus(targetCompId, s);
509 _sendVideoStreamStatus(targetCompId, streamId);
511 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
519 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_DENIED, msgId);
524void MockLinkCamera::_sendCameraInformation(uint8_t compId)
526 const CameraState *cam = _findCamera(compId);
531 const int cameraIndex = compId - MAV_COMP_ID_CAMERA;
533 const uint8_t vendorName[32] =
"MockLink";
534 const char cameraDefinitionUri[MAVLINK_MSG_CAMERA_INFORMATION_FIELD_CAM_DEFINITION_URI_LEN] = {};
535 const QString model = QStringLiteral(
"MockCam %1").arg(cameraIndex + 1);
536 QByteArray modelBA = model.toLocal8Bit();
537 modelBA.resize(MAVLINK_MSG_CAMERA_INFORMATION_FIELD_MODEL_NAME_LEN);
540 (void) mavlink_msg_camera_information_pack_chan(
547 reinterpret_cast<const uint8_t *
>(modelBA.constData()),
562 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_INFORMATION for compId:" << compId <<
"model:" << model;
565void MockLinkCamera::_sendCameraSettings(uint8_t compId)
567 const CameraState *cam = _findCamera(compId);
573 (void) mavlink_msg_camera_settings_pack_chan(
585 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_SETTINGS for compId:" << compId
586 <<
"mode:" << cam->cameraMode
587 <<
"zoom:" << cam->zoomLevel
588 <<
"focus:" << cam->focusLevel;
591void MockLinkCamera::_sendStorageInformation(uint8_t compId)
593 const char storageName[MAVLINK_MSG_STORAGE_INFORMATION_FIELD_NAME_LEN] = {};
596 (void) mavlink_msg_storage_information_pack_chan(
604 STORAGE_STATUS_READY,
605 static_cast<float>(kStorageTotalMiB),
606 static_cast<float>(kStorageTotalMiB - kStorageFreeMiB),
607 static_cast<float>(kStorageFreeMiB),
615 qCDebug(MockLinkCameraLog) <<
"Sent STORAGE_INFORMATION for compId:" << compId;
618void MockLinkCamera::_sendCameraCaptureStatus(uint8_t compId)
620 const CameraState *cam = _findCamera(compId);
626 (void) mavlink_msg_camera_capture_status_pack_chan(
633 cam->recording ? 1 : 0,
636 static_cast<float>(kStorageFreeMiB),
641 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_CAPTURE_STATUS for compId:" << compId
642 <<
"status:" << _imageCaptureStatusToString(cam->image_status)
643 <<
"interval:" << cam->image_interval
644 <<
"recording:" << cam->recording
645 <<
"images:" << cam->imagesCaptured;
648void MockLinkCamera::_sendCameraImageCaptured(uint8_t compId)
650 const CameraState *cam = _findCamera(compId);
657 const int32_t lat =
static_cast<int32_t
>(_mockLink->
vehicleLatitude() * 1e7);
658 const int32_t lon =
static_cast<int32_t
>(_mockLink->
vehicleLongitude() * 1e7);
660 const float q[4] = {1.0f, 0.0f, 0.0f, 0.0f};
661 const char fileUrl[MAVLINK_MSG_CAMERA_IMAGE_CAPTURED_FIELD_FILE_URL_LEN] = {};
664 (void) mavlink_msg_camera_image_captured_pack_chan(
671 (compId - MAV_COMP_ID_CAMERA) + 1,
682 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_IMAGE_CAPTURED for compId:" << compId
683 <<
"index:" << cam->imagesCaptured;
686void MockLinkCamera::_sendVideoStreamInformation(uint8_t compId, uint8_t streamId)
688 const int cameraIndex = compId - MAV_COMP_ID_CAMERA;
689 const QString name = QStringLiteral(
"Stream %1-%2").arg(cameraIndex + 1).arg(streamId);
690 QByteArray nameBA = name.toLocal8Bit();
691 nameBA.resize(MAVLINK_MSG_VIDEO_STREAM_INFORMATION_FIELD_NAME_LEN);
696 uint8_t streamType = VIDEO_STREAM_TYPE_RTPUDP;
697 uint8_t encoding = VIDEO_STREAM_ENCODING_H264;
698 QString uri = QStringLiteral(
"udp://127.0.0.1:5600");
699 uint16_t flags = VIDEO_STREAM_STATUS_FLAGS_RUNNING;
704 switch (servedType) {
706 streamType = VIDEO_STREAM_TYPE_RTPUDP;
707 encoding = VIDEO_STREAM_ENCODING_H264;
711 streamType = VIDEO_STREAM_TYPE_RTPUDP;
712 encoding = VIDEO_STREAM_ENCODING_H265;
716 streamType = VIDEO_STREAM_TYPE_RTSP;
717 encoding = VIDEO_STREAM_ENCODING_H264;
721 streamType = VIDEO_STREAM_TYPE_MPEG_TS;
722 encoding = VIDEO_STREAM_ENCODING_H264;
726 streamType = VIDEO_STREAM_TYPE_TCP_MPEG;
727 encoding = VIDEO_STREAM_ENCODING_H264;
731#ifdef QGC_GST_STREAMING
744 QByteArray uriBA = uri.toLocal8Bit();
745 uriBA.resize(MAVLINK_MSG_VIDEO_STREAM_INFORMATION_FIELD_URI_LEN);
748 (void) mavlink_msg_video_stream_information_pack_chan(
769 qCDebug(MockLinkCameraLog) <<
"Sent VIDEO_STREAM_INFORMATION for compId:" << compId <<
"stream:" << streamId
770 <<
"type:" << streamType <<
"uri:" << uri;
773void MockLinkCamera::_sendVideoStreamStatus(uint8_t compId, uint8_t streamId)
778 uint16_t flags = VIDEO_STREAM_STATUS_FLAGS_RUNNING;
779#ifdef QGC_GST_STREAMING
790 (void) mavlink_msg_video_stream_status_pack_chan(
806 qCDebug(MockLinkCameraLog) <<
"Sent VIDEO_STREAM_STATUS for compId:" << compId <<
"stream:" << streamId;
809void MockLinkCamera::_sendCameraTrackingImageStatus(uint8_t compId)
811 const CameraState *cam = _findCamera(compId);
812 if (!cam || cam->trackingMode == CAMERA_TRACKING_MODE_NONE) {
817 (void) mavlink_msg_camera_tracking_image_status_pack_chan(
822 CAMERA_TRACKING_STATUS_FLAGS_ACTIVE,
824 CAMERA_TRACKING_TARGET_DATA_EMBEDDED,
830 cam->trackRecBottomX,
831 cam->trackRecBottomY,
836void MockLinkCamera::_sendCommandAck(uint8_t compId, uint16_t command, uint8_t result,
int requestedMsgId)
839 (void) mavlink_msg_command_ack_pack_chan(
853 QString logMsg = QStringLiteral(
"Sent COMMAND_ACK for compId: %1 command: %2 result: %3")
854 .arg(compId).arg(commandName).arg(result);
856 if (command == MAV_CMD_REQUEST_MESSAGE && requestedMsgId >= 0) {
857 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(
static_cast<uint32_t
>(requestedMsgId));
858 QString msgName = info ? info->name : QString::number(requestedMsgId);
859 logMsg += QStringLiteral(
" requestedMsg: %1").arg(msgName);
862 qCDebug(MockLinkCameraLog) << logMsg;
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_command_long_t mavlink_command_long_t
static MissionCommandTree * instance()
QString rawName(MAV_CMD command) const
Returns the raw name for the specified command.
@ VideoStreamRtpUdpH265
RTP/UDP H.265 -> udp265://.
@ VideoStreamNone
No stream served.
@ VideoStreamRtpUdpH264
RTP/UDP H.264 -> udp://.
@ VideoStreamRtspH264
RTSP H.264 -> rtsp://.
@ VideoStreamMpegTsTcp
MPEG-TS over TCP -> tcp://.
@ VideoStreamMpegTsUdp
MPEG-TS over UDP -> mpegts://.
Simulates MAVLink Camera Protocol v2 components for MockLink.
void sendCameraHeartbeats()
Send heartbeats for all simulated camera components (call from 1Hz tasks)
bool handleMavlinkMessage(const mavlink_message_t &msg)
void run10HzTasks()
Update camera states (call from 10Hz tasks)
@ ImageCaptureInProgress
Single image capture in progress.
@ ImageCaptureInterval
Interval capture enabled.
@ ImageCaptureIntervalCapture
Interval capture with capture in progress.
@ ImageCaptureIdle
No capture in progress.
void servedVideoStream(MockConfiguration::VideoStreamType &type, QString &uri) const
double vehicleAltitudeAMSL() const
uint8_t outgoingMavlinkChannel() const
Vehicle-side channel used to encode outgoing (mock vehicle -> QGC) messages. Signing state lives here...
void respondWithMavlinkMessage(const mavlink_message_t &msg)
Sends the specified mavlink message to QGC.
double vehicleLatitude() const
MockConfiguration::VideoStreamType requestedVideoStreamType() const
Video stream type the configuration requested (immutable after construction).
double vehicleLongitude() const
Per-camera simulated state.
qint64 trackingStatusLastSentMs
Timestamp of last tracking status message.
float trackAnchorX
Original center X of tracked target.
qint64 singleShotStartMs
Timestamp when single-shot capture started (0 = not active)
qint64 trackingStatusIntervalUs
Interval for CAMERA_TRACKING_IMAGE_STATUS (-1 = disabled)
qint64 trackingStartMs
Timestamp when tracking was started (for drift animation)
uint8_t trackingMode
CAMERA_TRACKING_MODE enum.
float trackAnchorY
Original center Y of tracked target.
uint8_t image_status
ImageCaptureStatus enum.