blob: 13130ccd4cea49b0ffa0b03e7a826efae9717f40 [file] [log] [blame]
Stephan Pleines7463f602024-04-03 20:16:54 -07001#include <unistd.h>
2
3#include <iostream>
4
5#include "gflags/gflags.h"
6
7#include "aos/aos_cli_utils.h"
8#include "aos/configuration.h"
9#include "aos/init.h"
10#include "aos/json_to_flatbuffer.h"
11#include "aos/realtime.h"
12
13DEFINE_int32(priority, -1, "If set, the RT priority to run at.");
James Kuszmaul97772342024-05-04 13:40:48 -070014DEFINE_double(max_jitter, 10.00,
Stephan Pleines7463f602024-04-03 20:16:54 -070015 "The max time in seconds between messages before considering the "
16 "camera processes dead.");
17DEFINE_double(grace_period, 10.00,
18 "The grace period at startup before enforcing that messages must "
19 "flow from the camera processes.");
20
21namespace aos {
22
23class State {
24 public:
25 State(aos::EventLoop *event_loop, const Channel *channel)
26 : channel_(channel),
27 channel_name_(aos::configuration::StrippedChannelToString(channel_)) {
28 LOG(INFO) << "Watching for healthy message sends on " << channel_name_;
29
30 event_loop->MakeRawNoArgWatcher(
31 channel_,
32 [this](const aos::Context &context) { HandleMessage(context); });
33
34 timer_handle_ = event_loop->AddTimer(
35 [this, event_loop]() { RunHealthCheck(event_loop); });
36 timer_handle_->set_name("jitter");
37 event_loop->OnRun([this, event_loop]() {
38 timer_handle_->Schedule(
39 event_loop->monotonic_now() +
40 std::chrono::duration_cast<std::chrono::nanoseconds>(
41 std::chrono::duration<double>(FLAGS_grace_period)),
42 std::chrono::milliseconds(1000));
43 });
44 }
45
46 void HandleMessage(const aos::Context &context) {
James Kuszmaul97772342024-05-04 13:40:48 -070047 if (last_time_ == aos::monotonic_clock::min_time) {
48 LOG(INFO) << "First message on " << channel_name_;
49 }
Stephan Pleines7463f602024-04-03 20:16:54 -070050 last_time_ = context.monotonic_event_time;
51 }
52
53 void RunHealthCheck(aos::EventLoop *event_loop) {
54 if (last_time_ + std::chrono::duration_cast<std::chrono::nanoseconds>(
55 std::chrono::duration<double>(FLAGS_max_jitter)) <
56 event_loop->monotonic_now()) {
57 // Restart camera services
58 LOG(INFO) << "Restarting camera services";
James Kuszmaul97772342024-05-04 13:40:48 -070059 LOG(INFO) << "Channel " << channel_name_ << " has not received a message "
60 << FLAGS_max_jitter << " seconds";
Stephan Pleines7463f602024-04-03 20:16:54 -070061 CHECK_EQ(std::system("aos_starter stop argus_camera0"), 0);
62 CHECK_EQ(std::system("aos_starter stop argus_camera1"), 0);
63 CHECK_EQ(std::system("sudo systemctl restart nvargus-daemon.service"), 0);
64 CHECK_EQ(std::system("aos_starter start argus_camera0"), 0);
65 CHECK_EQ(std::system("aos_starter start argus_camera1"), 0);
66
67 std::exit(0);
68 return;
69 }
70 }
71
72 private:
73 const Channel *channel_;
74
75 std::string channel_name_;
76
77 aos::monotonic_clock::time_point last_time_ = aos::monotonic_clock::min_time;
78
79 aos::TimerHandler *timer_handle_;
80};
81
82} // namespace aos
83
84int main(int argc, char **argv) {
85 aos::InitGoogle(&argc, &argv);
86
87 aos::CliUtilInfo cli_info;
88 if (cli_info.Initialize(
89 &argc, &argv,
90 [&cli_info](const aos::Channel *channel) {
91 return aos::configuration::ChannelIsReadableOnNode(
92 channel, cli_info.event_loop->node());
93 },
94 "channel is readeable on node", true)) {
95 return 0;
96 }
97
98 std::vector<std::unique_ptr<aos::State>> states;
99
100 for (const aos::Channel *channel : cli_info.found_channels) {
101 states.emplace_back(
102 std::make_unique<aos::State>(&(cli_info.event_loop.value()), channel));
103 }
104
105 if (FLAGS_priority > 0) {
106 cli_info.event_loop->SetRuntimeRealtimePriority(FLAGS_priority);
107 }
108
109 cli_info.event_loop->Run();
110
111 return 0;
112}