A lot of new features and tweaks #12
178
pus/Service2DeviceAccess.cpp
Normal file
178
pus/Service2DeviceAccess.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include <framework/pus/Service2DeviceAccess.h>
|
||||||
|
#include <framework/pus/servicepackets/Service2Packets.h>
|
||||||
|
|
||||||
|
#include <framework/devicehandlers/DeviceHandlerIF.h>
|
||||||
|
#include <framework/storagemanager/StorageManagerIF.h>
|
||||||
|
#include <framework/devicehandlers/DeviceHandlerMessage.h>
|
||||||
|
#include <framework/serialize/EndianConverter.h>
|
||||||
|
#include <framework/action/ActionMessage.h>
|
||||||
|
#include <framework/serialize/SerializeAdapter.h>
|
||||||
|
#include <framework/serialize/SerialLinkedListAdapter.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId,
|
||||||
|
uint16_t apid, uint8_t serviceId, object_id_t tcSource,
|
||||||
|
object_id_t tmDestination):
|
||||||
|
CommandingServiceBase(objectId, apid, serviceId,
|
||||||
|
NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS,
|
||||||
|
tcSource, tmDestination) {}
|
||||||
|
|
||||||
|
Service2DeviceAccess::~Service2DeviceAccess() {}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) {
|
||||||
|
switch(static_cast<Subservice>(subservice)){
|
||||||
|
case Subservice::RAW_COMMANDING:
|
||||||
|
case Subservice::TOGGLE_WIRETAPPING:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
sif::error << "Invalid Subservice" << std::endl;
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::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 != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::checkAndAcquireTargetID(
|
||||||
|
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
|
||||||
|
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData,
|
||||||
|
&tcDataLen, SerializeIF::Endianness::BIG) != RETURN_OK) {
|
||||||
|
sif::error << "Service 2: Target ID not found. ID: " <<
|
||||||
|
std::hex << objectIdToSet ;
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t * messageQueueToSet, object_id_t *objectId) {
|
||||||
|
DeviceHandlerIF* possibleTarget =
|
||||||
|
objectManager->get<DeviceHandlerIF>(*objectId);
|
||||||
|
if(possibleTarget == nullptr) {
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::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::RAW_COMMANDING: {
|
||||||
|
return prepareRawCommand(dynamic_cast<CommandMessage*>(message),
|
||||||
|
tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Subservice::TOGGLE_WIRETAPPING: {
|
||||||
|
return prepareWiretappingCommand(dynamic_cast<CommandMessage*>(message),
|
||||||
|
tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::prepareRawCommand(
|
||||||
|
CommandMessage* messageToSet, const uint8_t *tcData,size_t tcDataLen) {
|
||||||
|
RawCommand RawCommand(tcData,tcDataLen);
|
||||||
|
// store command into the Inter Process Communication Store
|
||||||
|
store_address_t storeAddress;
|
||||||
|
ReturnValue_t result = IPCStore->addData(&storeAddress,
|
||||||
|
RawCommand.getCommand(), RawCommand.getCommandSize());
|
||||||
|
DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet,
|
||||||
|
storeAddress);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::prepareWiretappingCommand(
|
||||||
|
CommandMessage *messageToSet, const uint8_t *tcData,
|
||||||
|
size_t tcDataLen) {
|
||||||
|
if(tcDataLen != WiretappingToggle::WIRETAPPING_COMMAND_SIZE) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
WiretappingToggle command;
|
||||||
|
ReturnValue_t result = command.deSerialize(&tcData, &tcDataLen,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(messageToSet,
|
||||||
|
command.getWiretappingMode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply,
|
||||||
|
Command_t previousCommand, uint32_t* state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool* isStep) {
|
||||||
|
switch(reply->getCommand()) {
|
||||||
|
case CommandMessage::REPLY_COMMAND_OK:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
case CommandMessage::REPLY_REJECTED:
|
||||||
|
return reply->getReplyRejectedReason();
|
||||||
|
default:
|
||||||
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All device handlers set service 2 as default raw receiver for wiretapping
|
||||||
|
// so we have to handle those unrequested messages.
|
||||||
|
void Service2DeviceAccess::handleUnrequestedReply(CommandMessage* reply) {
|
||||||
|
switch(reply->getCommand()) {
|
||||||
|
case DeviceHandlerMessage::REPLY_RAW_COMMAND:
|
||||||
|
sendWiretappingTm(reply,
|
||||||
|
static_cast<uint8_t>(Subservice::WIRETAPPING_RAW_TC));
|
||||||
|
break;
|
||||||
|
case DeviceHandlerMessage::REPLY_RAW_REPLY:
|
||||||
|
sendWiretappingTm(reply,
|
||||||
|
static_cast<uint8_t>(Subservice::RAW_REPLY));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sif::error << "Unknown message in Service2DeviceAccess::"
|
||||||
|
"handleUnrequestedReply with command ID " <<
|
||||||
|
reply->getCommand() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Must be reached by all cases to clear message
|
||||||
|
reply->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service2DeviceAccess::sendWiretappingTm(CommandMessage *reply,
|
||||||
|
uint8_t subservice) {
|
||||||
|
// Raw Wiretapping
|
||||||
|
// Get Address of Data from Message
|
||||||
|
store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply);
|
||||||
|
const uint8_t* data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
ReturnValue_t result = IPCStore->getData(storeAddress,&data,&size);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||||
|
sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in "
|
||||||
|
"handleUnrequestedReply with failure ID "<< result
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init our dummy packet and correct endianness of object ID before
|
||||||
|
// sending it back.
|
||||||
|
WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply),
|
||||||
|
data);
|
||||||
|
TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId);
|
||||||
|
sendTmPacket(subservice,TmPacket.data,size,reinterpret_cast<uint8_t*>(
|
||||||
|
&TmPacket.objectId),sizeof(TmPacket.objectId));
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t Service2DeviceAccess::getDeviceQueue() {
|
||||||
|
return commandQueue->getId();
|
||||||
|
}
|
||||||
|
|
96
pus/Service2DeviceAccess.h
Normal file
96
pus/Service2DeviceAccess.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#ifndef FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_
|
||||||
|
|
||||||
|
#include <framework/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <framework/devicehandlers/AcceptsDeviceResponsesIF.h>
|
||||||
|
#include <framework/tmtcservices/CommandingServiceBase.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Raw Commanding and Wiretapping of devices.
|
||||||
|
* @details
|
||||||
|
* Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A
|
||||||
|
* Dissertation Baetz p. 115, 116, 165-167.
|
||||||
|
*
|
||||||
|
* This service provides the capability to communicate with devices in their
|
||||||
|
* native protocols with raw commands through the DeviceHandlerIF.
|
||||||
|
*
|
||||||
|
* This is a gateway service. It relays device commands using the software bus.
|
||||||
|
* This service is very closely tied to the Commanding Service Base
|
||||||
|
* template class. There is constant interaction between this Service Base und
|
||||||
|
* a Subclass like this service
|
||||||
|
* There are 4 adaption points for component implementation through the
|
||||||
|
* Commanding Service Base.
|
||||||
|
*
|
||||||
|
* This service employs custom subservices exclusively. This includes a
|
||||||
|
* wiretapping subservice to monitor all traffic between target devices and
|
||||||
|
* this service.
|
||||||
|
*
|
||||||
|
* - TC[2,128]: Raw Commanding
|
||||||
|
* - TC[2,129]: Toggle Wiretapping
|
||||||
|
* - TM[2,130]: Wiretapping Packet TM
|
||||||
|
* - TM[2,131]: Wiretapping Packet TC
|
||||||
|
* @ingroup pus_services
|
||||||
|
*/
|
||||||
|
class Service2DeviceAccess : public CommandingServiceBase,
|
||||||
|
public AcceptsDeviceResponsesIF
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Service2DeviceAccess(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t serviceId, object_id_t tcSource,
|
||||||
|
object_id_t tmDestination);
|
||||||
|
virtual ~Service2DeviceAccess();
|
||||||
|
|
||||||
|
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
|
||||||
|
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
|
||||||
|
protected:
|
||||||
|
//! CommandingServiceBase (CSB) abstract functions. 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates TM packets containing either the TC wiretapping
|
||||||
|
* packets or the TM wiretapping packets.
|
||||||
|
* Note that for service 2, all telemetry will be treated as an
|
||||||
|
* unrequested reply regardless of wiretapping mode.
|
||||||
|
* @param reply
|
||||||
|
*/
|
||||||
|
void handleUnrequestedReply(CommandMessage* reply) override;
|
||||||
|
|
||||||
|
MessageQueueId_t getDeviceQueue() override;
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Generates TM packets for Wiretapping Service
|
||||||
|
* @param reply
|
||||||
|
* @param subservice
|
||||||
|
*/
|
||||||
|
void sendWiretappingTm(CommandMessage* reply,uint8_t subservice);
|
||||||
|
|
||||||
|
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 prepareRawCommand(CommandMessage* messageToSet,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
ReturnValue_t prepareWiretappingCommand(CommandMessage* messageToSet,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
|
||||||
|
enum class Subservice {
|
||||||
|
RAW_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Command in device native protocol
|
||||||
|
TOGGLE_WIRETAPPING = 129, //!< [EXPORT] : [COMMAND] Toggle wiretapping of raw communication
|
||||||
|
RAW_REPLY = 130, //!< [EXPORT] : [REPLY] Includes wiretapping TM and normal TM raw replies from device
|
||||||
|
WIRETAPPING_RAW_TC = 131 //!< [EXPORT] : [REPLY] Wiretapping packets of commands built by device handler
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MISSION_PUS_DEVICE2DEVICECOMMANDING_H_ */
|
76
pus/servicepackets/Service2Packets.h
Normal file
76
pus/servicepackets/Service2Packets.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_
|
||||||
|
|
||||||
|
#include <framework/action/ActionMessage.h>
|
||||||
|
#include <framework/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <framework/serialize/SerialLinkedListAdapter.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservice 128
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class RawCommand { //!< [EXPORT] : [SUBSERVICE] 128
|
||||||
|
public:
|
||||||
|
RawCommand(const uint8_t* buffer, size_t size) {
|
||||||
|
// Deserialize Adapter to get correct endianness
|
||||||
|
SerializeAdapter::deSerialize(&objectId, &buffer, &size,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
commandBuffer = buffer;
|
||||||
|
// size is decremented by AutoSerializeAdapter,
|
||||||
|
// remaining size is data size
|
||||||
|
dataSize = size;
|
||||||
|
}
|
||||||
|
object_id_t getObjectId() const {
|
||||||
|
return objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* getCommand() {
|
||||||
|
return commandBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getCommandSize() const {
|
||||||
|
return dataSize;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
object_id_t objectId = 0;
|
||||||
|
const uint8_t* commandBuffer = nullptr; //!< [EXPORT] : [MAXSIZE] 256 Bytes
|
||||||
|
size_t dataSize = 0; //!< [EXPORT] : [IGNORE]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservice 129: Command packet to set wiretapping mode
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class WiretappingToggle: public SerialLinkedListAdapter<SerializeIF>{ //!< [EXPORT] : [SUBSERVICE] 129
|
||||||
|
public:
|
||||||
|
static const size_t WIRETAPPING_COMMAND_SIZE = 5;
|
||||||
|
WiretappingToggle(){
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(&wiretappingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getWiretappingMode() const {
|
||||||
|
return wiretappingMode.entry;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SerializeElement<object_id_t> objectId;
|
||||||
|
SerializeElement<uint8_t> wiretappingMode; //!< [EXPORT] : [INPUT] Mode 0: OFF, Mode 1: RAW
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservices 130 and 131: TM packets
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class WiretappingPacket { //!< [EXPORT] : [SUBSERVICE] 130, 131
|
||||||
|
public:
|
||||||
|
object_id_t objectId; //!< [EXPORT] : [COMMENT] Object ID of source object
|
||||||
|
const uint8_t* data; //!< [EXPORT] : [MAXSIZE] Raw Command Max. Size
|
||||||
|
WiretappingPacket(object_id_t objectId, const uint8_t* buffer):
|
||||||
|
objectId(objectId), data(buffer) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ */
|
@ -1,17 +1,3 @@
|
|||||||
/**
|
|
||||||
* \file Service5Packets.h
|
|
||||||
*
|
|
||||||
* Structure of Event Report.
|
|
||||||
* It consists of:
|
|
||||||
* 1. Report ID(RID). This is the Event ID in the FSFW
|
|
||||||
* 2. Object ID of the reporter (e.g. subsystem)
|
|
||||||
* 2. Parameter 1
|
|
||||||
* 3. Parameter 2
|
|
||||||
*
|
|
||||||
* Created on: 21.05.2019
|
|
||||||
* Author: R. Mueller, J. Meier
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_
|
#ifndef MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_
|
||||||
#define MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_
|
#define MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_
|
||||||
|
|
||||||
@ -20,8 +6,15 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Subservice 1, 2, 3, 4
|
* @brief Subservice 1, 2, 3, 4
|
||||||
* \ingroup spacepackets
|
* Structure of Event Report.
|
||||||
|
* It consists of:
|
||||||
|
* 1. Report ID(RID). This is the Event ID in the FSFW
|
||||||
|
* 2. Object ID of the reporter (e.g. subsystem)
|
||||||
|
* 2. Parameter 1
|
||||||
|
* 3. Parameter 2
|
||||||
|
*
|
||||||
|
* @ingroup spacepackets
|
||||||
*/
|
*/
|
||||||
class EventReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 2, 3, 4
|
class EventReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 2, 3, 4
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user