Restructured header file

Abstract functions are closer to the top
because they must be implemented and documentation
should be near the top.
Important virtual functions moved up too.
Additional documentation added
This commit is contained in:
Robin Müller 2020-01-20 23:00:23 +01:00
parent 424c82ce16
commit dba26baee6
2 changed files with 306 additions and 286 deletions

View File

@ -90,6 +90,85 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
return RETURN_OK;
}
ReturnValue_t DeviceHandlerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
communicationInterface = objectManager->get<DeviceCommunicationIF>(
deviceCommunicationId);
if (communicationInterface == NULL) {
return RETURN_FAILED;
}
result = communicationInterface->open(&cookie, logicalAddress,
maxDeviceReplyLen);
if (result != RETURN_OK) {
return result;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == NULL) {
return RETURN_FAILED;
}
AcceptsDeviceResponsesIF *rawReceiver = objectManager->get<
AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == NULL) {
return RETURN_FAILED;
}
defaultRawReceiver = rawReceiver->getDeviceQueue();
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == NULL) {
return RETURN_FAILED;
}
result = healthHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
return result;
}
result = fdirInstance->initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = parameterHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = hkSwitcher.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
fillCommandAndReplyMap();
//Set temperature target state to NON_OP.
DataSet mySet;
PoolVariable<int8_t> thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_WRITE);
mySet.read();
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
mySet.commit(PoolVariableIF::VALID);
return RETURN_OK;
}
void DeviceHandlerBase::decrementDeviceReplyMap() {
for (std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter =
deviceReplyMap.begin(); iter != deviceReplyMap.end(); iter++) {
@ -454,7 +533,8 @@ void DeviceHandlerBase::doGetWrite() {
if (wiretappingMode == RAW) {
replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true);
}
// We need to distinguish here, because a raw command never expects a reply. (Could be done in eRIRM, but then child implementations need to be careful.
//We need to distinguish here, because a raw command never expects a reply.
//(Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
} else {
//always generate a failure event, so that FDIR knows what's up
@ -474,9 +554,9 @@ void DeviceHandlerBase::doSendRead() {
cookieInfo.state = COOKIE_READ_SENT;
} else {
triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result);
// We can't inform anyone, because we don't know which command was sent last.
// So, we need to wait for a timeout.
// but I think we can allow to ignore one missedReply.
//We can't inform anyone, because we don't know which command was sent last.
//So, we need to wait for a timeout.
//but I think we can allow to ignore one missedReply.
ignoreMissedRepliesCount++;
cookieInfo.state = COOKIE_UNUSED;
}
@ -579,84 +659,6 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress,
}
ReturnValue_t DeviceHandlerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
communicationInterface = objectManager->get<DeviceCommunicationIF>(
deviceCommunicationId);
if (communicationInterface == NULL) {
return RETURN_FAILED;
}
result = communicationInterface->open(&cookie, logicalAddress,
maxDeviceReplyLen);
if (result != RETURN_OK) {
return result;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == NULL) {
return RETURN_FAILED;
}
AcceptsDeviceResponsesIF *rawReceiver = objectManager->get<
AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == NULL) {
return RETURN_FAILED;
}
defaultRawReceiver = rawReceiver->getDeviceQueue();
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == NULL) {
return RETURN_FAILED;
}
result = healthHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
return result;
}
result = fdirInstance->initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = parameterHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = hkSwitcher.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
fillCommandAndReplyMap();
//Set temperature target state to NON_OP.
DataSet mySet;
PoolVariable<int8_t> thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_WRITE);
mySet.read();
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
mySet.commit(PoolVariableIF::VALID);
return RETURN_OK;
}
void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
MessageQueueId_t sendTo, bool isCommand) {
@ -1020,7 +1022,6 @@ void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data,
}
}
ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(
CommandMessage * message) {
ReturnValue_t result;

View File

@ -33,7 +33,6 @@ class StorageManagerIF;
* Contains all devices and the DeviceHandlerBase class.
*/
/**
* @brief This is the abstract base class for device handlers.
* @details
@ -56,6 +55,17 @@ class StorageManagerIF;
* 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).
* 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()
* Other important virtual methods with a default implementation
* are the getTransitionDelay() function and the getSwitches() function
*
* @ingroup devices
*/
@ -75,17 +85,19 @@ public:
* @param setObjectId the ObjectId to pass to the SystemObject() Constructor
* @param maxDeviceReplyLen the length the RMAP getRead call will be sent with
* @param setDeviceSwitch the switch the device is connected to, for devices using two switches, overwrite getSwitches()
* @param deviceCommuncation Communcation Interface object which is used to implement communication functions
* @param thermalStatePoolId
* @param thermalRequestPoolId
* @param fdirInstance
* @param cmdQueueSize
*/
DeviceHandlerBase(uint32_t logicalAddress, object_id_t setObjectId,
uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
object_id_t deviceCommunication, uint32_t thermalStatePoolId =
PoolVariableIF::NO_PARAMETER,
object_id_t deviceCommunication,
uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER,
uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER,
FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20);
virtual MessageQueueId_t getCommandQueue(void) const;
/**
* @brief This function is the device handler base core component and is called periodically.
* @details
@ -117,17 +129,214 @@ public:
*/
virtual ReturnValue_t performOperation(uint8_t counter);
/**
* @brief Initializes the device handler
* @details
* Initialize Device Handler as system object and
* initializes all important helper classes.
* Calls fillCommandAndReplyMap().
* @return
*/
virtual ReturnValue_t initialize();
/**
*
* @param parentQueueId
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
/**
* Destructor.
*/
virtual ~DeviceHandlerBase();
protected:
/**
* This is used to let the child class handle the transition from mode @c _MODE_START_UP to @c MODE_ON
*
* 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.
*
* 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
*/
virtual void doStartUp() = 0;
/**
* This is used to let the child class handle the transition from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN
*
* 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
*/
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 returned depending on the submode.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
*
* @param[out] id the device command id that has been built
* @return
* - @c RETURN_OK when a command is to be sent
* - not @c RETURN_OK when no command is to be sent
*/
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,
* @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition()
*
* 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.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
*
* @param[out] id the device command id built
* @return
* - @c RETURN_OK when a command is to be sent
* - not @c RETURN_OK when no command is to be sent
*/
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
/**
* Build a device command packet from data supplied by a direct command.
*
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
*
* @param deviceCommand the command to build, already checked against deviceCommandMap
* @param commandData pointer to the data from the direct command
* @param commandDataLen length of commandData
* @return
* - @c RETURN_OK when #rawPacket is valid
* - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent
*/
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData, size_t commandDataLen) = 0;
/**
* @brief fill the #deviceCommandMap
* 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).
* As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. 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.
* When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, DeviceCommandInfo.delayCycles to 0;
* - 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;
/**
* @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, eg 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, eg 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() )
*/
virtual ReturnValue_t scanForReply(const uint8_t *start, uint32_t len,
DeviceCommandId_t *foundId, uint32_t *foundLen) = 0;
/**
* @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 the 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.
* - @c RETURN_FAILED when the reply could not be interpreted, eg. logical errors or range violations occurred
*/
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) = 0;
/**
* @brief Can be implemented by child handler to
* perform debugging
* @details Example: Calling this in performOperation
* to track values like mode.
* @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
* 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]
* _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered)
*
* The default implementation returns 0 !
* @param modeFrom
* @param modeTo
* @return time in ms
*/
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo);
/**
* 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);
public:
/**
* @param parentQueueId
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size);
@ -146,6 +355,8 @@ public:
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF* task_);
virtual MessageQueueId_t getCommandQueue(void) const;
protected:
/**
* The Returnvalues id of this class, required by HasReturnvaluesIF
@ -357,41 +568,6 @@ protected:
*/
void setMode(Mode_t newMode, Submode_t submode);
/**
* This is used to let the child class handle the transition from mode @c _MODE_START_UP to @c MODE_ON
*
* 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.
*
* 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
*/
virtual void doStartUp() = 0;
/**
* This is used to let the child class handle the transition from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN
*
* 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
*/
virtual void doShutDown() = 0;
/**
* Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW).
*
@ -421,24 +597,6 @@ protected:
*/
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
/**
* 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]
* _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered)
*
* The default implementation returns 0;
*
* @param modeFrom
* @param modeTo
* @return time in ms
*/
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo);
/**
* Is the combination of mode and submode valid?
*
@ -460,40 +618,6 @@ protected:
*/
virtual RmapAction_t getRmapAction();
/**
* 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 returned depending on the submode.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
*
* @param[out] id the device command id that has been built
* @return
* - @c RETURN_OK when a command is to be sent
* - not @c RETURN_OK when no command is to be sent
*/
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,
* @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition()
*
* 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.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
*
* @param[out] id the device command id built
* @return
* - @c RETURN_OK when a command is to be sent
* - not @c RETURN_OK when no command is to be sent
*/
virtual ReturnValue_t buildTransitionDeviceCommand(
DeviceCommandId_t * id) = 0;
/**
* Build the device command to send for raw mode.
*
@ -514,52 +638,6 @@ protected:
*/
virtual ReturnValue_t buildChildRawCommand();
/**
* Build a device command packet from data supplied by a direct command.
*
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
*
* @param deviceCommand the command to build, already checked against deviceCommandMap
* @param commandData pointer to the data from the direct command
* @param commandDataLen length of commandData
* @return
* - @c RETURN_OK when #rawPacket is valid
* - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent
*/
virtual ReturnValue_t buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t * commandData,
size_t commandDataLen) = 0;
/**
* @brief fill the #deviceCommandMap
* 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).
* As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. 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.
* When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, DeviceCommandInfo.delayCycles to 0;
* - 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;
/**
* @brief Can be implemented by child handler to
* perform debugging
* @details Example: Calling this in performOperation
* to track values like mode.
* @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
* 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);
/**
* This is a helper method to facilitate inserting entries in the command map.
@ -608,50 +686,6 @@ protected:
*/
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
/**
* Scans a buffer for a valid reply.
*
* This is used by the base class to check the data received from the RMAP stack for valid packets.
* It only checks if a valid packet starts at @c start.
* It also only checks the structural validy of the packet, eg checksums lengths and protocol data. No
* information check is done, eg 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, eg 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() )
*/
virtual ReturnValue_t scanForReply(const uint8_t *start, uint32_t len,
DeviceCommandId_t *foundId, uint32_t *foundLen) = 0;
/**
* Interpret a reply from the device.
*
* 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 the 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.
* - @c RETURN_FAILED when the reply could not be interpreted, eg. logical errors or range violations occurred
*/
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) = 0;
/**
* Construct a command reply containing a raw reply.
*
@ -675,21 +709,6 @@ protected:
*/
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
/**
* 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);
/**
* notify child about mode change
*/