option to use Countdown object to time out replies
This commit is contained in:
parent
b8516b15cb
commit
951c077abc
@ -233,16 +233,27 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||||
|
bool timedOut = false;
|
||||||
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
|
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
|
||||||
if (replyPair.second.delayCycles != 0) {
|
if (replyPair.second.countdown != nullptr && replyPair.second.active) {
|
||||||
|
if (replyPair.second.countdown->hasTimedOut()) {
|
||||||
|
timedOut = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (replyPair.second.delayCycles != 0 && replyPair.second.countdown == nullptr) {
|
||||||
replyPair.second.delayCycles--;
|
replyPair.second.delayCycles--;
|
||||||
if (replyPair.second.delayCycles == 0) {
|
if (replyPair.second.delayCycles == 0) {
|
||||||
if (replyPair.second.periodic) {
|
if (replyPair.second.periodic) {
|
||||||
replyPair.second.delayCycles = replyPair.second.maxDelayCycles;
|
replyPair.second.delayCycles = replyPair.second.maxDelayCycles;
|
||||||
}
|
}
|
||||||
|
timedOut = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timedOut) {
|
||||||
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
||||||
missedReply(replyPair.first);
|
missedReply(replyPair.first);
|
||||||
}
|
timedOut = false;
|
||||||
|
replyPair.second.active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +370,6 @@ void DeviceHandlerBase::doStateMachine() {
|
|||||||
setMode(MODE_OFF);
|
setMode(MODE_OFF);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
||||||
setMode(MODE_ERROR_ON);
|
setMode(MODE_ERROR_ON);
|
||||||
@ -408,20 +418,22 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s
|
|||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
||||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
||||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
|
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
|
||||||
|
Countdown* countdown) {
|
||||||
// No need to check, as we may try to insert multiple times.
|
// No need to check, as we may try to insert multiple times.
|
||||||
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
||||||
if (hasDifferentReplyId) {
|
if (hasDifferentReplyId) {
|
||||||
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
|
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic, countdown);
|
||||||
} else {
|
} else {
|
||||||
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic);
|
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic,
|
||||||
|
countdown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||||
uint16_t maxDelayCycles,
|
uint16_t maxDelayCycles,
|
||||||
LocalPoolDataSetBase* dataSet, size_t replyLen,
|
LocalPoolDataSetBase* dataSet, size_t replyLen,
|
||||||
bool periodic) {
|
bool periodic, Countdown* countdown) {
|
||||||
DeviceReplyInfo info;
|
DeviceReplyInfo info;
|
||||||
info.maxDelayCycles = maxDelayCycles;
|
info.maxDelayCycles = maxDelayCycles;
|
||||||
info.periodic = periodic;
|
info.periodic = periodic;
|
||||||
@ -429,6 +441,10 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
|||||||
info.replyLen = replyLen;
|
info.replyLen = replyLen;
|
||||||
info.dataSet = dataSet;
|
info.dataSet = dataSet;
|
||||||
info.command = deviceCommandMap.end();
|
info.command = deviceCommandMap.end();
|
||||||
|
info.countdown = countdown;
|
||||||
|
if (info.periodic) {
|
||||||
|
info.active = true;
|
||||||
|
}
|
||||||
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
||||||
if (resultPair.second) {
|
if (resultPair.second) {
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
@ -459,13 +475,13 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
|||||||
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
||||||
if (command->second.useAlternativeReplyId) {
|
if (command->second.useAlternativeReplyId) {
|
||||||
replyId = command->second.alternativeReplyId;
|
replyId = command->second.alternativeReplyId;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
replyId = commandId;
|
replyId = commandId;
|
||||||
}
|
}
|
||||||
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
||||||
if (iter != deviceReplyMap.end()) {
|
if (iter != deviceReplyMap.end()) {
|
||||||
if (iter->second.delayCycles != 0) {
|
if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
|
||||||
|
(iter->second.active && iter->second.countdown != nullptr)) {
|
||||||
return iter->second.replyLen;
|
return iter->second.replyLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,17 +825,18 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
|||||||
|
|
||||||
DeviceReplyInfo* info = &(iter->second);
|
DeviceReplyInfo* info = &(iter->second);
|
||||||
|
|
||||||
if (info->delayCycles != 0) {
|
if ((info->delayCycles != 0 && info->countdown == nullptr) ||
|
||||||
|
(info->active && info->countdown != nullptr)) {
|
||||||
result = interpretDeviceReply(foundId, receivedData);
|
result = interpretDeviceReply(foundId, receivedData);
|
||||||
|
|
||||||
if (result == IGNORE_REPLY_DATA) {
|
if (result == IGNORE_REPLY_DATA) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->periodic) {
|
if (info->active && info->countdown != nullptr) {
|
||||||
info->delayCycles = info->maxDelayCycles;
|
disableTimeoutControlledReply(info);
|
||||||
} else {
|
} else if (info->delayCycles != 0) {
|
||||||
info->delayCycles = 0;
|
disableDelayCyclesControlledReply(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
@ -838,6 +855,24 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceHandlerBase::disableTimeoutControlledReply(DeviceReplyInfo* info) {
|
||||||
|
if (info->periodic) {
|
||||||
|
info->countdown->resetTimer();
|
||||||
|
} else {
|
||||||
|
info->active = false;
|
||||||
|
info->countdown->timeOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceHandlerBase::disableDelayCyclesControlledReply(DeviceReplyInfo* info) {
|
||||||
|
if (info->periodic) {
|
||||||
|
info->delayCycles = info->maxDelayCycles;
|
||||||
|
} else {
|
||||||
|
info->delayCycles = 0;
|
||||||
|
info->active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
|
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
|
||||||
size_t* len) {
|
size_t* len) {
|
||||||
size_t lenTmp;
|
size_t lenTmp;
|
||||||
@ -963,6 +998,10 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap(DeviceCommandMap::iterato
|
|||||||
info->delayCycles = info->maxDelayCycles;
|
info->delayCycles = info->maxDelayCycles;
|
||||||
info->command = command;
|
info->command = command;
|
||||||
command->second.expectedReplies = expectedReplies;
|
command->second.expectedReplies = expectedReplies;
|
||||||
|
if (info->countdown != nullptr) {
|
||||||
|
info->countdown->resetTimer();
|
||||||
|
}
|
||||||
|
info->active = true;
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return NO_REPLY_EXPECTED;
|
return NO_REPLY_EXPECTED;
|
||||||
@ -1197,7 +1236,8 @@ void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) {
|
|||||||
bool DeviceHandlerBase::isAwaitingReply() {
|
bool DeviceHandlerBase::isAwaitingReply() {
|
||||||
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter;
|
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter;
|
||||||
for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) {
|
for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) {
|
||||||
if (iter->second.delayCycles != 0) {
|
if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
|
||||||
|
(iter->second.active && iter->second.countdown != nullptr)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1353,6 +1393,9 @@ uint8_t DeviceHandlerBase::getReplyDelayCycles(DeviceCommandId_t deviceCommand)
|
|||||||
if (iter == deviceReplyMap.end()) {
|
if (iter == deviceReplyMap.end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if (iter->second.countdown != nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return iter->second.delayCycles;
|
return iter->second.delayCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,6 +448,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
||||||
* Please note that periodic replies are disabled by default. You can enable them with
|
* Please note that periodic replies are disabled by default. You can enable them with
|
||||||
* #updatePeriodicReply
|
* #updatePeriodicReply
|
||||||
|
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
|
||||||
|
* to provide a pointer to a Countdown object which will signal the timeout
|
||||||
|
* when expired
|
||||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||||
* - @c RETURN_FAILED else.
|
* - @c RETURN_FAILED else.
|
||||||
*/
|
*/
|
||||||
@ -455,7 +458,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
LocalPoolDataSetBase *replyDataSet = nullptr,
|
LocalPoolDataSetBase *replyDataSet = nullptr,
|
||||||
size_t replyLen = 0, bool periodic = false,
|
size_t replyLen = 0, bool periodic = false,
|
||||||
bool hasDifferentReplyId = false,
|
bool hasDifferentReplyId = false,
|
||||||
DeviceCommandId_t replyId = 0);
|
DeviceCommandId_t replyId = 0,
|
||||||
|
Countdown *countdown = nullptr);
|
||||||
/**
|
/**
|
||||||
* @brief This is a helper method to insert replies in the reply map.
|
* @brief This is a helper method to insert replies in the reply map.
|
||||||
* @param deviceCommand Identifier of the reply to add.
|
* @param deviceCommand Identifier of the reply to add.
|
||||||
@ -465,12 +469,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
||||||
* Please note that periodic replies are disabled by default. You can enable them with
|
* Please note that periodic replies are disabled by default. You can enable them with
|
||||||
* #updatePeriodicReply
|
* #updatePeriodicReply
|
||||||
|
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
|
||||||
|
* to provide a pointer to a Countdown object which will signal the timeout
|
||||||
|
* when expired
|
||||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||||
* - @c RETURN_FAILED else.
|
* - @c RETURN_FAILED else.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
||||||
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
|
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
|
||||||
bool periodic = false);
|
bool periodic = false, Countdown *countdown = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A simple command to add a command to the commandList.
|
* @brief A simple command to add a command to the commandList.
|
||||||
@ -783,6 +790,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
LocalPoolDataSetBase *dataSet = nullptr;
|
LocalPoolDataSetBase *dataSet = nullptr;
|
||||||
//! The command that expects this reply.
|
//! The command that expects this reply.
|
||||||
DeviceCommandMap::iterator command;
|
DeviceCommandMap::iterator command;
|
||||||
|
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
|
||||||
|
//! is also possible specify a countdown
|
||||||
|
Countdown* countdown = nullptr;
|
||||||
|
//! will be set to true when reply is enabled
|
||||||
|
bool active = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>;
|
using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>;
|
||||||
@ -1243,6 +1255,17 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
*/
|
*/
|
||||||
void doGetRead(void);
|
void doGetRead(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles disabling of replies which use a timeout to detect missed replies.
|
||||||
|
*/
|
||||||
|
void disableTimeoutControlledReply(DeviceReplyInfo* info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles disabling of replies which use a number of maximum delay cycles to detect
|
||||||
|
* missed replies.
|
||||||
|
*/
|
||||||
|
void disableDelayCyclesControlledReply(DeviceReplyInfo* info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrive data from the #IPCStore.
|
* Retrive data from the #IPCStore.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user