2021-11-30 16:01:02 +01:00
|
|
|
#include "StrImageLoader.h"
|
|
|
|
|
2021-12-06 19:36:21 +01:00
|
|
|
#include <fstream>
|
2021-11-30 16:01:02 +01:00
|
|
|
#include <filesystem>
|
|
|
|
|
2021-12-06 19:36:21 +01:00
|
|
|
StrImageLoader::StrImageLoader(object_id_t objectId) : SystemObject(objectId){
|
2021-11-30 16:01:02 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StrImageLoader::~StrImageLoader() {
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t StrImageLoader::initialize() {
|
|
|
|
sdcMan = SdCardManager::instance();
|
|
|
|
if (sdcMan == nullptr) {
|
|
|
|
sif::warning << "StrImageLoader::initialize: Invalid SD Card Manager" << std::endl;
|
2021-12-06 19:36:21 +01:00
|
|
|
return RETURN_FAILED;
|
2021-11-30 16:01:02 +01:00
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
return RETURN_OK;
|
2021-11-30 16:01:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t StrImageLoader::performOperation(uint8_t operationCode) {
|
2021-12-02 08:05:33 +01:00
|
|
|
ReturnValue_t result = RETURN_OK;
|
2021-11-30 16:01:02 +01:00
|
|
|
semaphore.acquire();
|
|
|
|
while(true) {
|
|
|
|
switch(internalState) {
|
2021-12-02 08:05:33 +01:00
|
|
|
case InternalState::IDLE: {
|
2021-11-30 16:01:02 +01:00
|
|
|
semaphore.acquire();
|
|
|
|
break;
|
2021-12-02 08:05:33 +01:00
|
|
|
}
|
|
|
|
case InternalState::UPLOAD_IMAGE: {
|
2021-12-06 19:36:21 +01:00
|
|
|
result = performImageUpload();
|
2021-12-02 08:05:33 +01:00
|
|
|
if (result == RETURN_OK){
|
|
|
|
triggerEvent(IMAGE_UPLOAD_SUCCESSFUL);
|
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
internalState = InternalState::IDLE;
|
2021-11-30 16:01:02 +01:00
|
|
|
break;
|
2021-12-02 08:05:33 +01:00
|
|
|
}
|
2021-11-30 16:01:02 +01:00
|
|
|
case InternalState::DOWNLOAD_IMAGE:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StrImageLoader::setComIF(DeviceCommunicationIF* communicationInterface_) {
|
|
|
|
communicationInterface = communicationInterface_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StrImageLoader::setComCookie(CookieIF* comCookie_) {
|
|
|
|
comCookie = 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)) {
|
|
|
|
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
|
|
|
|
sif::warning << "StrImageLoader::getImageLocation: SD card 0 not mounted" << std::endl;
|
|
|
|
return SD_NOT_MOUNTED;
|
|
|
|
}
|
|
|
|
} else if (image.substr(0, sizeof(SdCardManager::SD_1_MOUNT_POINT))
|
|
|
|
== std::string(SdCardManager::SD_1_MOUNT_POINT)) {
|
|
|
|
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
|
|
|
|
sif::warning << "StrImageLoader::getImageLocation: SD card 1 not mounted" << std::endl;
|
|
|
|
return SD_NOT_MOUNTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadImage = image;
|
|
|
|
|
|
|
|
if(not std::filesystem::exists(uploadImage)) {
|
|
|
|
return FILE_NOT_EXISTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
internalState = InternalState::UPLOAD_IMAGE;
|
|
|
|
|
|
|
|
semaphore.release();
|
2021-12-06 19:36:21 +01:00
|
|
|
|
|
|
|
return RETURN_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t StrImageLoader::startImageDownload() {
|
|
|
|
return RETURN_OK;
|
2021-11-30 16:01:02 +01:00
|
|
|
}
|
|
|
|
|
2021-12-06 19:36:21 +01:00
|
|
|
ReturnValue_t StrImageLoader::performImageUpload() {
|
2021-12-02 08:05:33 +01:00
|
|
|
ReturnValue_t result = RETURN_OK;
|
|
|
|
uint32_t imageSize = 0;
|
|
|
|
struct UploadActionRequest uploadReq;
|
|
|
|
uploadReq.position = 0;
|
2021-12-06 19:36:21 +01:00
|
|
|
std::memset(&uploadReq.data, 0, sizeof(uploadReq.data));
|
2021-12-02 08:05:33 +01:00
|
|
|
|
|
|
|
if (not std::filesystem::exists(uploadImage)) {
|
|
|
|
triggerEvent(IMAGE_FILE_NOT_EXISTS, uploadReq.position);
|
2021-12-06 19:36:21 +01:00
|
|
|
internalState = InternalState::IDLE;
|
2021-12-02 08:05:33 +01:00
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
std::ifstream file(uploadImage, std::ifstream::binary);
|
2021-12-06 19:36:21 +01:00
|
|
|
// Set position of next character to end of file input stream
|
2021-12-02 08:05:33 +01:00
|
|
|
file.seekg(0, file.end);
|
2021-12-06 19:36:21 +01:00
|
|
|
// tellg returns position of character in input stream
|
2021-12-02 08:05:33 +01:00
|
|
|
imageSize = file.tellg();
|
2021-12-06 19:36:21 +01:00
|
|
|
// Set position of next character to beginning of file input stream
|
|
|
|
file.seekg(0, file.beg);
|
|
|
|
if (imageSize >= SIZE_IMAGE_PART) {
|
|
|
|
file.read(reinterpret_cast<char*>(uploadReq.data), SIZE_IMAGE_PART);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
file.read(reinterpret_cast<char*>(uploadReq.data), imageSize);
|
|
|
|
}
|
2021-12-02 08:05:33 +01:00
|
|
|
while(uploadReq.position * SIZE_IMAGE_PART < imageSize) {
|
2021-12-06 19:36:21 +01:00
|
|
|
result = uploadSendAndRead(&uploadReq);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
result = checkUploadReply();
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
uploadReq.position++;
|
|
|
|
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
|
2021-12-02 08:05:33 +01:00
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
std::memset(uploadReq.data, 0, sizeof(uploadReq.data));
|
2021-12-02 08:05:33 +01:00
|
|
|
uint32_t remainder = imageSize - uploadReq.position * SIZE_IMAGE_PART;
|
|
|
|
file.read(reinterpret_cast<char*>(uploadReq.data), remainder);
|
2021-12-06 19:36:21 +01:00
|
|
|
file.close();
|
2021-12-02 08:05:33 +01:00
|
|
|
uploadReq.position++;
|
2021-12-06 19:36:21 +01:00
|
|
|
result = uploadSendAndRead(&uploadReq);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
result = checkUploadReply();
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return RETURN_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t StrImageLoader::uploadSendAndRead(struct UploadActionRequest* uploadReq) {
|
|
|
|
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);
|
2021-12-02 08:05:33 +01:00
|
|
|
result = communicationInterface->sendMessage(comCookie, datalinkLayer.getEncodedFrame(),
|
2021-12-06 19:36:21 +01:00
|
|
|
datalinkLayer.getEncodedLength());
|
|
|
|
if (result != RETURN_OK) {
|
2021-12-02 08:05:33 +01:00
|
|
|
sif::warning << "StrImageLoader::uploadImage: Failed to send upload packet" << std::endl;
|
2021-12-06 19:36:21 +01:00
|
|
|
triggerEvent(SENDING_UPLOAD_PACKET_FAILED, result, uploadReq->position);
|
2021-12-02 08:05:33 +01:00
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
decResult = ArcsecDatalinkLayer::DEC_IN_PROGRESS;
|
|
|
|
while (decResult == ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
|
|
|
|
result = communicationInterface->requestReceiveMessage(comCookie,
|
|
|
|
StarTracker::MAX_FRAME_SIZE * 2 + 2);
|
2021-12-02 08:05:33 +01:00
|
|
|
if (result != RETURN_OK) {
|
|
|
|
sif::warning << "StrImageLoader::uploadImage: Failed to request reply" << std::endl;
|
2021-12-06 19:36:21 +01:00
|
|
|
triggerEvent(UPLOAD_REQUESTING_MSG_FAILED, result, uploadReq->position);
|
2021-12-02 08:05:33 +01:00
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen);
|
2021-12-02 08:05:33 +01:00
|
|
|
if (result != RETURN_OK) {
|
2021-12-06 19:36:21 +01:00
|
|
|
sif::warning << "StrImageLoader::uploadImage: Failed to read received message" << std::endl;
|
|
|
|
triggerEvent(UPLOAD_READING_REPLY_FAILED, result, uploadReq->position);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
if (receivedDataLen == 0 && missedReplies < MAX_POLLS) {
|
|
|
|
missedReplies++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ((receivedDataLen == 0) && (missedReplies >= MAX_POLLS)) {
|
|
|
|
triggerEvent(NO_REPLY, uploadReq->position);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
missedReplies = 0;
|
2021-12-02 08:05:33 +01:00
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
decResult = datalinkLayer.decodeFrame(receivedData, receivedDataLen, &bytesLeft);
|
2021-12-02 08:05:33 +01:00
|
|
|
if (bytesLeft != 0) {
|
|
|
|
// This should never happen
|
2021-12-06 19:36:21 +01:00
|
|
|
sif::warning << "StrImageLoader::uploadSendAndRead: Bytes left after decoding" << std::endl;
|
|
|
|
triggerEvent(UPLOAD_COM_ERROR, result, uploadReq->position);
|
2021-12-02 08:05:33 +01:00
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
if (decResult != RETURN_OK) {
|
|
|
|
triggerEvent(DEC_ERROR, decResult, uploadReq->position);
|
|
|
|
return RETURN_FAILED;
|
|
|
|
}
|
|
|
|
return RETURN_OK;
|
|
|
|
}
|
2021-12-02 08:05:33 +01:00
|
|
|
|
2021-12-06 19:36:21 +01:00
|
|
|
ReturnValue_t StrImageLoader::checkUploadReply() {
|
|
|
|
uint8_t type = datalinkLayer.getReplyFrameType();
|
|
|
|
if (type != TMTC_ACTIONREPLY) {
|
|
|
|
sif::warning << "StrImageLoader::checkUploadReply: Received invalid upload reply"
|
|
|
|
<< std::endl;
|
|
|
|
triggerEvent(INVALID_TYPE_ID);
|
|
|
|
return RETURN_FAILED;
|
2021-12-02 08:05:33 +01:00
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
uint8_t status = datalinkLayer.getStatusField();
|
|
|
|
if (status != ArcsecDatalinkLayer::STATUS_OK) {
|
|
|
|
triggerEvent(STATUS_ERROR);
|
|
|
|
sif::warning << "StrImageLoader::checkUploadReply: Status failure" << std::endl;
|
|
|
|
return RETURN_FAILED;
|
2021-12-02 08:05:33 +01:00
|
|
|
}
|
2021-12-06 19:36:21 +01:00
|
|
|
return RETURN_OK;
|
2021-11-30 16:01:02 +01:00
|
|
|
}
|