| #include <unistd.h> |
| |
| #include <iostream> |
| |
| #include "gflags/gflags.h" |
| |
| #include "aos/aos_cli_utils.h" |
| #include "aos/configuration.h" |
| #include "aos/init.h" |
| #include "aos/json_to_flatbuffer.h" |
| #include "aos/realtime.h" |
| |
| DEFINE_int32(priority, -1, "If set, the RT priority to run at."); |
| DEFINE_double(max_jitter, 5.00, |
| "The max time in seconds between messages before considering the " |
| "camera processes dead."); |
| DEFINE_double(grace_period, 10.00, |
| "The grace period at startup before enforcing that messages must " |
| "flow from the camera processes."); |
| |
| namespace aos { |
| |
| class State { |
| public: |
| State(aos::EventLoop *event_loop, const Channel *channel) |
| : channel_(channel), |
| channel_name_(aos::configuration::StrippedChannelToString(channel_)) { |
| LOG(INFO) << "Watching for healthy message sends on " << channel_name_; |
| |
| event_loop->MakeRawNoArgWatcher( |
| channel_, |
| [this](const aos::Context &context) { HandleMessage(context); }); |
| |
| timer_handle_ = event_loop->AddTimer( |
| [this, event_loop]() { RunHealthCheck(event_loop); }); |
| timer_handle_->set_name("jitter"); |
| event_loop->OnRun([this, event_loop]() { |
| timer_handle_->Schedule( |
| event_loop->monotonic_now() + |
| std::chrono::duration_cast<std::chrono::nanoseconds>( |
| std::chrono::duration<double>(FLAGS_grace_period)), |
| std::chrono::milliseconds(1000)); |
| }); |
| } |
| |
| void HandleMessage(const aos::Context &context) { |
| last_time_ = context.monotonic_event_time; |
| } |
| |
| void RunHealthCheck(aos::EventLoop *event_loop) { |
| if (last_time_ + std::chrono::duration_cast<std::chrono::nanoseconds>( |
| std::chrono::duration<double>(FLAGS_max_jitter)) < |
| event_loop->monotonic_now()) { |
| // Restart camera services |
| LOG(INFO) << "Restarting camera services"; |
| CHECK_EQ(std::system("aos_starter stop argus_camera0"), 0); |
| CHECK_EQ(std::system("aos_starter stop argus_camera1"), 0); |
| CHECK_EQ(std::system("sudo systemctl restart nvargus-daemon.service"), 0); |
| CHECK_EQ(std::system("aos_starter start argus_camera0"), 0); |
| CHECK_EQ(std::system("aos_starter start argus_camera1"), 0); |
| |
| std::exit(0); |
| return; |
| } |
| } |
| |
| private: |
| const Channel *channel_; |
| |
| std::string channel_name_; |
| |
| aos::monotonic_clock::time_point last_time_ = aos::monotonic_clock::min_time; |
| |
| aos::TimerHandler *timer_handle_; |
| }; |
| |
| } // namespace aos |
| |
| int main(int argc, char **argv) { |
| aos::InitGoogle(&argc, &argv); |
| |
| aos::CliUtilInfo cli_info; |
| if (cli_info.Initialize( |
| &argc, &argv, |
| [&cli_info](const aos::Channel *channel) { |
| return aos::configuration::ChannelIsReadableOnNode( |
| channel, cli_info.event_loop->node()); |
| }, |
| "channel is readeable on node", true)) { |
| return 0; |
| } |
| |
| std::vector<std::unique_ptr<aos::State>> states; |
| |
| for (const aos::Channel *channel : cli_info.found_channels) { |
| states.emplace_back( |
| std::make_unique<aos::State>(&(cli_info.event_loop.value()), channel)); |
| } |
| |
| if (FLAGS_priority > 0) { |
| cli_info.event_loop->SetRuntimeRealtimePriority(FLAGS_priority); |
| } |
| |
| cli_info.event_loop->Run(); |
| |
| return 0; |
| } |