5 #ifndef UAVCAN_PROTOCOL_FIRMWARE_UPDATE_TRIGGER_HPP_INCLUDED 6 #define UAVCAN_PROTOCOL_FIRMWARE_UPDATE_TRIGGER_HPP_INCLUDED 15 #include <uavcan/protocol/file/BeginFirmwareUpdate.hpp> 54 FirmwareFilePath& out_firmware_file_path) = 0;
76 const protocol::file::BeginFirmwareUpdate::Response& error_response,
77 FirmwareFilePath& out_firmware_file_path) = 0;
90 const protocol::file::BeginFirmwareUpdate::Response& response)
145 enum { DefaultRequestIntervalMs = 1000 };
149 enum { DefaultOutput = 0xFFU };
156 , output(DefaultOutput)
164 output =
min(output, node_id.
get());
192 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Node ID %d could not provide GetNodeInfo response",
int(node_id.
get()));
193 pending_nodes_.
remove(node_id);
198 FirmwareFilePath firmware_file_path;
202 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Node ID %d requires update; file path: %s",
203 int(node_id.
get()), firmware_file_path.
c_str());
204 trySetPendingNode(node_id, firmware_file_path);
208 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Node ID %d does not need update",
int(node_id.
get()));
209 pending_nodes_.
remove(node_id);
215 if (event.
status.
mode == protocol::NodeStatus::MODE_OFFLINE)
239 getNode().registerInternalFailure(
"FirmwareUpdateTrigger OOM");
250 if (s1.
output != NextNodeIDSearchPredicate::DefaultOutput)
252 last_queried_node_id_ = s1.
output;
254 else if (last_queried_node_id_ != 0)
257 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Node selector reset, last value: %d",
int(last_queried_node_id_));
258 last_queried_node_id_ = 0;
263 if (s2.
output != NextNodeIDSearchPredicate::DefaultOutput)
265 last_queried_node_id_ = s2.
output;
272 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Next node ID to query: %d, pending nodes: %u, pending calls: %u",
273 int(last_queried_node_id_), pending_nodes_.
getSize(),
275 return last_queried_node_id_;
282 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Request to %d has timed out, will retry",
283 int(result.
getCallID().server_node_id.get()));
287 FirmwareFilePath*
const old_path = pending_nodes_.
access(result.
getCallID().server_node_id);
294 const bool confirmed =
295 result.
getResponse().error == protocol::file::BeginFirmwareUpdate::Response::ERROR_OK ||
296 result.
getResponse().error == protocol::file::BeginFirmwareUpdate::Response::ERROR_IN_PROGRESS;
300 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Node %d confirmed the update request",
301 int(result.
getCallID().server_node_id.get()));
311 const bool update_needed =
316 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Node %d does not need retry",
317 int(result.
getCallID().server_node_id.get()));
332 const NodeID node_id = pickNextNodeID();
338 FirmwareFilePath*
const path = pending_nodes_.
access(node_id);
345 protocol::file::BeginFirmwareUpdate::Request req;
347 req.source_node_id = getNode().getNodeID().get();
348 if (!common_path_prefix_.
empty())
350 req.image_file_remote_path.path += common_path_prefix_.
c_str();
351 req.image_file_remote_path.path.push_back(protocol::file::Path::SEPARATOR);
353 req.image_file_remote_path.path += path->
c_str();
355 UAVCAN_TRACE(
"FirmwareUpdateTrigger",
"Request to %d with path: %s",
356 int(node_id.
get()), req.image_file_remote_path.path.c_str());
358 const int call_res = begin_fw_update_client_.
call(node_id, req);
361 getNode().registerInternalFailure(
"FirmwareUpdateTrigger call");
368 , begin_fw_update_client_(node)
371 , pending_nodes_(node.getAllocator())
373 , last_queried_node_id_(0)
404 node_info_retriever_ = &node_info_retriever;
415 common_path_prefix_ = arg_common_path_prefix;
417 if (!common_path_prefix_.
empty() &&
418 *(common_path_prefix_.
end() - 1) == protocol::file::Path::SEPARATOR)
426 res = begin_fw_update_client_.
init(priority);
447 request_interval_ = interval;
467 const unsigned ret = pending_nodes_.
getSize();
476 #endif // Include guard void remove(const Key &key)
void handleBeginFirmwareUpdateResponse(const ServiceCallResult< protocol::file::BeginFirmwareUpdate > &result)
MonotonicDuration getRequestInterval() const
IFirmwareVersionChecker::FirmwareFilePath FirmwareFilePath
const char * c_str() const
ServiceCallID getCallID() const
Map< NodeID, FirmwareFilePath > pending_nodes_
EnableIf< sizeof((reinterpret_cast< const R * >0)) -> size()) &&sizeof((*(reinterpret_cast< const R *>(0)))[0])
virtual ~IFirmwareVersionChecker()
int start(NodeInfoRetriever &node_info_retriever, const FirmwareFilePath &arg_common_path_prefix=FirmwareFilePath(), const TransferPriority priority=TransferPriority::OneHigherThanLowest)
virtual void handleNodeInfoUnavailable(NodeID node_id)
virtual void handleNodeInfoRetrieved(const NodeID node_id, const protocol::GetNodeInfo::Response &node_info)
void startPeriodic(MonotonicDuration period)
virtual bool shouldRetryFirmwareUpdate(NodeID node_id, const protocol::file::BeginFirmwareUpdate::Response &error_response, FirmwareFilePath &out_firmware_file_path)=0
int addListener(INodeInfoListener *listener)
bool isTimerRunning() const
Value * insert(const Key &key, const Value &value)
const FirmwareUpdateTrigger & owner
ServiceClient< protocol::file::BeginFirmwareUpdate, BeginFirmwareUpdateResponseCallback > begin_fw_update_client_
#define UAVCAN_TRACE(...)
void removeListener(INodeInfoListener *listener)
MonotonicDuration request_interval_
virtual bool shouldRequestFirmwareUpdate(NodeID node_id, const protocol::GetNodeInfo::Response &node_info, FirmwareFilePath &out_firmware_file_path)=0
IFirmwareVersionChecker & checker_
const Key * find(Predicate predicate) const
void resize(SizeType new_size, const ValueType &filler)
unsigned getNumPendingNodes() const
UAVCAN_EXPORT const T & min(const T &a, const T &b)
const ResponseFieldType & getResponse() const
NodeInfoRetriever * node_info_retriever_
virtual void handleFirmwareUpdateConfirmation(NodeID node_id, const protocol::file::BeginFirmwareUpdate::Response &response)
void setCallback(const Callback &cb)
FirmwareUpdateTrigger(INode &node, IFirmwareVersionChecker &checker)
NodeID pickNextNodeID() const
void setRequestInterval(const MonotonicDuration interval)
Value * access(const Key &key)
unsigned getNumPendingCalls() const
bool operator()(const NodeID node_id, const FirmwareFilePath &)
virtual void handleNodeStatusChange(const NodeStatusMonitor::NodeStatusChangeEvent &event)
MakeString< MaxFirmwareFilePathLength >::Type FirmwareFilePath
NextNodeIDSearchPredicate(const FirmwareUpdateTrigger &arg_owner)
uint8_t last_queried_node_id_
void trySetPendingNode(const NodeID node_id, const FirmwareFilePath &path)
FirmwareFilePath common_path_prefix_
static const TransferPriority OneHigherThanLowest
int call(NodeID server_node_id, const RequestType &request)
bool isSuccessful() const
virtual void handleTimerEvent(const TimerEvent &)