Files
2025-01-12 18:08:57 +01:00

84 lines
2.4 KiB
C++

#include "graphics/common/ResponseHandler.h"
#include "Arduino.h"
#include "util/ILog.h"
uint32_t ResponseHandler::rollingPacketId = 0;
/**
* @brief Construct a new Response Handler:: Response Handler object
*
* @param timeout
*/
ResponseHandler::ResponseHandler(uint32_t timeout) : requestIdCounter(0), maxTime(timeout)
{
rollingPacketId = random(UINT32_MAX & 0x7fffffff);
}
uint32_t ResponseHandler::addRequest(uint32_t id, RequestType type, void *cookie, Callback cb)
{
requestIdCounter++;
uint32_t requestId = generatePacketId();
pendingRequest[requestId] = Request{.id = id, .timestamp = millis(), .type = type, .cookie = cookie, .cb = cb};
return requestId;
}
ResponseHandler::Request ResponseHandler::findRequest(uint32_t requestId, RequestType match, int32_t pass)
{
const auto it = pendingRequest.find(requestId);
if (it != pendingRequest.end()) {
Request &req = it->second;
if (req.cb && pass != -1 && (match == anyRequest || match == req.type))
req.cb(req, found, pass);
return req;
}
return Request{};
}
ResponseHandler::Request ResponseHandler::removeRequest(uint32_t requestId, RequestType match, int32_t pass)
{
Request req{};
const auto it = pendingRequest.find(requestId);
if (it != pendingRequest.end()) {
req = it->second;
ILOG_DEBUG("removing request %08x", it->first);
if (req.cb && pass != -1 && (match == anyRequest || match == req.type))
req.cb(req, removed, pass);
pendingRequest.erase(it);
}
return req;
}
/**
* @brief: Generate a unique packet id
*
*/
uint32_t ResponseHandler::generatePacketId(void)
{
rollingPacketId++;
rollingPacketId &= UINT32_MAX >> 22;
return rollingPacketId | random(UINT32_MAX & 0x7fffffff) << 10;
}
/**
* @brief Garbage collection that is periodically called.
* removes all pending requests that timed out
*
*/
void ResponseHandler::task_handler(void)
{
if (pendingRequest.size())
ILOG_DEBUG("ResponseHandler has %d pending request(s)", pendingRequest.size());
auto it = pendingRequest.begin();
while (it != pendingRequest.end()) {
Request &req = it->second;
if (req.timestamp + maxTime < millis()) {
ILOG_DEBUG("removing timed out request %08x", it->first);
if (req.cb)
req.cb(req, timeout, 0);
it = pendingRequest.erase(it);
} else {
it++;
}
}
}