diff --git a/bsp_q7s/devices/startracker/StarTrackerDefinitions.h b/bsp_q7s/devices/startracker/StarTrackerDefinitions.h index 6ea8d6f7..e74d8a51 100644 --- a/bsp_q7s/devices/startracker/StarTrackerDefinitions.h +++ b/bsp_q7s/devices/startracker/StarTrackerDefinitions.h @@ -90,10 +90,15 @@ static const DeviceCommandId_t BOOT = 1; static const DeviceCommandId_t REQ_VERSION = 2; static const DeviceCommandId_t REQ_INTERFACE = 3; static const DeviceCommandId_t REQ_TIME = 4; +static const DeviceCommandId_t ERASE = 5; +static const DeviceCommandId_t UNLOCK = 6; static const DeviceCommandId_t REBOOT = 7; static const DeviceCommandId_t DOWNLOAD_IMAGE = 9; static const DeviceCommandId_t UPLOAD_IMAGE = 10; static const DeviceCommandId_t REQ_POWER = 11; +static const DeviceCommandId_t TAKE_IMAGE = 15; +static const DeviceCommandId_t DOWNLOAD_CENTROID = 16; +static const DeviceCommandId_t UPLOAD_CENTROID = 17; static const DeviceCommandId_t SUBSCRIBE_TO_TM = 18; static const DeviceCommandId_t REQ_SOLUTION = 24; static const DeviceCommandId_t REQ_TEMPERATURE = 25; @@ -107,6 +112,11 @@ static const DeviceCommandId_t MATCHING = 46; static const DeviceCommandId_t TRACKING = 47; static const DeviceCommandId_t VALIDATION = 48; static const DeviceCommandId_t ALGO = 49; +static const DeviceCommandId_t CHECKSUM = 50; +static const DeviceCommandId_t READ = 51; +static const DeviceCommandId_t WRITE = 52; +static const DeviceCommandId_t DOWNLOAD_MATCHED_STAR = 53; +static const DeviceCommandId_t DOWNLOAD_DB_IMAGE = 54; static const DeviceCommandId_t NONE = 0xFFFFFFFF; static const uint32_t VERSION_SET_ID = REQ_VERSION; @@ -149,6 +159,12 @@ namespace ID { static const uint8_t SOLUTION = 24; static const uint8_t TEMPERATURE = 25; static const uint8_t TIME = 1; + static const uint8_t WRITE = 2; + static const uint8_t READ = 3; + static const uint8_t CHECKSUM = 4; + static const uint8_t ERASE = 5; + static const uint8_t UNLOCK = 6; + static const uint8_t TAKE_IMAGE = 15; } /** diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp index d0a926a0..9244b967 100644 --- a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp @@ -86,7 +86,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu return EXECUTION_FINISHED; } case(StarTracker::DOWNLOAD_IMAGE): { - strImageLoader->startImageDownload(); + strImageLoader->startImageDownload(std::string(reinterpret_cast(data), size)); imageLoaderExecuting = true; return EXECUTION_FINISHED; } @@ -167,12 +167,6 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi prepareInterfaceRequest(); return RETURN_OK; } - case (StarTracker::UPLOAD_IMAGE): { - std::string uploadImage = std::string(reinterpret_cast(commandData), - commandDataLen); - strImageLoader->startImageUpload(uploadImage); - return result; - } case (StarTracker::REQ_POWER): { preparePowerRequest(); return RETURN_OK; @@ -181,6 +175,10 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi prepareRebootCommand(); return RETURN_OK; } + case (StarTracker::TAKE_IMAGE): { + prepareTakeImageCommand(); + return RETURN_OK; + } case (StarTracker::SUBSCRIBE_TO_TM): { prepareSubscriptionCommand(commandData); return RETURN_OK; @@ -261,6 +259,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() { this->insertInCommandAndReplyMap(StarTracker::REQ_TIME, 3, &timeSet, StarTracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandMap(StarTracker::UPLOAD_IMAGE); + this->insertInCommandMap(StarTracker::DOWNLOAD_IMAGE); this->insertInCommandAndReplyMap(StarTracker::REQ_POWER, 3, &powerSet, StarTracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(StarTracker::REQ_INTERFACE, 3, &interfaceSet, @@ -293,6 +292,8 @@ void StarTrackerHandler::fillCommandAndReplyMap() { StarTracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(StarTracker::ALGO, 3, nullptr, StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::TAKE_IMAGE, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); } ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t *start, size_t remainingSize, @@ -365,6 +366,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, con result = handleActionReply(); break; } + case (StarTracker::TAKE_IMAGE): { + result = handleActionReply(); + break; + } case (StarTracker::REQ_VERSION): { result = handleVersionTm(); break; @@ -522,6 +527,10 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t *foundId) *foundId = StarTracker::BOOT; break; } + case (StarTracker::ID::TAKE_IMAGE): { + *foundId = StarTracker::TAKE_IMAGE; + break; + } case (StarTracker::ID::UPLOAD_IMAGE): { *foundId = StarTracker::UPLOAD_IMAGE; break; @@ -701,6 +710,15 @@ void StarTrackerHandler::prepareRebootCommand() { rawPacketLen = dataLinkLayer.getEncodedLength(); } +void StarTrackerHandler::prepareTakeImageCommand() { + uint32_t length = 0; + struct CameraActionRequest camReq; + arc_pack_camera_action_req(&camReq, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + void StarTrackerHandler::prepareSubscriptionCommand(const uint8_t* tmId) { uint32_t length = 18; commandBuffer[0] = TMTC_SETPARAMREQ; diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.h b/bsp_q7s/devices/startracker/StarTrackerHandler.h index 3f3c8197..5c7de4fa 100644 --- a/bsp_q7s/devices/startracker/StarTrackerHandler.h +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.h @@ -183,6 +183,11 @@ private: */ void prepareBootCommand(); + /** + * @brief Fills the command buffer with the command to take an image. + */ + void prepareTakeImageCommand(); + /** * @brief Fills command buffer with data to request the version telemetry packet */ diff --git a/bsp_q7s/devices/startracker/StrImageLoader.cpp b/bsp_q7s/devices/startracker/StrImageLoader.cpp index 9d49d8bf..998d3f1c 100644 --- a/bsp_q7s/devices/startracker/StrImageLoader.cpp +++ b/bsp_q7s/devices/startracker/StrImageLoader.cpp @@ -37,6 +37,11 @@ ReturnValue_t StrImageLoader::performOperation(uint8_t operationCode) { break; } case InternalState::DOWNLOAD_IMAGE: + result = performImageDownload(); + if (result == RETURN_OK){ + triggerEvent(IMAGE_DOWNLOAD_SUCCESSFUL); + } + internalState = InternalState::IDLE; break; } } @@ -51,7 +56,6 @@ void StrImageLoader::setComCookie(CookieIF* comCookie_) { } ReturnValue_t StrImageLoader::startImageUpload(std::string image) { - // Check if file is stored on SD card and if associated SD card is mounted if (image.substr(0, sizeof(SdCardManager::SD_0_MOUNT_POINT)) == std::string(SdCardManager::SD_0_MOUNT_POINT)) { @@ -66,31 +70,58 @@ ReturnValue_t StrImageLoader::startImageUpload(std::string image) { return SD_NOT_MOUNTED; } } - uploadImage = image; - if(not std::filesystem::exists(uploadImage)) { return FILE_NOT_EXISTS; } - internalState = InternalState::UPLOAD_IMAGE; - semaphore.release(); - return RETURN_OK; } -ReturnValue_t StrImageLoader::startImageDownload() { +void StrImageLoader::startImageDownload(std::string downloadImage_) { + downloadImage = downloadImage_; + internalState = InternalState::DOWNLOAD_IMAGE; + semaphore.release(); +} + +ReturnValue_t StrImageLoader::performImageDownload() { + ReturnValue_t result; + struct DownloadActionRequest downloadReq; + uint32_t size = 0; + std::ofstream file(downloadImage, std::ios_base::app | std::ios_base::out); + while(downloadReq.position < LAST_POSITION) { + arc_pack_download_action_req(&downloadReq, commandBuffer, &size); + result = sendAndRead(size, downloadReq.position); + if (result != RETURN_OK) { + file.close(); + return result; + } + result = checkReply(); + if (result != RETURN_OK) { + file.close(); + return result; + } + result = checkReplyPosition(downloadReq.position); + if (result != RETURN_OK) { + file.close(); + return result; + } + file.write(reinterpret_cast(datalinkLayer.getReply() + DATA_OFFSET), + IMAGE_DATA_SIZE); + downloadReq.position++; + } + file.close(); return RETURN_OK; } ReturnValue_t StrImageLoader::performImageUpload() { ReturnValue_t result = RETURN_OK; + uint32_t size = 0; uint32_t imageSize = 0; struct UploadActionRequest uploadReq; uploadReq.position = 0; std::memset(&uploadReq.data, 0, sizeof(uploadReq.data)); - if (not std::filesystem::exists(uploadImage)) { triggerEvent(IMAGE_FILE_NOT_EXISTS, uploadReq.position); internalState = InternalState::IDLE; @@ -101,57 +132,51 @@ ReturnValue_t StrImageLoader::performImageUpload() { file.seekg(0, file.end); // tellg returns position of character in input stream imageSize = file.tellg(); - // Set position of next character to beginning of file input stream - file.seekg(0, file.beg); - if (imageSize >= SIZE_IMAGE_PART) { + while((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) { + file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg); file.read(reinterpret_cast(uploadReq.data), SIZE_IMAGE_PART); - } - else { - file.read(reinterpret_cast(uploadReq.data), imageSize); - } - while(uploadReq.position * SIZE_IMAGE_PART < imageSize) { - result = uploadSendAndRead(&uploadReq); + arc_pack_upload_action_req(&uploadReq, commandBuffer, &size); + result = sendAndRead(size, uploadReq.position); if (result != RETURN_OK) { return RETURN_FAILED; } - result = checkUploadReply(); + result = checkReply(); if (result != RETURN_OK) { return result; } uploadReq.position++; - file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg); } std::memset(uploadReq.data, 0, sizeof(uploadReq.data)); uint32_t remainder = imageSize - uploadReq.position * SIZE_IMAGE_PART; + file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg); file.read(reinterpret_cast(uploadReq.data), remainder); file.close(); uploadReq.position++; - result = uploadSendAndRead(&uploadReq); + arc_pack_upload_action_req(&uploadReq, commandBuffer, &size); + result = sendAndRead(size, uploadReq.position); if (result != RETURN_OK) { return RETURN_FAILED; } - result = checkUploadReply(); + result = checkReply(); if (result != RETURN_OK) { return result; } return RETURN_OK; } -ReturnValue_t StrImageLoader::uploadSendAndRead(struct UploadActionRequest* uploadReq) { +ReturnValue_t StrImageLoader::sendAndRead(size_t size, uint32_t position) { ReturnValue_t result = RETURN_OK; ReturnValue_t decResult = RETURN_OK; size_t receivedDataLen = 0; uint8_t *receivedData = nullptr; size_t bytesLeft = 0; - uint32_t size = 0; uint32_t missedReplies = 0; - arc_pack_upload_action_req(uploadReq, commandBuffer, &size); datalinkLayer.encodeFrame(commandBuffer, size); result = communicationInterface->sendMessage(comCookie, datalinkLayer.getEncodedFrame(), datalinkLayer.getEncodedLength()); if (result != RETURN_OK) { - sif::warning << "StrImageLoader::uploadImage: Failed to send upload packet" << std::endl; - triggerEvent(SENDING_UPLOAD_PACKET_FAILED, result, uploadReq->position); + sif::warning << "StrImageLoader::sendAndRead: Failed to send packet" << std::endl; + triggerEvent(IMG_LOADER_SENDING_PACKET_FAILED, result, position); return RETURN_FAILED; } decResult = ArcsecDatalinkLayer::DEC_IN_PROGRESS; @@ -159,14 +184,14 @@ ReturnValue_t StrImageLoader::uploadSendAndRead(struct UploadActionRequest* uplo result = communicationInterface->requestReceiveMessage(comCookie, StarTracker::MAX_FRAME_SIZE * 2 + 2); if (result != RETURN_OK) { - sif::warning << "StrImageLoader::uploadImage: Failed to request reply" << std::endl; - triggerEvent(UPLOAD_REQUESTING_MSG_FAILED, result, uploadReq->position); + sif::warning << "StrImageLoader::sendAndRead: Failed to request reply" << std::endl; + triggerEvent(IMG_LOADER_REQUESTING_MSG_FAILED, result, position); return RETURN_FAILED; } result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); if (result != RETURN_OK) { - sif::warning << "StrImageLoader::uploadImage: Failed to read received message" << std::endl; - triggerEvent(UPLOAD_READING_REPLY_FAILED, result, uploadReq->position); + sif::warning << "StrImageLoader::sendAndRead: Failed to read received message" << std::endl; + triggerEvent(IMG_LOADER_READING_REPLY_FAILED, result, position); return RETURN_FAILED; } if (receivedDataLen == 0 && missedReplies < MAX_POLLS) { @@ -174,7 +199,7 @@ ReturnValue_t StrImageLoader::uploadSendAndRead(struct UploadActionRequest* uplo continue; } else if ((receivedDataLen == 0) && (missedReplies >= MAX_POLLS)) { - triggerEvent(NO_REPLY, uploadReq->position); + triggerEvent(IMG_LOADER_NO_REPLY, position); return RETURN_FAILED; } else { @@ -183,22 +208,22 @@ ReturnValue_t StrImageLoader::uploadSendAndRead(struct UploadActionRequest* uplo decResult = datalinkLayer.decodeFrame(receivedData, receivedDataLen, &bytesLeft); if (bytesLeft != 0) { // This should never happen - sif::warning << "StrImageLoader::uploadSendAndRead: Bytes left after decoding" << std::endl; - triggerEvent(UPLOAD_COM_ERROR, result, uploadReq->position); + sif::warning << "StrImageLoader::sendAndRead: Bytes left after decoding" << std::endl; + triggerEvent(IMG_LOADER_COM_ERROR, result, position); return RETURN_FAILED; } } if (decResult != RETURN_OK) { - triggerEvent(DEC_ERROR, decResult, uploadReq->position); + triggerEvent(IMG_LOADER_DEC_ERROR, decResult, position); return RETURN_FAILED; } return RETURN_OK; } -ReturnValue_t StrImageLoader::checkUploadReply() { +ReturnValue_t StrImageLoader::checkReply() { uint8_t type = datalinkLayer.getReplyFrameType(); if (type != TMTC_ACTIONREPLY) { - sif::warning << "StrImageLoader::checkUploadReply: Received invalid upload reply" + sif::warning << "StrImageLoader::checkUploadReply: Received reply with invalid type ID" << std::endl; triggerEvent(INVALID_TYPE_ID); return RETURN_FAILED; @@ -211,3 +236,13 @@ ReturnValue_t StrImageLoader::checkUploadReply() { } return RETURN_OK; } + +ReturnValue_t StrImageLoader::checkReplyPosition(uint32_t expectedPosition) { + uint32_t receivedPosition = 0; + std::memcpy(&receivedPosition, datalinkLayer.getReply() + POS_OFFSET, sizeof(receivedPosition)); + if (receivedPosition != expectedPosition) { + triggerEvent(POSITION_MISMATCH, receivedPosition); + return RETURN_FAILED; + } + return RETURN_OK; +} diff --git a/bsp_q7s/devices/startracker/StrImageLoader.h b/bsp_q7s/devices/startracker/StrImageLoader.h index e53e57d1..2f486658 100644 --- a/bsp_q7s/devices/startracker/StrImageLoader.h +++ b/bsp_q7s/devices/startracker/StrImageLoader.h @@ -29,35 +29,40 @@ public: //! [EXPORT] : [COMMENT] Try to upload image but specified image does not exist static const Event IMAGE_FILE_NOT_EXISTS = MAKE_EVENT(0, severity::LOW); - //! [EXPORT] : [COMMENT] Sending image upload packet to star tracker failed + //! [EXPORT] : [COMMENT] Sending packet (download or upload) to star tracker failed //!P1: Return code of communication interface sendMessage function - //!P2: Position of upload packet for which the transmission failed - static const Event SENDING_UPLOAD_PACKET_FAILED = MAKE_EVENT(1, severity::LOW); + //!P2: Position of upload/download packet for which the transmission failed + static const Event IMG_LOADER_SENDING_PACKET_FAILED = MAKE_EVENT(1, severity::LOW); //! [EXPORT] : [COMMENT] Communication interface requesting reply failed //!P1: Return code of failed request - //!P1: Upload position for which the request failed - static const Event UPLOAD_REQUESTING_MSG_FAILED = MAKE_EVENT(2, severity::LOW); + //!P1: Upload/download position for which the request failed + static const Event IMG_LOADER_REQUESTING_MSG_FAILED = MAKE_EVENT(2, severity::LOW); //! [EXPORT] : [COMMENT] Uploading image to star tracker was successful static const Event IMAGE_UPLOAD_SUCCESSFUL = MAKE_EVENT(3, severity::LOW); //! [EXPORT] : [COMMENT] Failed to read communication interface reply data //!P1: Return code of failed communication interface read call - //!P1: Upload position for which the read call failed - static const Event UPLOAD_READING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW); + //!P1: Upload/download position for which the read call failed + static const Event IMG_LOADER_READING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW); //! [EXPORT] : [COMMENT] Unexpected stop of decoding sequence //!P1: Return code of failed communication interface read call - //!P1: Upload position for which the read call failed - static const Event UPLOAD_COM_ERROR = MAKE_EVENT(5, severity::LOW); + //!P1: Upload/download position for which the read call failed + static const Event IMG_LOADER_COM_ERROR = MAKE_EVENT(5, severity::LOW); //! [EXPORT] : [COMMENT] Star tracker did not send replies (maybe device is powered off) - //!P1: Position of upload packet for which no reply was sent - static const Event NO_REPLY = MAKE_EVENT(6, severity::LOW); + //!P1: Position of upload or download packet for which no reply was sent + static const Event IMG_LOADER_NO_REPLY = MAKE_EVENT(6, severity::LOW); //! [EXPORT] : [COMMENT] Received reply with invalid type ID static const Event INVALID_TYPE_ID = MAKE_EVENT(7, severity::LOW); //! [EXPORT] : [COMMENT] Status field in reply signals error static const Event STATUS_ERROR = MAKE_EVENT(8, severity::LOW); //! [EXPORT] : [COMMENT] Error during decoding of received reply occurred //P1: Return value of decoding function - //P2: Position of upload packet for which reply decoding failed - static const Event DEC_ERROR = MAKE_EVENT(9, severity::LOW); + //P2: Position of upload/download packet for which reply decoding failed + static const Event IMG_LOADER_DEC_ERROR = MAKE_EVENT(9, severity::LOW); + //! [EXPORT] : [COMMENT] Image download was successful + static const Event IMAGE_DOWNLOAD_SUCCESSFUL = MAKE_EVENT(10, severity::LOW); + //! [EXPORT] : [COMMENT] Position mismatch + //! P1: The expected position and thus the position for which the image upload/download failed + static const Event POSITION_MISMATCH = MAKE_EVENT(11, severity::LOW); StrImageLoader(object_id_t objectId); @@ -80,7 +85,7 @@ public: /** * @brief Calling this function initiates the download of an image from the star tracker. */ - ReturnValue_t startImageDownload(); + void startImageDownload(std::string downloadImage_); private: @@ -94,8 +99,14 @@ private: // Size of one image part which can be sent per action request static const size_t SIZE_IMAGE_PART = 1024; + static const uint32_t LAST_POSITION = 4095; + static const uint32_t MAX_POLLS = 10000; + static const uint8_t POS_OFFSET = 2; + static const uint8_t DATA_OFFSET = 5; + static const size_t IMAGE_DATA_SIZE = 1024; + enum class InternalState { IDLE, UPLOAD_IMAGE, @@ -108,8 +119,10 @@ private: BinarySemaphore semaphore; - // Absolute path and name to image to upload + // Name including absolute path of image to upload std::string uploadImage; + // Name including the absolute path of downloaded image + std::string downloadImage; SdCardManager* sdcMan = nullptr; @@ -132,21 +145,33 @@ private: ReturnValue_t performImageUpload(); /** - * @brief Sends a upload image packet and receives the action reply. - * - * @param uploadReq Pointer to upload request structure to send - * - * @return RETURN_OK if successful, otherwise RETURN_FALIED + * @bried Performs download of last taken image from the star tracker. */ - ReturnValue_t uploadSendAndRead(struct UploadActionRequest* uploadReq); + ReturnValue_t performImageDownload(); /** - * @brief Checks the reply to an upload action request + * @brief Sends packet to the star tracker and reads reply by using the communication + * interface * - * @return RETURN_OK if reply confirms success of upload packet transfer, otherwise - * REUTRN_FAILED + * @return RETURN_OK if successful, otherwise RETURN_FAILED */ - ReturnValue_t checkUploadReply(); + ReturnValue_t sendAndRead(size_t size, uint32_t position); + + /** + * @brief Checks the reply header (type id and status fields) + * + * @return RETURN_OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED + */ + ReturnValue_t checkReply(); + + /** + * @brief Checks the position field in a star tracker reply. + * + * @param expectedPosition Value of expected position + * + * @return RETURN_OK if received position matches expected position, otherwise RETURN_FAILED + */ + ReturnValue_t checkReplyPosition(uint32_t expectedPosition); }; #endif /* BSP_Q7S_DEVICES_STRIMAGELOADER_H_ */