blob: d95768fadd38a7a551c179d77a6b035c858e3aa2 [file] [log] [blame]
Eric Schmiedeberg7055b7e2022-07-19 10:04:58 -06001#include <poll.h>
Brian Silvermanea2c95f2021-02-10 18:10:26 -08002#include <unistd.h>
3
4#include <iostream>
5
Austin Schuh99f7c6a2024-06-25 22:07:44 -07006#include "absl/flags/flag.h"
7#include "absl/flags/usage.h"
8#include "absl/log/log.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07009
Brian Silvermanea2c95f2021-02-10 18:10:26 -080010#include "aos/aos_cli_utils.h"
11#include "aos/configuration.h"
12#include "aos/init.h"
13#include "aos/json_to_flatbuffer.h"
Brian Silvermanea2c95f2021-02-10 18:10:26 -080014
Austin Schuh99f7c6a2024-06-25 22:07:44 -070015ABSL_FLAG(double, rate, -1,
16 "Rate at which to send the message (-1 to send once).");
James Kuszmaul27ff5ac2022-01-21 11:43:48 -080017
Brian Silvermanea2c95f2021-02-10 18:10:26 -080018int main(int argc, char **argv) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -070019 absl::SetProgramUsageMessage(
Brian Silvermanea2c95f2021-02-10 18:10:26 -080020 "Sends messages on arbitrary channels.\n"
21 "Typical Usage: aos_send [--config path_to_config.json]"
22 " channel_name message_type '{\"foo\": \"bar\"}'\n"
23 "Example usage: aos_send /test aos.examples.Ping "
Eric Schmiedeberg7055b7e2022-07-19 10:04:58 -060024 "'{\"value\": 1}'\n"
25 "Pipe usage: cat ping.json | aos_send /test/ aos.examples.Ping -");
Brian Silvermanea2c95f2021-02-10 18:10:26 -080026 aos::InitGoogle(&argc, &argv);
27
28 aos::CliUtilInfo cli_info;
Austin Schuh59f3b0f2021-07-31 20:50:40 -070029 if (cli_info.Initialize(
30 &argc, &argv,
31 [&cli_info](const aos::Channel *channel) {
32 return aos::configuration::ChannelIsSendableOnNode(
33 channel, cli_info.event_loop->node());
34 },
Austin Schuhba2c8652022-08-17 14:56:08 -070035 "channel is sendable on node", false)) {
Brian Silvermanea2c95f2021-02-10 18:10:26 -080036 return 0;
37 }
38 if (cli_info.found_channels.size() > 1) {
39 LOG(FATAL) << "Matched multiple channels, but may only send on 1";
40 }
41
42 if (argc == 1) {
43 LOG(FATAL) << "Must specify a message to send";
44 }
45
Eric Schmiedeberg7055b7e2022-07-19 10:04:58 -060046 // Check if the user wants to use stdin (denoted by '-') or the argument
47 // present in argv for the message to send. CliUtilInfo will ensure the
48 // message data will be in argv[1]
49 std::string_view message_to_send{argv[1]};
50 std::string stdin_data;
51 if (message_to_send == "-") {
52 // Read in everything from stdin, blocks when there's no data on stdin
53 stdin_data = std::string(std::istreambuf_iterator(std::cin), {});
54 message_to_send = stdin_data;
55 }
56
Brian Silvermanea2c95f2021-02-10 18:10:26 -080057 const aos::Channel *const channel = cli_info.found_channels[0];
58 const std::unique_ptr<aos::RawSender> sender =
59 cli_info.event_loop->MakeRawSender(channel);
60 flatbuffers::FlatBufferBuilder fbb(sender->fbb_allocator()->size(),
61 sender->fbb_allocator());
Austin Schuha36cfa82021-03-20 21:56:03 -070062 fbb.ForceDefaults(true);
Austin Schuhe54988c2024-04-30 12:14:02 -070063 flatbuffers::Offset<flatbuffers::Table> msg_offset =
64 aos::JsonToFlatbuffer(message_to_send, channel->schema(), &fbb);
65
66 if (msg_offset.IsNull()) {
67 return 1;
68 }
69
70 fbb.Finish(msg_offset);
James Kuszmaul27ff5ac2022-01-21 11:43:48 -080071
Austin Schuh99f7c6a2024-06-25 22:07:44 -070072 if (absl::GetFlag(FLAGS_rate) < 0) {
James Kuszmaul27ff5ac2022-01-21 11:43:48 -080073 sender->CheckOk(sender->Send(fbb.GetSize()));
74 } else {
75 cli_info.event_loop
76 ->AddTimer([&fbb, &sender]() {
77 sender->CheckOk(sender->Send(fbb.GetBufferPointer(), fbb.GetSize()));
78 })
Philipp Schradera6712522023-07-05 20:25:11 -070079 ->Schedule(cli_info.event_loop->monotonic_now(),
80 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh99f7c6a2024-06-25 22:07:44 -070081 std::chrono::duration<double>(
82 1.0 / absl::GetFlag(FLAGS_rate))));
James Kuszmaul27ff5ac2022-01-21 11:43:48 -080083 cli_info.event_loop->Run();
84 }
Brian Silvermanea2c95f2021-02-10 18:10:26 -080085
86 return 0;
87}