64struct AresSerialConfigs {
65 AresSerialConfigs() =
default;
103 std::function<void(int64_t, uint64_t, uint16_t,
bool, uint8_t, uint16_t)>
122 std::function<void(uint16_t, uint16_t, uint8_t, uint8_t,
123 const std::string &)>
244 int send_start(int64_t sec, uint64_t nsec, uint16_t
id,
bool broadcast);
271 py::tuple
led(uint8_t
id, uint8_t state);
299 py::tuple
send_log(
const std::string &log_msg,
bool broadcast,
300 uint8_t tx_cnt, uint16_t
id);
326 Serial::Serial _serial;
328 SpinLock _command_lock;
329 std::exception_ptr _exception;
333 std::chrono::milliseconds _response_timeout;
334 std::chrono::milliseconds _rx_period;
336 void _process_frames_helper();
337 void _process_frames();
339 void _process_rx_buffer(std::vector<uint8_t> &buf);
340 void _read_serial_helper();
343 struct AresResponse {
355 void _publish_response(
const AresFrame::Decoded &frame);
356 void _send_frame(
const std::vector<uint8_t> &tx);
357 AresResponse _send_frame(AresFrame &frame,
358 const std::chrono::milliseconds &timeout);
359 void _send_multi_frame(AresFrame &frame,
360 const std::chrono::milliseconds &timeout,
361 std::vector<AresResponse> &responses);
362 AresResponse _wait_response(
const std::chrono::milliseconds &timeout);
364 _wait_response_timeout(
const std::chrono::milliseconds &timeout);
365 AresResponse _wait_response_forever();
367 std::atomic_bool _tasks_running =
false;
369 Task<void()> _rx_task;
370 ares::bounded_queue<AresFrame::Decoded, 10, true> _frame_q;
372 Task<void()> _processing_task;
373 ares::bounded_queue<AresResponse> _response_queue;
375 std::recursive_mutex _serial_lock;
377 std::function<void(int64_t, uint64_t, uint16_t,
bool, uint8_t, uint16_t)>
378 _start_callback =
nullptr;
379 void _start_event(
const AresFrame::Start &start_frame)
const;
381 static void _handle_bad_frame(
const AresResponse &response);
383 struct HeartbeatWork {
384 HeartbeatWork(work_handler_t handler,
AresSerial *ctx)
385 : work(std::move(handler)), obj(ctx) {}
386 ~HeartbeatWork() { work.work_flush(); }
390 ares::semaphore<> sem{};
394 uint16_t _claimed_host = 0;
395 std::function<void(uint16_t,
bool,
bool)> _heartbeat_callback =
nullptr;
396 void _heartbeat_event(
const AresFrame::Heartbeat &heartbeat);
397 static void _heartbeat_handler(Work *work);
398 HeartbeatWork _heartbeat_work;
399 int _heartbeat_claim_host(uint16_t destination_id);
401 std::function<void(uint16_t)> _claim_callback =
nullptr;
402 void _claim_event(
const AresFrame::Claim &claim);
404 SpinLock _log_spinlock;
405 uint16_t _log_id = 0;
406 ares::bounded_queue<AresFrame::LogAck> _log_ack_signal;
407 void _log_ack_event(
const AresFrame::LogAck &ack);
408 bool _log_ack_event_wait(
const std::chrono::milliseconds &timeout,
409 size_t part,
size_t num_parts, uint16_t
id);
410 void _send_log_frame_directed(AresFrame &frame,
411 const std::chrono::milliseconds &ack_timeout,
413 std::vector<AresResponse> &responses,
415 std::gamma_distribution<double> _mac_backoff;
416 std::random_device _rd;
417 std::mt19937 _generator;
418 void _handle_ack(uint16_t target,
bool acked);
419 std::function<void(uint16_t, uint16_t, uint8_t, uint8_t,
420 const std::string &msg)>
421 _log_callback =
nullptr;
422 void _log_event(
const AresFrame::Log &log)
const;
424 static py::tuple _decode_version(uint32_t version_num);
426 static void _debug_event(
const AresFrame::Dbg &msg);
428 std::function<void(uint8_t, uint16_t, uint16_t)> _pkt_rx_cb =
nullptr;
429 void _packet_rx_event(
const AresFrame::PktRx &msg)
const;
431 std::function<void(uint32_t)> _pkt_tx_cb =
nullptr;
432 void _packet_tx_event(
const AresFrame::PktTx &msg)
const;