2020-10-12 18:18:41 +02:00
# ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
# define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
2016-06-15 23:48:41 +02:00
2020-08-27 19:50:02 +02:00
# include "DeviceHandlerIF.h"
# include "DeviceCommunicationIF.h"
# include "DeviceHandlerFailureIsolation.h"
2020-12-08 15:59:30 +01:00
# include "DeviceHandlerThermalSet.h"
2016-06-15 23:48:41 +02:00
2021-01-08 16:14:11 +01:00
# include "../serviceinterface/ServiceInterface.h"
# include "../serviceinterface/serviceInterfaceDefintions.h"
2020-08-13 20:53:35 +02:00
# include "../objectmanager/SystemObject.h"
# include "../tasks/ExecutableObjectIF.h"
# include "../returnvalues/HasReturnvaluesIF.h"
# include "../action/HasActionsIF.h"
# include "../datapool/PoolVariableIF.h"
# include "../modes/HasModesIF.h"
# include "../power/PowerSwitchIF.h"
# include "../ipc/MessageQueueIF.h"
2020-10-12 18:18:41 +02:00
# include "../tasks/PeriodicTaskIF.h"
2020-08-13 20:53:35 +02:00
# include "../action/ActionHelper.h"
# include "../health/HealthHelper.h"
# include "../parameters/ParameterHelper.h"
# include "../datapool/HkSwitchHelper.h"
2020-10-12 18:18:41 +02:00
# include "../datapoollocal/HasLocalDataPoolIF.h"
# include "../datapoollocal/LocalDataPoolManager.h"
2020-04-19 14:03:47 +02:00
2016-06-15 23:48:41 +02:00
# include <map>
2018-07-12 16:29:32 +02:00
namespace Factory {
void setStaticFrameworkObjectIds ( ) ;
}
2016-06-15 23:48:41 +02:00
class StorageManagerIF ;
/**
2020-04-19 15:48:17 +02:00
* @ defgroup devices Devices
2019-08-28 14:50:24 +02:00
* Contains all devices and the DeviceHandlerBase class .
*/
/**
2020-04-19 14:03:47 +02:00
* @ brief This is the abstract base class for device handlers .
* @ details
2019-08-28 14:50:24 +02:00
* Documentation : Dissertation Baetz p .138 , 139 , p .141 - 149
2016-06-15 23:48:41 +02:00
*
2020-04-19 14:03:47 +02:00
* It features handling of @ link DeviceHandlerIF : : Mode_t Modes @ endlink ,
2020-10-12 18:18:41 +02:00
* communication with physical devices , using the
* @ link DeviceCommunicationIF @ endlink , and communication with commanding
* objects . It inherits SystemObject and thus can be created by the
* ObjectManagerIF .
2016-06-15 23:48:41 +02:00
*
2020-10-12 18:18:41 +02:00
* This class uses the opcode of ExecutableObjectIF to perform a
* step - wise execution . For each step a different action is selected and
* executed . Currently , the device handler base performs a 4 - step
* execution related to 4 communication steps ( based on RMAP ) .
* NOTE : RMAP is a standard which is used for Flying Laptop .
2020-04-19 14:03:47 +02:00
* RMAP communication is not mandatory for projects implementing the FSFW .
* However , the communication principles are similar to RMAP as there are
* two write and two send calls involved .
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* Device handler instances should extend this class and implement the abstract
* functions . Components and drivers can send so called cookies which are used
* for communication and contain information about the communcation ( e . g . slave
* address for I2C or RMAP structs ) .
2020-04-19 14:03:47 +02:00
* The following abstract methods must be implemented by a device handler :
* 1. doStartUp ( )
* 2. doShutDown ( )
* 3. buildTransitionDeviceCommand ( )
* 4. buildNormalDeviceCommand ( )
* 5. buildCommandFromCommand ( )
* 6. fillCommandAndReplyMap ( )
* 7. scanForReply ( )
* 8. interpretDeviceReply ( )
2019-08-28 14:50:24 +02:00
*
2020-04-19 14:03:47 +02:00
* Other important virtual methods with a default implementation
* are the getTransitionDelayMs ( ) function and the getSwitches ( ) function .
* If a transition to MODE_ON is desired without commanding , override the
* intialize ( ) function and call setMode ( _MODE_START_UP ) before calling
* DeviceHandlerBase : : initialize ( ) .
2019-08-28 14:50:24 +02:00
*
2020-04-19 14:03:47 +02:00
* @ ingroup devices
2016-06-15 23:48:41 +02:00
*/
class DeviceHandlerBase : public DeviceHandlerIF ,
public HasReturnvaluesIF ,
2018-07-12 16:29:32 +02:00
public ExecutableObjectIF ,
2016-06-15 23:48:41 +02:00
public SystemObject ,
public HasModesIF ,
public HasHealthIF ,
public HasActionsIF ,
2020-10-12 18:18:41 +02:00
public ReceivesParameterMessagesIF ,
public HasLocalDataPoolIF {
2018-07-12 16:29:32 +02:00
friend void ( Factory : : setStaticFrameworkObjectIds ) ( ) ;
2016-06-15 23:48:41 +02:00
public :
/**
* The constructor passes the objectId to the SystemObject ( ) .
*
* @ param setObjectId the ObjectId to pass to the SystemObject ( ) Constructor
2020-04-19 14:03:47 +02:00
* @ param deviceCommuncation Communcation Interface object which is used
* to implement communication functions
2020-10-12 18:18:41 +02:00
* @ param comCookie This object will be passed to the communication inter -
* face and can contain user - defined information about the communication .
2020-04-19 14:03:47 +02:00
* @ param fdirInstance
* @ param cmdQueueSize
2016-06-15 23:48:41 +02:00
*/
2020-04-19 15:48:17 +02:00
DeviceHandlerBase ( object_id_t setObjectId , object_id_t deviceCommunication ,
2020-07-16 11:56:48 +02:00
CookieIF * comCookie , FailureIsolationBase * fdirInstance = nullptr ,
2020-04-19 15:48:17 +02:00
size_t cmdQueueSize = 20 ) ;
2016-06-15 23:48:41 +02:00
2020-10-12 18:18:41 +02:00
void setHkDestination ( object_id_t hkDestination ) ;
2020-12-08 15:59:30 +01:00
/**
* If the device handler is controlled by the FSFW thermal building blocks ,
* this function should be called to initialize all required components .
* The device handler will then take care of creating local pool entries
* for the device thermal state and device heating request .
* Custom local pool IDs can be assigned as well .
* @ param thermalStatePoolId
* @ param thermalRequestPoolId
*/
void setThermalStateRequestPoolIds ( lp_id_t thermalStatePoolId =
DeviceHandlerIF : : DEFAULT_THERMAL_STATE_POOL_ID ,
lp_id_t thermalRequestPoolId =
DeviceHandlerIF : : DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID ,
uint32_t thermalSetId = DeviceHandlerIF : : DEFAULT_THERMAL_SET_ID ) ;
2020-10-12 18:18:41 +02:00
/**
* @ brief Helper function to ease device handler development .
* This will instruct the transition to MODE_ON immediately
* ( leading to doStartUp ( ) being called for the transition to the ON mode ) ,
* so external mode commanding is not necessary anymore .
*
* This has to be called before the task is started !
* ( e . g . in the task factory ) . This is only a helper function for
* development . Regular mode commanding should be performed by commanding
* the AssemblyBase or Subsystem objects resposible for the device handler .
*/
void setStartUpImmediately ( ) ;
2020-07-16 11:56:48 +02:00
2019-08-28 14:50:24 +02:00
/**
2020-04-19 14:03:47 +02:00
* @ brief This function is the device handler base core component and is
* called periodically .
* @ details
* General sequence , showing where abstract virtual functions are called :
* If the State is SEND_WRITE :
* 1. Set the cookie state to COOKIE_UNUSED and read the command queue
* 2. Handles Device State Modes by calling doStateMachine ( ) .
* This function calls callChildStatemachine ( ) which calls the
* abstract functions doStartUp ( ) and doShutDown ( )
* 3. Check switch states by calling checkSwitchStates ( )
* 4. Decrements counter for timeout of replies by calling
* decrementDeviceReplyMap ( )
* 5. Performs FDIR check for failures
* 6. Calls hkSwitcher . performOperation ( )
* 7. If the device mode is MODE_OFF , return RETURN_OK .
* Otherwise , perform the Action property and performs depending
* on value specified by input value counter ( incremented in PST ) .
* The child class tells base class what to do by setting this value .
* - SEND_WRITE : Send data or commands to device by calling
* doSendWrite ( ) which calls sendMessage function
* of # communicationInterface
* and calls buildInternalCommand if the cookie state is COOKIE_UNUSED
* - GET_WRITE : Get ackknowledgement for sending by calling doGetWrite ( )
* which calls getSendSuccess of # communicationInterface .
* Calls abstract functions scanForReply ( ) and interpretDeviceReply ( ) .
* - SEND_READ : Request reading data from device by calling doSendRead ( )
* which calls requestReceiveMessage of # communcationInterface
* - GET_READ : Access requested reading data by calling doGetRead ( )
* which calls readReceivedMessage of # communicationInterface
* @ param counter Specifies which Action to perform
* @ return RETURN_OK for successful execution
*/
2018-07-12 16:29:32 +02:00
virtual ReturnValue_t performOperation ( uint8_t counter ) ;
2016-06-15 23:48:41 +02:00
2020-04-19 14:03:47 +02:00
/**
* @ brief Initializes the device handler
* @ details
* Initialize Device Handler as system object and
* initializes all important helper classes .
* Calls fillCommandAndReplyMap ( ) .
* @ return
*/
2016-06-15 23:48:41 +02:00
virtual ReturnValue_t initialize ( ) ;
2020-10-12 18:18:41 +02:00
/**
* @ brief Intialization steps performed after all tasks have been created .
* This function will be called by the executing task .
* @ return
*/
virtual ReturnValue_t initializeAfterTaskCreation ( ) override ;
2020-07-16 11:56:48 +02:00
/** Destructor. */
2020-04-19 14:03:47 +02:00
virtual ~ DeviceHandlerBase ( ) ;
2020-07-16 11:56:48 +02:00
2020-04-19 14:03:47 +02:00
protected :
/**
* @ brief This is used to let the child class handle the transition from
* mode @ c _MODE_START_UP to @ c MODE_ON
* @ details
* It is only called when the device handler is in mode @ c _MODE_START_UP .
* That means , the device switch ( es ) are already set to on .
* Device handler commands are read and can be handled by the child class .
* If the child class handles a command , it should also send
* an reply accordingly .
* If an Command is not handled ( ie # DeviceHandlerCommand is not @ c CMD_NONE ,
* the base class handles rejecting the command and sends a reply .
* The replies for mode transitions are handled by the base class .
2016-06-15 23:48:41 +02:00
*
2020-04-19 14:03:47 +02:00
* - If the device is started and ready for operation , the mode should be
* set to MODE_ON . It is possible to set the mode to _MODE_TO_ON to
* use the to on transition if available .
* - If the power - up fails , the mode should be set to _MODE_POWER_DOWN
* which will lead to the device being powered off .
* - If the device does not change the mode , the mode will be changed
* to _MODE_POWER_DOWN , after the timeout ( from getTransitionDelay ( ) )
* has passed .
*
* # transitionFailure can be set to a failure code indicating the reason
* for a failed transition
2016-06-15 23:48:41 +02:00
*/
2020-04-19 14:03:47 +02:00
virtual void doStartUp ( ) = 0 ;
2016-06-15 23:48:41 +02:00
/**
2020-04-19 14:03:47 +02:00
* @ brief This is used to let the child class handle the transition
* from mode @ c _MODE_SHUT_DOWN to @ c _MODE_POWER_DOWN
* @ details
* It is only called when the device handler is in mode @ c _MODE_SHUT_DOWN .
* Device handler commands are read and can be handled by the child class .
* If the child class handles a command , it should also send an reply
* accordingly .
* If an Command is not handled ( ie # DeviceHandlerCommand is not
* @ c CMD_NONE , the base class handles rejecting the command and sends a
* reply . The replies for mode transitions are handled by the base class .
*
* - If the device ready to be switched off ,
* the mode should be set to _MODE_POWER_DOWN .
* - If the device should not be switched off , the mode can be changed to
* _MODE_TO_ON ( or MODE_ON if no transition is needed ) .
* - If the device does not change the mode , the mode will be changed to
* _MODE_POWER_DOWN , when the timeout ( from getTransitionDelay ( ) )
* has passed .
*
* # transitionFailure can be set to a failure code indicating the reason
* for a failed transition
2016-06-15 23:48:41 +02:00
*/
2020-04-19 14:03:47 +02:00
virtual void doShutDown ( ) = 0 ;
/**
* Build the device command to send for normal mode .
*
* This is only called in @ c MODE_NORMAL . If multiple submodes for
* @ c MODE_NORMAL are supported , different commands can built ,
* depending on the submode .
*
* # rawPacket and # rawPacketLen must be set by this method to the
* packet to be sent . If variable command frequence is required , a counter
* can be used and the frequency in the reply map has to be set manually
* by calling updateReplyMap ( ) .
*
* @ param [ out ] id the device command id that has been built
* @ return
2020-12-22 12:44:55 +01:00
* - @ c RETURN_OK to send command after setting # rawPacket and
* # rawPacketLen .
* - @ c NOTHING_TO_SEND when no command is to be sent .
* - Anything else triggers an even with the returnvalue as a parameter .
2020-04-19 14:03:47 +02:00
*/
virtual ReturnValue_t buildNormalDeviceCommand ( DeviceCommandId_t * id ) = 0 ;
/**
* Build the device command to send for a transitional mode .
*
* This is only called in @ c _MODE_TO_NORMAL , @ c _MODE_TO_ON , @ c _MODE_TO_RAW ,
2020-07-16 11:56:48 +02:00
* @ c _MODE_START_UP and @ c _MODE_SHUT_DOWN . So it is used by doStartUp ( )
* and doShutDown ( ) as well as doTransition ( ) , by setting those
* modes in the respective functions .
2020-04-19 14:03:47 +02:00
*
* A good idea is to implement a flag indicating a command has to be built
* and a variable containing the command number to be built
* and filling them in doStartUp ( ) , doShutDown ( ) and doTransition ( ) so no
* modes have to be checked here .
*
2020-12-22 12:44:55 +01:00
* # rawPacket and # rawPacketLen must be set by this method to the
* packet to be sent .
2020-04-19 14:03:47 +02:00
*
* @ param [ out ] id the device command id built
* @ return
* - @ c RETURN_OK when a command is to be sent
* - @ c NOTHING_TO_SEND when no command is to be sent
* - Anything else triggers an even with the returnvalue as a parameter
*/
virtual ReturnValue_t buildTransitionDeviceCommand ( DeviceCommandId_t * id ) = 0 ;
/**
2020-12-22 12:44:55 +01:00
* @ brief Build a device command packet from data supplied by a
* direct command .
2020-04-19 14:03:47 +02:00
*
* @ details
2020-12-22 12:44:55 +01:00
* # rawPacket and # rawPacketLen should be set by this method to the packet
* to be sent . The existence of the command in the command map and the
* command size check against 0 are done by the base class .
2020-04-19 14:03:47 +02:00
*
2020-12-22 12:44:55 +01:00
* @ param deviceCommand the command to build , already checked against
* deviceCommandMap
2020-04-19 14:03:47 +02:00
* @ param commandData pointer to the data from the direct command
* @ param commandDataLen length of commandData
* @ return
2020-12-22 12:44:55 +01:00
* - @ c RETURN_OK to send command after # rawPacket and # rawPacketLen
* have been set .
* - Anything else triggers an event with the
* returnvalue as a parameter
2020-04-19 14:03:47 +02:00
*/
virtual ReturnValue_t buildCommandFromCommand ( DeviceCommandId_t deviceCommand ,
const uint8_t * commandData , size_t commandDataLen ) = 0 ;
/**
* @ brief Scans a buffer for a valid reply .
* @ details
* This is used by the base class to check the data received for valid packets .
* It only checks if a valid packet starts at @ c start .
* It also only checks the structural validy of the packet ,
* e . g . checksums lengths and protocol data . No information check is done ,
* e . g . range checks etc .
*
* Errors should be reported directly , the base class does NOT report any
* errors based on the return value of this function .
*
* @ param start start of remaining buffer to be scanned
* @ param len length of remaining buffer to be scanned
* @ param [ out ] foundId the id of the data found in the buffer .
* @ param [ out ] foundLen length of the data found . Is to be set in function ,
* buffer is scanned at previous position + foundLen .
* @ return
* - @ c RETURN_OK a valid packet was found at @ c start , @ c foundLen is valid
* - @ c RETURN_FAILED no reply could be found starting at @ c start ,
* implies @ c foundLen is not valid , base class will call scanForReply ( )
* again with + + start
* - @ c DeviceHandlerIF : : INVALID_DATA a packet was found but it is invalid ,
* e . g . checksum error , implies @ c foundLen is valid , can be used to
* skip some bytes
* - @ c DeviceHandlerIF : : LENGTH_MISSMATCH @ c len is invalid
* - @ c DeviceHandlerIF : : IGNORE_REPLY_DATA Ignore this specific part of
* the packet
* - @ c DeviceHandlerIF : : IGNORE_FULL_PACKET Ignore the packet
* - @ c APERIODIC_REPLY if a valid reply is received that has not been
* requested by a command , but should be handled anyway
* ( @ see also fillCommandAndCookieMap ( ) )
*/
2020-05-07 23:38:28 +02:00
virtual ReturnValue_t scanForReply ( const uint8_t * start , size_t len ,
DeviceCommandId_t * foundId , size_t * foundLen ) = 0 ;
2020-04-19 14:03:47 +02:00
/**
* @ brief Interpret a reply from the device .
* @ details
* This is called after scanForReply ( ) found a valid packet , it can be
* assumed that the length and structure is valid .
* This routine extracts the data from the packet into a DataSet and then
* calls handleDeviceTM ( ) , which either sends a TM packet or stores the
* data in the DataPool depending on whether it was an external command .
* No packet length is given , as it should be defined implicitly by the id .
*
* @ param id the id found by scanForReply ( )
* @ param packet
* @ return
* - @ c RETURN_OK when the reply was interpreted .
2020-10-12 18:18:41 +02:00
* - @ c IGNORE_REPLY_DATA Ignore the reply and don ' t reset reply cycle
* counter .
2020-04-19 14:03:47 +02:00
* - @ c RETURN_FAILED when the reply could not be interpreted ,
* e . g . logical errors or range violations occurred
*/
virtual ReturnValue_t interpretDeviceReply ( DeviceCommandId_t id ,
const uint8_t * packet ) = 0 ;
2020-04-19 16:10:44 +02:00
/**
2020-07-16 11:56:48 +02:00
* @ brief fill the # DeviceCommandMap and # DeviceReplyMap
2020-04-19 16:10:44 +02:00
* called by the initialize ( ) of the base class
* @ details
* This is used to let the base class know which replies are expected .
* There are different scenarios regarding this :
*
* - " Normal " commands . These are commands , that trigger a direct reply
* from the device . In this case , the id of the command should be added
* to the command map with a commandData_t where maxDelayCycles is set
* to the maximum expected number of PST cycles the reply will take .
* Then , scanForReply returns the id of the command and the base class
* can handle time - out and missing replies .
*
* - Periodic , unrequested replies . These are replies that , once enabled ,
* are sent by the device on its own in a defined interval .
* In this case , the id of the reply or a placeholder id should be added
* to the deviceCommandMap with a commandData_t where maxDelayCycles is
* set to the maximum expected number of PST cycles between two replies
* ( also a tolerance should be added , as an FDIR message will be
* generated if it is missed ) .
* From then on , the base class handles the reception .
* Then , scanForReply returns the id of the reply or the placeholder id
* and the base class will take care of checking that all replies are
* received and the interval is correct .
*
* - Aperiodic , unrequested replies . These are replies that are sent
* by the device without any preceding command and not in a defined
* interval . These are not entered in the deviceCommandMap but
* handled by returning @ c APERIODIC_REPLY in scanForReply ( ) .
*/
virtual void fillCommandAndReplyMap ( ) = 0 ;
/**
* This is a helper method to facilitate inserting entries in the command map .
* @ param deviceCommand Identifier of the command to add .
* @ param maxDelayCycles The maximum number of delay cycles the command
* waits until it times out .
2020-10-12 18:18:41 +02:00
* @ param replyLen Will be supplied to the requestReceiveMessage call of
* the communication interface .
2020-04-19 16:10:44 +02:00
* @ param periodic Indicates if the command is periodic ( i . e . it is sent
* by the device repeatedly without request ) or not . Default is aperiodic ( 0 )
* @ return - @ c RETURN_OK when the command was successfully inserted ,
* - @ c RETURN_FAILED else .
*/
ReturnValue_t insertInCommandAndReplyMap ( DeviceCommandId_t deviceCommand ,
2020-10-12 18:18:41 +02:00
uint16_t maxDelayCycles ,
LocalPoolDataSetBase * replyDataSet = nullptr ,
size_t replyLen = 0 , bool periodic = false ,
2020-04-19 16:10:44 +02:00
bool hasDifferentReplyId = false , DeviceCommandId_t replyId = 0 ) ;
/**
* @ brief This is a helper method to insert replies in the reply map .
* @ param deviceCommand Identifier of the reply to add .
* @ param maxDelayCycles The maximum number of delay cycles the reply waits
* until it times out .
* @ param periodic Indicates if the command is periodic ( i . e . it is sent
* by the device repeatedly without request ) or not . Default is aperiodic ( 0 )
* @ return - @ c RETURN_OK when the command was successfully inserted ,
* - @ c RETURN_FAILED else .
*/
ReturnValue_t insertInReplyMap ( DeviceCommandId_t deviceCommand ,
2020-10-12 18:18:41 +02:00
uint16_t maxDelayCycles , LocalPoolDataSetBase * dataSet = nullptr ,
size_t replyLen = 0 , bool periodic = false ) ;
2020-04-19 16:10:44 +02:00
/**
* @ brief A simple command to add a command to the commandList .
* @ param deviceCommand The command to add
* @ return - @ c RETURN_OK when the command was successfully inserted ,
* - @ c RETURN_FAILED else .
*/
ReturnValue_t insertInCommandMap ( DeviceCommandId_t deviceCommand ) ;
/**
* @ brief This is a helper method to facilitate updating entries
* in the reply map .
* @ param deviceCommand Identifier of the reply to update .
* @ param delayCycles The current number of delay cycles to wait .
* As stated in # fillCommandAndCookieMap , to disable periodic commands ,
* this is set to zero .
* @ param maxDelayCycles The maximum number of delay cycles the reply waits
* until it times out . By passing 0 the entry remains untouched .
* @ param periodic Indicates if the command is periodic ( i . e . it is sent
* by the device repeatedly without request ) or not . Default is aperiodic ( 0 ) .
* Warning : The setting always overrides the value that was entered in the map .
* @ return - @ c RETURN_OK when the command was successfully inserted ,
* - @ c RETURN_FAILED else .
*/
ReturnValue_t updateReplyMapEntry ( DeviceCommandId_t deviceReply ,
uint16_t delayCycles , uint16_t maxDelayCycles ,
2020-06-19 01:05:51 +02:00
bool periodic = false ) ;
2020-04-19 16:10:44 +02:00
2020-10-12 18:18:41 +02:00
ReturnValue_t setReplyDataset ( DeviceCommandId_t replyId ,
LocalPoolDataSetBase * dataset ) ;
2020-04-19 14:03:47 +02:00
/**
* @ brief Can be implemented by child handler to
* perform debugging
* @ details Example : Calling this in performOperation
* to track values like mode .
2020-04-19 16:10:44 +02:00
* @ param positionTracker Provide the child handler a way to know
* where the debugInterface was called
* @ param objectId Provide the child handler object Id to
* specify actions for spefic devices
* @ param parameter Supply a parameter of interest
2020-04-19 14:03:47 +02:00
* Please delete all debugInterface calls in DHB after debugging is finished !
*/
virtual void debugInterface ( uint8_t positionTracker = 0 ,
object_id_t objectId = 0 , uint32_t parameter = 0 ) ;
/**
* Get the time needed to transit from modeFrom to modeTo .
*
* Used for the following transitions :
* modeFrom - > modeTo :
* MODE_ON - > [ MODE_ON , MODE_NORMAL , MODE_RAW , _MODE_POWER_DOWN ]
* MODE_NORMAL - > [ MODE_ON , MODE_NORMAL , MODE_RAW , _MODE_POWER_DOWN ]
* MODE_RAW - > [ MODE_ON , MODE_NORMAL , MODE_RAW , _MODE_POWER_DOWN ]
2020-04-19 16:10:44 +02:00
* _MODE_START_UP - > MODE_ON ( do not include time to set the switches ,
* the base class got you covered )
2020-04-19 14:03:47 +02:00
*
* The default implementation returns 0 !
* @ param modeFrom
* @ param modeTo
* @ return time in ms
*/
2020-12-22 14:11:36 +01:00
virtual uint32_t getTransitionDelayMs ( Mode_t modeFrom , Mode_t modeTo ) = 0 ;
2020-04-19 14:03:47 +02:00
/**
* Return the switches connected to the device .
*
* The default implementation returns one switch set in the ctor .
*
* @ param [ out ] switches pointer to an array of switches
* @ param [ out ] numberOfSwitches length of returned array
* @ return
* - @ c RETURN_OK if the parameters were set
* - @ c RETURN_FAILED if no switches exist
*/
virtual ReturnValue_t getSwitches ( const uint8_t * * switches ,
uint8_t * numberOfSwitches ) ;
2020-04-19 22:17:14 +02:00
2020-07-16 11:56:48 +02:00
/**
* This function is used to initialize the local housekeeping pool
* entries . The default implementation leaves the pool empty .
* @ param localDataPoolMap
* @ return
*/
2020-10-12 18:18:41 +02:00
virtual ReturnValue_t initializeLocalDataPool ( LocalDataPool & localDataPoolMap ,
LocalDataPoolManager & poolManager ) override ;
2020-07-16 11:56:48 +02:00
2021-01-12 00:13:49 +01:00
2020-07-16 11:56:48 +02:00
/** Get the HK manager object handle */
2021-01-12 14:08:51 +01:00
//LocalDataPoolManager* getHkManagerHandle() override;
2021-01-11 21:31:03 +01:00
2021-01-11 22:27:24 +01:00
ProvidesDataPoolSubscriptionIF * getSubscriptionInterface ( ) override ;
2020-07-16 11:56:48 +02:00
2021-01-12 14:08:51 +01:00
AccessPoolManagerIF * getAccessorHandle ( ) override ;
2021-01-12 00:13:49 +01:00
2020-04-19 22:17:14 +02:00
/**
* @ brief Hook function for child handlers which is called once per
* performOperation ( ) . Default implementation is empty .
*/
virtual void performOperationHook ( ) ;
2020-10-12 18:18:41 +02:00
2020-04-19 14:03:47 +02:00
public :
2020-10-12 18:18:41 +02:00
/** Explicit interface implementation of getObjectId */
virtual object_id_t getObjectId ( ) const override ;
2020-04-19 14:03:47 +02:00
/**
* @ param parentQueueId
*/
virtual void setParentQueue ( MessageQueueId_t parentQueueId ) ;
2016-06-15 23:48:41 +02:00
2020-05-17 15:47:17 +02:00
/** @brief Implementation required for HasActionIF */
2016-06-15 23:48:41 +02:00
ReturnValue_t executeAction ( ActionId_t actionId ,
2020-05-17 15:43:45 +02:00
MessageQueueId_t commandedBy , const uint8_t * data ,
2020-07-16 11:56:48 +02:00
size_t size ) override ;
2020-05-17 15:47:17 +02:00
2016-06-15 23:48:41 +02:00
Mode_t getTransitionSourceMode ( ) const ;
Submode_t getTransitionSourceSubMode ( ) const ;
virtual void getMode ( Mode_t * mode , Submode_t * submode ) ;
HealthState getHealth ( ) ;
ReturnValue_t setHealth ( HealthState health ) ;
virtual ReturnValue_t getParameter ( uint8_t domainId , uint16_t parameterId ,
2018-07-12 16:29:32 +02:00
ParameterWrapper * parameterWrapper ,
2020-07-16 11:56:48 +02:00
const ParameterWrapper * newValues , uint16_t startAtIndex ) override ;
2018-07-13 18:28:26 +02:00
/**
* Implementation of ExecutableObjectIF function
*
* Used to setup the reference of the task , that executes this component
* @ param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF ( PeriodicTaskIF * task_ ) ;
2020-04-19 14:03:47 +02:00
virtual MessageQueueId_t getCommandQueue ( void ) const ;
2016-06-15 23:48:41 +02:00
protected :
/**
2020-07-16 11:56:48 +02:00
* The Returnvalues id of this class , required by HasReturnvaluesIF
2016-06-15 23:48:41 +02:00
*/
2018-07-12 16:29:32 +02:00
static const uint8_t INTERFACE_ID = CLASS_ID : : DEVICE_HANDLER_BASE ;
2016-06-15 23:48:41 +02:00
2020-05-25 23:36:47 +02:00
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE ( 0xA0 ) ;
2020-04-19 14:45:28 +02:00
// Returnvalues for scanForReply()
2020-05-25 23:36:47 +02:00
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE ( 0xB0 ) ; //!< This is used to specify for replies from a device which are not replies to requests
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE ( 0xB1 ) ; //!< Ignore parts of the received packet
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE ( 0xB2 ) ; //!< Ignore full received packet
2020-05-25 23:31:13 +02:00
// Returnvalues for command building
2020-05-25 23:36:47 +02:00
static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE ( 0xC0 ) ; //!< Return this if no command sending in required
static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE ( 0xC2 ) ;
2020-05-25 23:45:32 +02:00
// Returnvalues for getSwitches()
static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE ( 0xD0 ) ;
2020-05-25 23:31:13 +02:00
// Mode handling error Codes
2020-05-25 23:45:32 +02:00
static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE ( 0xE0 ) ;
static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE ( 0xE1 ) ;
2016-06-15 23:48:41 +02:00
static const MessageQueueId_t NO_COMMANDER = 0 ;
2020-07-16 11:56:48 +02:00
/** Pointer to the raw packet that will be sent.*/
2020-04-19 15:15:33 +02:00
uint8_t * rawPacket = nullptr ;
2020-07-16 11:56:48 +02:00
/** Size of the #rawPacket. */
2020-04-19 15:15:33 +02:00
uint32_t rawPacketLen = 0 ;
2016-06-15 23:48:41 +02:00
/**
* The mode the device handler is currently in .
* This should never be changed directly but only with setMode ( )
*/
Mode_t mode ;
/**
* The submode the device handler is currently in .
* This should never be changed directly but only with setMode ( )
*/
Submode_t submode ;
2020-07-16 11:56:48 +02:00
/** This is the counter value from performOperation(). */
2020-04-19 15:15:33 +02:00
uint8_t pstStep = 0 ;
2020-10-12 18:28:07 +02:00
uint8_t lastStep = 0 ;
2020-07-16 11:56:48 +02:00
uint32_t pstIntervalMs = 0 ;
2016-06-15 23:48:41 +02:00
/**
2020-07-16 11:56:48 +02:00
* Wiretapping flag :
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* indicates either that all raw messages to and from the device should be
* sent to # defaultRawReceiver
* or that all device TM should be downlinked to # defaultRawReceiver .
2016-06-15 23:48:41 +02:00
*/
enum WiretappingMode {
OFF = 0 , RAW = 1 , TM = 2
} wiretappingMode ;
/**
2020-07-16 11:56:48 +02:00
* @ brief A message queue that accepts raw replies
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* Statically initialized in initialize ( ) to a configurable object .
* Used when there is no method of finding a recipient , ie raw mode and
* reporting erroneous replies
2016-06-15 23:48:41 +02:00
*/
2020-07-16 11:56:48 +02:00
MessageQueueId_t defaultRawReceiver = MessageQueueIF : : NO_QUEUE ;
2016-06-15 23:48:41 +02:00
store_address_t storedRawData ;
/**
2020-07-16 11:56:48 +02:00
* @ brief The message queue which wants to read all raw traffic
* If # isWiretappingActive all raw communication from and to the device
* will be sent to this queue
2016-06-15 23:48:41 +02:00
*/
2020-04-19 15:15:33 +02:00
MessageQueueId_t requestedRawTraffic = 0 ;
2016-06-15 23:48:41 +02:00
/**
* Pointer to the IPCStore .
* This caches the pointer received from the objectManager in the constructor .
*/
2020-04-19 15:15:33 +02:00
StorageManagerIF * IPCStore = nullptr ;
2020-07-16 11:56:48 +02:00
/** The comIF object ID is cached for the intialize() function */
2016-06-15 23:48:41 +02:00
object_id_t deviceCommunicationId ;
2020-07-16 11:56:48 +02:00
/** Communication object used for device communication */
2020-05-17 15:28:00 +02:00
DeviceCommunicationIF * communicationInterface = nullptr ;
2020-07-16 11:56:48 +02:00
/** Cookie used for communication */
CookieIF * comCookie ;
/** Health helper for HasHealthIF */
HealthHelper healthHelper ;
/** Mode helper for HasModesIF */
ModeHelper modeHelper ;
/** Parameter helper for ReceivesParameterMessagesIF */
ParameterHelper parameterHelper ;
/** Action helper for HasActionsIF */
ActionHelper actionHelper ;
/** Housekeeping Manager */
2020-10-12 18:18:41 +02:00
LocalDataPoolManager hkManager ;
2016-06-15 23:48:41 +02:00
/**
2020-07-16 11:56:48 +02:00
* @ brief Information about commands
2016-06-15 23:48:41 +02:00
*/
2020-04-19 15:01:27 +02:00
struct DeviceCommandInfo {
2020-07-16 11:56:48 +02:00
//! Indicates if the command is already executing.
bool isExecuting ;
//! Dynamic value to indicate how many replies are expected.
//! Inititated with 0.
uint8_t expectedReplies ;
//! if this is != NO_COMMANDER, DHB was commanded externally and shall
//! report everything to commander.
MessageQueueId_t sendReplyTo ;
2020-04-19 15:01:27 +02:00
} ;
using DeviceCommandMap = std : : map < DeviceCommandId_t , DeviceCommandInfo > ;
2020-07-16 11:56:48 +02:00
/**
* Information about commands
*/
DeviceCommandMap deviceCommandMap ;
2020-04-19 15:01:27 +02:00
/**
* @ brief Information about expected replies
2020-07-16 11:56:48 +02:00
* This is used to keep track of pending replies .
2020-04-19 15:01:27 +02:00
*/
struct DeviceReplyInfo {
2020-07-16 11:56:48 +02:00
//! The maximum number of cycles the handler should wait for a reply
//! to this command.
uint16_t maxDelayCycles ;
//! The currently remaining cycles the handler should wait for a reply,
//! 0 means there is no reply expected
uint16_t delayCycles ;
2020-04-19 15:01:27 +02:00
size_t replyLen = 0 ; //!< Expected size of the reply.
2020-07-16 11:56:48 +02:00
//! if this is !=0, the delayCycles will not be reset to 0 but to
//! maxDelayCycles
bool periodic = false ;
//! The dataset used to access housekeeping data related to the
//! respective device reply. Will point to a dataset held by
//! the child handler (if one is specified)
2020-12-22 12:44:55 +01:00
LocalPoolDataSetBase * dataSet = nullptr ;
2020-07-16 11:56:48 +02:00
//! The command that expects this reply.
DeviceCommandMap : : iterator command ;
2020-04-19 15:01:27 +02:00
} ;
using DeviceReplyMap = std : : map < DeviceCommandId_t , DeviceReplyInfo > ;
using DeviceReplyIter = DeviceReplyMap : : iterator ;
2016-06-15 23:48:41 +02:00
/**
2020-07-16 11:56:48 +02:00
* This map is used to check and track correct reception of all replies .
*
* It has multiple use :
* - It stores the information on pending replies . If a command is sent ,
* the DeviceCommandInfo . count is incremented .
* - It is used to time - out missing replies . If a command is sent , the
* DeviceCommandInfo . DelayCycles is set to MaxDelayCycles .
* - It is queried to check if a reply from the device can be interpreted .
* scanForReply ( ) returns the id of the command a reply was found for .
* The reply is ignored in the following cases :
* - No entry for the returned id was found
* - The deviceReplyInfo . delayCycles is = = 0
2016-06-15 23:48:41 +02:00
*/
2020-07-16 11:56:48 +02:00
DeviceReplyMap deviceReplyMap ;
//! The MessageQueue used to receive device handler commands
//! and to send replies.
2020-04-19 15:15:33 +02:00
MessageQueueIF * commandQueue = nullptr ;
2016-06-15 23:48:41 +02:00
2020-12-08 15:59:30 +01:00
DeviceHandlerThermalSet * thermalSet = nullptr ;
2016-06-15 23:48:41 +02:00
/**
2020-10-12 18:18:41 +02:00
* Optional Error code . Can be set in doStartUp ( ) , doShutDown ( ) and
* doTransition ( ) to signal cause for Transition failure .
2016-06-15 23:48:41 +02:00
*/
ReturnValue_t childTransitionFailure ;
2020-10-12 18:18:41 +02:00
/** Counts if communication channel lost a reply, so some missed
* replys can be ignored . */
uint32_t ignoreMissedRepliesCount = 0 ;
2016-06-15 23:48:41 +02:00
2020-10-12 18:18:41 +02:00
/** Pointer to the used FDIR instance. If not provided by child,
* default class is instantiated . */
FailureIsolationBase * fdirInstance ;
2018-07-12 16:29:32 +02:00
HkSwitchHelper hkSwitcher ;
2016-06-15 23:48:41 +02:00
bool defaultFDIRUsed ; //!< To correctly delete the default instance.
bool switchOffWasReported ; //!< Indicates if SWITCH_WENT_OFF was already thrown.
2020-07-16 11:56:48 +02:00
//! Pointer to the task which executes this component, is invalid
//! before setTaskIF was called.
PeriodicTaskIF * executingTask = nullptr ;
2018-07-13 18:28:26 +02:00
2020-12-08 15:59:30 +01:00
//!< Object which switches power on and off.
static object_id_t powerSwitcherId ;
2018-07-12 16:29:32 +02:00
2020-12-08 15:59:30 +01:00
//!< Object which receives RAW data by default.
static object_id_t rawDataReceiverId ;
//!< Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId ;
2020-12-22 12:44:55 +01:00
/**
* @ brief Set all datapool variables that are update periodically in
* normal mode invalid
* @ details
* The default implementation will set all datasets which have been added
* in # fillCommandAndReplyMap to invalid . It will also set all pool
* variables inside the dataset to invalid . The user can override this
* method optionally .
*/
virtual void setNormalDatapoolEntriesInvalid ( ) ;
2020-12-08 15:59:30 +01:00
/**
* Helper function to get pending command . This is useful for devices
* like SPI sensors to identify the last sent command .
2020-12-10 17:18:46 +01:00
* This only returns the command sent in the last SEND_WRITE cycle .
2020-12-08 15:59:30 +01:00
* @ return
*/
DeviceCommandId_t getPendingCommand ( ) const ;
2018-07-12 16:29:32 +02:00
2016-06-15 23:48:41 +02:00
/**
* Helper function to report a missed reply
*
2020-12-08 15:59:30 +01:00
* Can be overwritten by children to act on missed replies or to fake
* reporting Id .
2016-06-15 23:48:41 +02:00
*
* @ param id of the missed reply
*/
virtual void missedReply ( DeviceCommandId_t id ) ;
/**
* Send a reply to a received device handler command .
*
* This also resets # DeviceHandlerCommand to 0.
*
* @ param reply the reply type
* @ param parameter parameter for the reply
*/
void replyReturnvalueToCommand ( ReturnValue_t status ,
uint32_t parameter = 0 ) ;
void replyToCommand ( ReturnValue_t status , uint32_t parameter = 0 ) ;
/**
* Set the device handler mode
*
* Sets # timeoutStart with every call .
*
2020-04-19 16:10:44 +02:00
* Sets # transitionTargetMode if necessary so transitional states can be
* entered from everywhere without breaking the state machine
2016-06-15 23:48:41 +02:00
* ( which relies on a correct # transitionTargetMode ) .
*
* The submode is left unchanged .
*
* @ param newMode
*/
void setMode ( Mode_t newMode ) ;
/**
* @ overload
* @ param submode
*/
void setMode ( Mode_t newMode , Submode_t submode ) ;
/**
* Do the transition to the main modes ( MODE_ON , MODE_NORMAL and MODE_RAW ) .
*
2020-07-16 11:56:48 +02:00
* If the transition is complete , the mode should be set to the target mode ,
* which can be deduced from the current mode which is
2016-06-15 23:48:41 +02:00
* [ _MODE_TO_ON , _MODE_TO_NORMAL , _MODE_TO_RAW ]
*
2020-07-16 11:56:48 +02:00
* The intended target submode is already set .
* The origin submode can be read in subModeFrom .
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* If the transition can not be completed , the child class can try to reach
* an working mode by setting the mode either directly
* or setting the mode to an transitional mode ( TO_ON , TO_NORMAL , TO_RAW )
* if the device needs to be reconfigured .
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* If nothing works , the child class can wait for the timeout and the base
* class will reset the mode to the mode where the transition
2016-06-15 23:48:41 +02:00
* originated from ( the child should report the reason for the failed transition ) .
*
2020-07-16 11:56:48 +02:00
* The intended way to send commands is to set a flag ( enum ) indicating
* which command is to be sent here and then to check in
* buildTransitionCommand ( ) for the flag . This flag can also be used by
* doStartUp ( ) and doShutDown ( ) to get a nice and clean implementation of
* buildTransitionCommand ( ) without switching through modes .
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* When the the condition for the completion of the transition is met , the
* mode can be set , for example in the scanForReply ( ) function .
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* The default implementation goes into the target mode directly .
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* # transitionFailure can be set to a failure code indicating the reason
* for a failed transition
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* @ param modeFrom
* The mode the transition originated from :
* [ MODE_ON , MODE_NORMAL , MODE_RAW and _MODE_POWER_DOWN ( if the mode changed
* from _MODE_START_UP to _MODE_TO_ON ) ]
2016-06-15 23:48:41 +02:00
* @ param subModeFrom the subMode of modeFrom
*/
virtual void doTransition ( Mode_t modeFrom , Submode_t subModeFrom ) ;
/**
* @ param mode
* @ param submode
* @ return
* - @ c RETURN_OK if valid
* - @ c RETURN_FAILED if invalid
*/
virtual ReturnValue_t isModeCombinationValid ( Mode_t mode ,
Submode_t submode ) ;
/**
2020-12-22 12:44:55 +01:00
* Get the communication action for the current step .
2016-06-15 23:48:41 +02:00
* The step number can be read from # pstStep .
2020-12-22 12:44:55 +01:00
* @ return The communication action to execute in this step
2016-06-15 23:48:41 +02:00
*/
2020-10-12 18:28:07 +02:00
virtual CommunicationAction getComAction ( ) ;
2016-06-15 23:48:41 +02:00
/**
* Build the device command to send for raw mode .
*
2020-12-08 15:59:30 +01:00
* This is only called in @ c MODE_RAW . It is for the rare case that in
* raw mode packets are to be sent by the handler itself . It is NOT needed
* for the raw commanding service . Its only current use is in the STR
* handler which gets its raw packets from a different source .
* Also it can be used for transitional commands , to get the device ready
* for @ c MODE_RAW
2016-06-15 23:48:41 +02:00
*
2020-12-08 15:59:30 +01:00
* As it is almost never used , there is a default implementation
* returning @ c NOTHING_TO_SEND .
2016-06-15 23:48:41 +02:00
*
2020-12-08 15:59:30 +01:00
* # rawPacket and # rawPacketLen must be set by this method to the packet
* to be sent .
2016-06-15 23:48:41 +02:00
*
* @ param [ out ] id the device command id built
* @ return
* - @ c RETURN_OK when a command is to be sent
* - not @ c NOTHING_TO_SEND when no command is to be sent
*/
virtual ReturnValue_t buildChildRawCommand ( ) ;
/**
* Returns the delay cycle count of a reply .
* A count ! = 0 indicates that the command is already executed .
* @ param deviceCommand The command to look for
2020-12-08 15:59:30 +01:00
* @ return
* The current delay count . If the command does not exist ( should never
* happen ) it returns 0.
2016-06-15 23:48:41 +02:00
*/
uint8_t getReplyDelayCycles ( DeviceCommandId_t deviceCommand ) ;
/**
* Construct a command reply containing a raw reply .
*
* It gets space in the # IPCStore , copies data there , then sends a raw reply
* containing the store address .
*
2020-12-22 12:44:55 +01:00
* This method is virtual , as devices can have different channels to send
* raw replies
2016-06-15 23:48:41 +02:00
*
* @ param data data to send
* @ param len length of @ c data
* @ param sendTo the messageQueueId of the one to send to
2020-12-08 15:59:30 +01:00
* @ param isCommand marks the raw data as a command , the message then
* will be of type raw_command
2016-06-15 23:48:41 +02:00
*/
virtual void replyRawData ( const uint8_t * data , size_t len ,
MessageQueueId_t sendTo , bool isCommand = false ) ;
2018-07-12 16:29:32 +02:00
/**
2020-12-08 15:59:30 +01:00
* Calls replyRawData ( ) with # defaultRawReceiver , but checks if wiretapping
* is active and if so , does not send the data as the wiretapping will have
* sent it already
2018-07-12 16:29:32 +02:00
*/
void replyRawReplyIfnotWiretapped ( const uint8_t * data , size_t len ) ;
2016-06-15 23:48:41 +02:00
/**
2020-12-22 12:44:55 +01:00
* @ brief Notify child about mode change .
2016-06-15 23:48:41 +02:00
*/
virtual void modeChanged ( void ) ;
/**
* Enable the reply checking for a command
*
2020-12-08 15:59:30 +01:00
* Is only called , if the command was sent ( i . e . the getWriteReply was
* successful ) . Must ensure that all replies are activated and correctly
* linked to the command that initiated it .
* The default implementation looks for a reply with the same id as the
* command id in the replyMap or uses the alternativeReplyId if flagged so .
* When found , copies maxDelayCycles to delayCycles in the reply information
* and sets the command to expect one reply .
2016-06-15 23:48:41 +02:00
*
2020-04-19 15:01:27 +02:00
* Can be overwritten by the child , if a command activates multiple replies
* or replyId differs from commandId .
2016-06-15 23:48:41 +02:00
* Notes for child implementations :
2020-12-08 15:59:30 +01:00
* - If the command was not found in the reply map ,
* NO_REPLY_EXPECTED MUST be returned .
2016-06-15 23:48:41 +02:00
* - A failure code may be returned if something went fundamentally wrong .
*
* @ param deviceCommand
* @ return - RETURN_OK if a reply was activated .
2020-04-19 15:01:27 +02:00
* - NO_REPLY_EXPECTED if there was no reply found . This is not an
* error case as many commands do not expect a reply .
2016-06-15 23:48:41 +02:00
*/
virtual ReturnValue_t enableReplyInReplyMap ( DeviceCommandMap : : iterator cmd ,
uint8_t expectedReplies = 1 , bool useAlternateId = false ,
DeviceCommandId_t alternateReplyID = 0 ) ;
/**
2020-12-22 12:44:55 +01:00
* Get the state of the PCDU switches in the local datapool
2016-06-15 23:48:41 +02:00
* @ return
2020-12-08 15:59:30 +01:00
* - @ c PowerSwitchIF : : SWITCH_ON if all switches specified
* by # switches are on
* - @ c PowerSwitchIF : : SWITCH_OFF one of the switches specified by
* # switches are off
* - @ c PowerSwitchIF : : RETURN_FAILED if an error occured
2016-06-15 23:48:41 +02:00
*/
ReturnValue_t getStateOfSwitches ( void ) ;
2018-07-12 16:29:32 +02:00
/**
* build a list of sids and pass it to the # hkSwitcher
*/
virtual void changeHK ( Mode_t mode , Submode_t submode , bool enable ) ;
2016-06-15 23:48:41 +02:00
/**
2020-12-08 15:59:30 +01:00
* Children can overwrite this function to suppress checking of the
* command Queue
2016-06-15 23:48:41 +02:00
*
2020-12-08 15:59:30 +01:00
* This can be used when the child does not want to receive a command in
* a certain situation . Care must be taken that checking is not
* permanentely disabled as this would render the handler unusable .
2016-06-15 23:48:41 +02:00
*
* @ return whether checking the queue should NOT be done
*/
virtual bool dontCheckQueue ( ) ;
Mode_t getBaseMode ( Mode_t transitionMode ) ;
bool isAwaitingReply ( ) ;
void handleDeviceTM ( SerializeIF * dataSet , DeviceCommandId_t commandId ,
2018-07-12 16:29:32 +02:00
bool neverInDataPool = false , bool forceDirectTm = false ) ;
2016-06-15 23:48:41 +02:00
virtual ReturnValue_t checkModeCommand ( Mode_t mode , Submode_t submode ,
uint32_t * msToReachTheMode ) ;
2020-10-12 18:18:41 +02:00
/* HasModesIF overrides */
virtual void startTransition ( Mode_t mode , Submode_t submode ) override ;
virtual void setToExternalControl ( ) override ;
virtual void announceMode ( bool recursive ) override ;
2016-06-15 23:48:41 +02:00
virtual ReturnValue_t letChildHandleMessage ( CommandMessage * message ) ;
/**
2020-10-12 18:18:41 +02:00
* Overwrites SystemObject : : triggerEvent in order to inform FDIR " Helper "
* faster about executed events .
2016-06-15 23:48:41 +02:00
* This is a bit sneaky , but improves responsiveness of the device FDIR .
* @ param event The event to be thrown
* @ param parameter1 Optional parameter 1
* @ param parameter2 Optional parameter 2
*/
void triggerEvent ( Event event , uint32_t parameter1 = 0 ,
uint32_t parameter2 = 0 ) ;
/**
* Same as triggerEvent , but for forwarding if object is used as proxy .
*/
virtual void forwardEvent ( Event event , uint32_t parameter1 = 0 ,
uint32_t parameter2 = 0 ) const ;
/**
2020-12-08 15:59:30 +01:00
* Checks state of switches in conjunction with mode and triggers an event
* if they don ' t fit .
2016-06-15 23:48:41 +02:00
*/
virtual void checkSwitchState ( ) ;
/**
2020-12-08 15:59:30 +01:00
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in OFF mode .
2016-06-15 23:48:41 +02:00
*/
virtual void doOffActivity ( ) ;
/**
2020-12-08 15:59:30 +01:00
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in ON mode .
2016-06-15 23:48:41 +02:00
*/
virtual void doOnActivity ( ) ;
/**
* Checks if current mode is transitional mode .
* @ return true if mode is transitional , false else .
*/
bool isTransitionalMode ( ) ;
/**
* Checks if current handler state allows reception of external device commands .
* Default implementation allows commands only in plain MODE_ON and MODE_NORMAL .
* @ return RETURN_OK if commands are accepted , anything else otherwise .
*/
virtual ReturnValue_t acceptExternalDeviceCommands ( ) ;
bool commandIsExecuting ( DeviceCommandId_t commandId ) ;
/**
2020-07-16 11:56:48 +02:00
* set all switches returned by getSwitches ( )
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* @ param onOff on = = @ c SWITCH_ON ; off ! = @ c SWITCH_ON
2018-07-12 16:29:32 +02:00
*/
2020-07-16 11:56:48 +02:00
void commandSwitch ( ReturnValue_t onOff ) ;
2018-07-12 16:29:32 +02:00
private :
2016-06-15 23:48:41 +02:00
/**
* State a cookie is in .
*
* Used to keep track of the state of the RMAP communication .
*/
enum CookieState_t {
COOKIE_UNUSED , //!< The Cookie is unused
COOKIE_WRITE_READY , //!< There's data available to send.
COOKIE_READ_SENT , //!< A sendRead command was sent with this cookie
COOKIE_WRITE_SENT //!< A sendWrite command was sent with this cookie
} ;
/**
* Information about a cookie .
*
2020-12-08 15:59:30 +01:00
* This is stored in a map for each cookie , to not only track the state ,
* but also information about the sent command . Tracking this information
* is needed as the state of a commandId ( waiting for reply ) is done when a
* write reply is received .
2016-06-15 23:48:41 +02:00
*/
struct CookieInfo {
CookieState_t state ;
DeviceCommandMap : : iterator pendingCommand ;
} ;
/**
2020-07-16 11:56:48 +02:00
* @ brief Info about the # cookie
2016-06-15 23:48:41 +02:00
* Used to track the state of the communication
*/
CookieInfo cookieInfo ;
2020-07-16 11:56:48 +02:00
/** the object used to set power switches */
PowerSwitchIF * powerSwitcher = nullptr ;
2020-10-12 18:18:41 +02:00
/** HK destination can also be set individually */
object_id_t hkDestination = objects : : NO_OBJECT ;
2016-06-15 23:48:41 +02:00
/**
2020-07-16 11:56:48 +02:00
* @ brief Used for timing out mode transitions .
2016-06-15 23:48:41 +02:00
* Set when setMode ( ) is called .
*/
2020-04-19 15:15:33 +02:00
uint32_t timeoutStart = 0 ;
2016-06-15 23:48:41 +02:00
2020-10-12 18:18:41 +02:00
bool setStartupImmediately = false ;
2016-06-15 23:48:41 +02:00
/**
* Delay for the current mode transition , used for time out
*/
uint32_t childTransitionDelay ;
/**
2020-07-16 11:56:48 +02:00
* @ brief The mode the current transition originated from
2016-06-15 23:48:41 +02:00
*
2021-01-08 16:14:11 +01:00
* This is private so the child can not change it and mess up the timeouts
2016-06-15 23:48:41 +02:00
*
2020-07-16 11:56:48 +02:00
* IMPORTANT : This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP ! !
* ( it is _MODE_POWER_DOWN during this modes )
2016-06-15 23:48:41 +02:00
*
* is element of [ MODE_ON , MODE_NORMAL , MODE_RAW ]
*/
Mode_t transitionSourceMode ;
/**
* the submode of the source mode during a transition
*/
Submode_t transitionSourceSubMode ;
/**
* read the command queue
*/
void readCommandQueue ( void ) ;
/**
* Handle the device handler mode .
*
2020-12-08 15:59:30 +01:00
* - checks whether commands are valid for the current mode , rejects
* them accordingly
* - checks whether commanded mode transitions are required and calls
* handleCommandedModeTransition ( )
* - does the necessary action for the current mode or calls
* doChildStateMachine in modes @ c MODE_TO_ON and @ c MODE_TO_OFF
* - actions that happen in transitions ( e . g . setting a timeout ) are
* handled in setMode ( )
2016-06-15 23:48:41 +02:00
*/
void doStateMachine ( void ) ;
void buildRawDeviceCommand ( CommandMessage * message ) ;
void buildInternalCommand ( void ) ;
/**
* Decrement the counter for the timout of replies .
*
2020-12-08 15:59:30 +01:00
* This is called at the beginning of each cycle . It checks whether a
* reply has timed out ( that means a reply was expected but not received ) .
2016-06-15 23:48:41 +02:00
*/
void decrementDeviceReplyMap ( void ) ;
/**
* Convenience function to handle a reply .
*
2020-12-08 15:59:30 +01:00
* Called after scanForReply ( ) has found a packet . Checks if the found ID
* is in the # deviceCommandMap , if so , calls
* # interpretDeviceReply for further action .
2016-06-15 23:48:41 +02:00
*
* It also resets the timeout counter for the command id .
*
* @ param data the found packet
* @ param id the found id
2018-07-12 16:29:32 +02:00
* @ foundLen the length of the packet
2016-06-15 23:48:41 +02:00
*/
2018-07-12 16:29:32 +02:00
void handleReply ( const uint8_t * data , DeviceCommandId_t id , uint32_t foundLen ) ;
2016-06-15 23:48:41 +02:00
void replyToReply ( DeviceReplyMap : : iterator iter , ReturnValue_t status ) ;
/**
* Build and send a command to the device .
*
2020-10-12 18:18:41 +02:00
* This routine checks whether a raw or direct command has been received ,
* checks the content of the received command and calls
* buildCommandFromCommand ( ) for direct commands or sets # rawpacket
* to the received raw packet .
* If no external command is received or the received command is invalid and
* the current mode is @ c MODE_NORMAL or a transitional mode , it asks the
* child class to build a command ( via getNormalDeviceCommand ( ) or
* getTransitionalDeviceCommand ( ) and buildCommand ( ) ) and
2016-06-15 23:48:41 +02:00
* sends the command via RMAP .
*/
void doSendWrite ( void ) ;
/**
* Check if the RMAP sendWrite action was successful .
*
* Depending on the result , the following is done
2021-01-08 16:14:11 +01:00
* - if the device command was external commanded , a reply is sent
* indicating the result
2016-06-15 23:48:41 +02:00
* - if the action was successful , the reply timout counter is initialized
*/
void doGetWrite ( void ) ;
/**
* Send a RMAP getRead command .
*
* The size of the getRead command is # maxDeviceReplyLen .
* This is always executed , independently from the current mode .
*/
void doSendRead ( void ) ;
/**
* Check the getRead reply and the contained data .
*
2021-01-08 16:14:11 +01:00
* If data was received scanForReply ( ) and , if successful , handleReply ( )
* are called . If the current mode is @ c MODE_RAW , the received packet
* is sent to the commanding object via commandQueue .
2016-06-15 23:48:41 +02:00
*/
void doGetRead ( void ) ;
/**
* Retrive data from the # IPCStore .
*
* @ param storageAddress
* @ param [ out ] data
* @ param [ out ] len
* @ return
* - @ c RETURN_OK @ c data is valid
2020-12-08 15:59:30 +01:00
* - @ c RETURN_FAILED IPCStore is nullptr
2016-06-15 23:48:41 +02:00
* - the return value from the IPCStore if it was not @ c RETURN_OK
*/
ReturnValue_t getStorageData ( store_address_t storageAddress , uint8_t * * data ,
uint32_t * len ) ;
/**
2021-01-08 16:14:11 +01:00
* @ param modeTo either @ c MODE_ON , MODE_NORMAL or MODE_RAW , nothing else !
2016-06-15 23:48:41 +02:00
*/
void setTransition ( Mode_t modeTo , Submode_t submodeTo ) ;
/**
* calls the right child function for the transitional submodes
*/
void callChildStatemachine ( ) ;
ReturnValue_t handleDeviceHandlerMessage ( CommandMessage * message ) ;
2020-07-16 11:56:48 +02:00
2020-10-12 18:18:41 +02:00
virtual LocalPoolDataSetBase * getDataSetHandle ( sid_t sid ) override ;
2020-07-16 13:00:22 +02:00
2020-10-12 18:18:41 +02:00
virtual dur_millis_t getPeriodicOperationFrequency ( ) const override ;
2016-06-15 23:48:41 +02:00
2020-10-12 18:18:41 +02:00
void parseReply ( const uint8_t * receivedData ,
size_t receivedDataLen ) ;
2020-12-08 15:59:30 +01:00
void handleTransitionToOnMode ( Mode_t commandedMode ,
Submode_t commandedSubmode ) ;
2021-01-08 16:14:11 +01:00
2021-01-12 13:18:18 +01:00
void printWarningOrError ( sif : : OutputTypes errorType ,
2021-01-08 16:14:11 +01:00
const char * functionName ,
ReturnValue_t errorCode = HasReturnvaluesIF : : RETURN_FAILED ,
const char * errorPrint = nullptr ) ;
2020-10-12 18:18:41 +02:00
} ;
2016-06-15 23:48:41 +02:00
2020-10-12 18:18:41 +02:00
# endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */