Merge pull request 'added hk service 3' (#311) from KSat/fsfw:mueller/hk-service3 into development
Reviewed-on: fsfw/fsfw#311
This commit is contained in:
commit
eb310a72ef
295
pus/Service3Housekeeping.cpp
Normal file
295
pus/Service3Housekeeping.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
#include "Service3Housekeeping.h"
|
||||
#include "servicepackets/Service3Packets.h"
|
||||
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
||||
|
||||
|
||||
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid,
|
||||
uint8_t serviceId):
|
||||
CommandingServiceBase(objectId, apid, serviceId,
|
||||
NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {}
|
||||
|
||||
Service3Housekeeping::~Service3Housekeeping() {}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::isValidSubservice(uint8_t subservice) {
|
||||
switch(static_cast<Subservice>(subservice)) {
|
||||
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
case Subservice::REPORT_HK_REPORT_STRUCTURES:
|
||||
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES :
|
||||
case Subservice::GENERATE_ONE_PARAMETER_REPORT:
|
||||
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
|
||||
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
|
||||
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
// Telemetry or invalid subservice.
|
||||
case Subservice::HK_DEFINITIONS_REPORT:
|
||||
case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
|
||||
case Subservice::HK_REPORT:
|
||||
case Subservice::DIAGNOSTICS_REPORT:
|
||||
default:
|
||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::getMessageQueueAndObject(uint8_t subservice,
|
||||
const uint8_t *tcData, size_t tcDataLen,
|
||||
MessageQueueId_t *id, object_id_t *objectId) {
|
||||
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
|
||||
if(result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::checkAndAcquireTargetID(
|
||||
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
|
||||
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue(
|
||||
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
|
||||
// check HasLocalDataPoolIF property of target
|
||||
HasLocalDataPoolIF* possibleTarget =
|
||||
objectManager->get<HasLocalDataPoolIF>(*objectId);
|
||||
if(possibleTarget == nullptr){
|
||||
return CommandingServiceBase::INVALID_OBJECT;
|
||||
}
|
||||
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message,
|
||||
uint8_t subservice, const uint8_t *tcData, size_t tcDataLen,
|
||||
uint32_t *state, object_id_t objectId) {
|
||||
switch(static_cast<Subservice>(subservice)) {
|
||||
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, true, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, false, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, true, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, false, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::REPORT_HK_REPORT_STRUCTURES:
|
||||
return prepareStructureReportingCommand(message, objectId, false, tcData,
|
||||
tcDataLen);
|
||||
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES:
|
||||
return prepareStructureReportingCommand(message, objectId, true, tcData,
|
||||
tcDataLen);
|
||||
case Subservice::GENERATE_ONE_PARAMETER_REPORT:
|
||||
return prepareOneShotReportCommand(message, objectId, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
|
||||
return prepareOneShotReportCommand(message, objectId, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
|
||||
return prepareCollectionIntervalModificationCommand(message, objectId,
|
||||
false, tcData, tcDataLen);
|
||||
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
|
||||
return prepareCollectionIntervalModificationCommand(message, objectId,
|
||||
true, tcData, tcDataLen);
|
||||
case Subservice::HK_DEFINITIONS_REPORT:
|
||||
case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
|
||||
case Subservice::HK_REPORT:
|
||||
case Subservice::DIAGNOSTICS_REPORT:
|
||||
// Those are telemetry packets.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
default:
|
||||
// should never happen, subservice was already checked.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand(
|
||||
CommandMessage *command, object_id_t objectId,
|
||||
bool enableReporting, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setToggleReportingCommand(command, targetSid,
|
||||
enableReporting, isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand(
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setStructureReportingCommand(command, targetSid,
|
||||
isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand(
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t *tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setOneShotReportCommand(command, targetSid,
|
||||
isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand(
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t *tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t) + sizeof(float)) {
|
||||
// SID plus the size of the new collection intervL.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
float newCollectionInterval = 0;
|
||||
SerializeAdapter::deSerialize(&newCollectionInterval, &tcData, &tcDataLen,
|
||||
SerializeIF::Endianness::BIG);
|
||||
HousekeepingMessage::setCollectionIntervalModificationCommand(command,
|
||||
targetSid, newCollectionInterval, isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
|
||||
Command_t previousCommand, uint32_t *state,
|
||||
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||
bool *isStep) {
|
||||
Command_t command = reply->getCommand();
|
||||
switch(command) {
|
||||
|
||||
case(HousekeepingMessage::HK_REPORT): {
|
||||
ReturnValue_t result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::HK_REPORT));
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
|
||||
ReturnValue_t result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_DEFINITIONS_REPORT): {
|
||||
return generateHkReply(reply, static_cast<uint8_t>(
|
||||
Subservice::HK_DEFINITIONS_REPORT));
|
||||
break;
|
||||
}
|
||||
case(HousekeepingMessage::DIAGNOSTICS_DEFINITION_REPORT): {
|
||||
return generateHkReply(reply, static_cast<uint8_t>(
|
||||
Subservice::DIAGNOSTICS_DEFINITION_REPORT));
|
||||
break;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REQUEST_SUCCESS): {
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REQUEST_FAILURE): {
|
||||
failureParameter1 = objectId;
|
||||
ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED;
|
||||
HousekeepingMessage::getHkRequestFailureReply(reply,&error);
|
||||
failureParameter2 = error;
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
default:
|
||||
sif::error << "Service3Housekeeping::handleReply: Invalid reply with "
|
||||
<< "reply command " << command << "!" << std::endl;
|
||||
return CommandingServiceBase::INVALID_REPLY;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void Service3Housekeeping::handleUnrequestedReply(
|
||||
CommandMessage* reply) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
Command_t command = reply->getCommand();
|
||||
|
||||
switch(command) {
|
||||
|
||||
case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
|
||||
result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
|
||||
break;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REPORT): {
|
||||
result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::HK_REPORT));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
sif::error << "Service3Housekeeping::handleUnrequestedReply: Invalid "
|
||||
<< "reply with " << "reply command " << command << "!"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// Configuration error
|
||||
sif::debug << "Service3Housekeeping::handleUnrequestedReply:"
|
||||
<< "Could not generate reply!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t Service3Housekeeping::getHkQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::generateHkReply(
|
||||
const CommandMessage* hkMessage, uint8_t subserviceId) {
|
||||
store_address_t storeId;
|
||||
|
||||
sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId);
|
||||
auto resultPair = IPCStore->getData(storeId);
|
||||
if(resultPair.first != HasReturnvaluesIF::RETURN_OK) {
|
||||
return resultPair.first;
|
||||
}
|
||||
|
||||
HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size());
|
||||
return sendTmPacket(static_cast<uint8_t>(subserviceId),
|
||||
hkPacket.hkData, hkPacket.hkSize, nullptr, 0);
|
||||
}
|
||||
|
||||
sid_t Service3Housekeeping::buildSid(object_id_t objectId,
|
||||
const uint8_t** tcData, size_t* tcDataLen) {
|
||||
sid_t targetSid;
|
||||
targetSid.objectId = objectId;
|
||||
// skip deserialization of object ID, was already done.
|
||||
*tcData += sizeof(object_id_t);
|
||||
*tcDataLen -= sizeof(object_id_t);
|
||||
// size check is expected to be performed beforehand!
|
||||
SerializeAdapter::deSerialize(&targetSid.ownerSetId, tcData, tcDataLen,
|
||||
SerializeIF::Endianness::BIG);
|
||||
return targetSid;
|
||||
}
|
105
pus/Service3Housekeeping.h
Normal file
105
pus/Service3Housekeeping.h
Normal file
@ -0,0 +1,105 @@
|
||||
#ifndef FSFW_PUS_SERVICE3HOUSEKEEPINGSERVICE_H_
|
||||
#define FSFW_PUS_SERVICE3HOUSEKEEPINGSERVICE_H_
|
||||
|
||||
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
||||
#include "../housekeeping/HousekeepingMessage.h"
|
||||
#include "../tmtcservices/CommandingServiceBase.h"
|
||||
|
||||
/**
|
||||
* @brief Manges spacecraft housekeeping reports and
|
||||
* sends pool variables (temperature, GPS data ...) to ground.
|
||||
*
|
||||
* @details Full Documentation: ECSS-E70-41A or ECSS-E-ST-70-41C.
|
||||
* Implementation based on PUS-C
|
||||
*
|
||||
* The housekeeping service type provides means to control and adapt the
|
||||
* spacecraft reporting plan according to the mission phases.
|
||||
* The housekeeping service type provides the visibility of any
|
||||
* on-board parameters assembled in housekeeping parameter report structures
|
||||
* or diagnostic parameter report structures as required for the mission.
|
||||
* The parameter report structures used by the housekeeping service can
|
||||
* be predefined on-board or created when needed.
|
||||
*
|
||||
* @author R. Mueller
|
||||
* @ingroup pus_services
|
||||
*/
|
||||
class Service3Housekeeping: public CommandingServiceBase,
|
||||
public AcceptsHkPacketsIF {
|
||||
public:
|
||||
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
|
||||
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
|
||||
|
||||
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId);
|
||||
virtual~ Service3Housekeeping();
|
||||
protected:
|
||||
/* CSB abstract functions implementation . See CSB documentation. */
|
||||
ReturnValue_t isValidSubservice(uint8_t subservice) override;
|
||||
ReturnValue_t getMessageQueueAndObject(uint8_t subservice,
|
||||
const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id,
|
||||
object_id_t *objectId) override;
|
||||
ReturnValue_t prepareCommand(CommandMessage* message,
|
||||
uint8_t subservice, const uint8_t *tcData, size_t tcDataLen,
|
||||
uint32_t *state, object_id_t objectId) override;
|
||||
ReturnValue_t handleReply(const CommandMessage* reply,
|
||||
Command_t previousCommand, uint32_t *state,
|
||||
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||
bool *isStep) override;
|
||||
|
||||
virtual MessageQueueId_t getHkQueue() const;
|
||||
private:
|
||||
enum class Subservice {
|
||||
ENABLE_PERIODIC_HK_REPORT_GENERATION = 5, //!< [EXPORT] : [TC]
|
||||
DISABLE_PERIODIC_HK_REPORT_GENERATION = 6, //!< [EXPORT] : [TC]
|
||||
|
||||
ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION = 7, //!< [EXPORT] : [TC]
|
||||
DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION = 8, //!< [EXPORT] : [TC]
|
||||
|
||||
//! [EXPORT] : [TC] Report HK structure by supplying SID
|
||||
REPORT_HK_REPORT_STRUCTURES = 9,
|
||||
//! [EXPORT] : [TC] Report Diagnostics structure by supplying SID
|
||||
REPORT_DIAGNOSTICS_REPORT_STRUCTURES = 11,
|
||||
|
||||
//! [EXPORT] : [TM] Report corresponding to Subservice 9 TC
|
||||
HK_DEFINITIONS_REPORT = 10,
|
||||
//! [EXPORT] : [TM] Report corresponding to Subservice 11 TC
|
||||
DIAGNOSTICS_DEFINITION_REPORT = 12,
|
||||
|
||||
//! [EXPORT] : [TM] Core packet. Contains Housekeeping data
|
||||
HK_REPORT = 25,
|
||||
//! [EXPORT] : [TM] Core packet. Contains diagnostics data
|
||||
DIAGNOSTICS_REPORT = 26,
|
||||
|
||||
/* PUS-C */
|
||||
GENERATE_ONE_PARAMETER_REPORT = 27, //!< [EXPORT] : [TC]
|
||||
GENERATE_ONE_DIAGNOSTICS_REPORT = 28, //!< [EXPORT] : [TC]
|
||||
|
||||
MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL = 31, //!< [EXPORT] : [TC]
|
||||
MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL = 32, //!< [EXPORT] : [TC]
|
||||
};
|
||||
|
||||
ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet,
|
||||
const uint8_t* tcData, size_t tcDataLen);
|
||||
ReturnValue_t checkInterfaceAndAcquireMessageQueue(
|
||||
MessageQueueId_t* messageQueueToSet, object_id_t* objectId);
|
||||
|
||||
ReturnValue_t generateHkReply(const CommandMessage* hkMessage,
|
||||
uint8_t subserviceId);
|
||||
ReturnValue_t prepareReportingTogglingCommand(CommandMessage* command,
|
||||
object_id_t objectId, bool enableReporting, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen);
|
||||
ReturnValue_t prepareStructureReportingCommand(CommandMessage* command,
|
||||
object_id_t objectId, bool isDiagnostics, const uint8_t* tcData,
|
||||
size_t tcDataLen);
|
||||
ReturnValue_t prepareOneShotReportCommand(CommandMessage* command,
|
||||
object_id_t objectId, bool isDiagnostics, const uint8_t* tcData,
|
||||
size_t tcDataLen);
|
||||
ReturnValue_t prepareCollectionIntervalModificationCommand(
|
||||
CommandMessage* command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen);
|
||||
|
||||
void handleUnrequestedReply(CommandMessage* reply) override;
|
||||
sid_t buildSid(object_id_t objectId, const uint8_t** tcData,
|
||||
size_t* tcDataLen);
|
||||
};
|
||||
|
||||
#endif /* FSFW_PUS_SERVICE3HOUSEKEEPINGSERVICE_H_ */
|
21
pus/servicepackets/Service3Packets.h
Normal file
21
pus/servicepackets/Service3Packets.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE3PACKETS_H_
|
||||
#define FSFW_PUS_SERVICEPACKETS_SERVICE3PACKETS_H_
|
||||
|
||||
#include <fsfw/housekeeping/HousekeepingMessage.h>
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* @brief Subservices 25 and 26: TM packets
|
||||
* @ingroup spacepackets
|
||||
*/
|
||||
class HkPacket { //!< [EXPORT] : [SUBSERVICE] 25, 26
|
||||
public:
|
||||
sid_t sid; //!< [EXPORT] : [COMMENT] Structure ID (SID) of housekeeping data.
|
||||
const uint8_t* hkData; //!< [EXPORT] : [MAXSIZE] Deduced size
|
||||
size_t hkSize; //!< [EXPORT] : [IGNORE]
|
||||
|
||||
HkPacket(sid_t sid, const uint8_t* data, size_t size):
|
||||
sid(sid), hkData(data), hkSize(size) {}
|
||||
};
|
||||
|
||||
#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE3PACKETS_H_ */
|
Loading…
Reference in New Issue
Block a user