blob: 210a2af68b27dc66336f01b6f14d61a673221f31 [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
Philipp Schrader790cb542023-07-05 21:06:52 -07006#include "gflags/gflags.h"
7#include "glog/logging.h"
8
Brian Silvermanea2c95f2021-02-10 18:10:26 -08009#include "aos/aos_cli_utils.h"
10#include "aos/configuration.h"
11#include "aos/init.h"
12#include "aos/json_to_flatbuffer.h"
Brian Silvermanea2c95f2021-02-10 18:10:26 -080013
James Kuszmaul27ff5ac2022-01-21 11:43:48 -080014DEFINE_double(rate, -1, "Rate at which to send the message (-1 to send once).");
15
Brian Silvermanea2c95f2021-02-10 18:10:26 -080016int main(int argc, char **argv) {
17 gflags::SetUsageMessage(
18 "Sends messages on arbitrary channels.\n"
19 "Typical Usage: aos_send [--config path_to_config.json]"
20 " channel_name message_type '{\"foo\": \"bar\"}'\n"
21 "Example usage: aos_send /test aos.examples.Ping "
Eric Schmiedeberg7055b7e2022-07-19 10:04:58 -060022 "'{\"value\": 1}'\n"
23 "Pipe usage: cat ping.json | aos_send /test/ aos.examples.Ping -");
Brian Silvermanea2c95f2021-02-10 18:10:26 -080024 aos::InitGoogle(&argc, &argv);
25
26 aos::CliUtilInfo cli_info;
Austin Schuh59f3b0f2021-07-31 20:50:40 -070027 if (cli_info.Initialize(
28 &argc, &argv,
29 [&cli_info](const aos::Channel *channel) {
30 return aos::configuration::ChannelIsSendableOnNode(
31 channel, cli_info.event_loop->node());
32 },
Austin Schuhba2c8652022-08-17 14:56:08 -070033 "channel is sendable on node", false)) {
Brian Silvermanea2c95f2021-02-10 18:10:26 -080034 return 0;
35 }
36 if (cli_info.found_channels.size() > 1) {
37 LOG(FATAL) << "Matched multiple channels, but may only send on 1";
38 }
39
40 if (argc == 1) {
41 LOG(FATAL) << "Must specify a message to send";
42 }
43
Eric Schmiedeberg7055b7e2022-07-19 10:04:58 -060044 // Check if the user wants to use stdin (denoted by '-') or the argument
45 // present in argv for the message to send. CliUtilInfo will ensure the
46 // message data will be in argv[1]
47 std::string_view message_to_send{argv[1]};
48 std::string stdin_data;
49 if (message_to_send == "-") {
50 // Read in everything from stdin, blocks when there's no data on stdin
51 stdin_data = std::string(std::istreambuf_iterator(std::cin), {});
52 message_to_send = stdin_data;
53 }
54
Brian Silvermanea2c95f2021-02-10 18:10:26 -080055 const aos::Channel *const channel = cli_info.found_channels[0];
56 const std::unique_ptr<aos::RawSender> sender =
57 cli_info.event_loop->MakeRawSender(channel);
58 flatbuffers::FlatBufferBuilder fbb(sender->fbb_allocator()->size(),
59 sender->fbb_allocator());
Austin Schuha36cfa82021-03-20 21:56:03 -070060 fbb.ForceDefaults(true);
Eric Schmiedeberg7055b7e2022-07-19 10:04:58 -060061 fbb.Finish(aos::JsonToFlatbuffer(message_to_send, channel->schema(), &fbb));
James Kuszmaul27ff5ac2022-01-21 11:43:48 -080062
63 if (FLAGS_rate < 0) {
64 sender->CheckOk(sender->Send(fbb.GetSize()));
65 } else {
66 cli_info.event_loop
67 ->AddTimer([&fbb, &sender]() {
68 sender->CheckOk(sender->Send(fbb.GetBufferPointer(), fbb.GetSize()));
69 })
70 ->Setup(cli_info.event_loop->monotonic_now(),
71 std::chrono::duration_cast<std::chrono::nanoseconds>(
72 std::chrono::duration<double>(1.0 / FLAGS_rate)));
73 cli_info.event_loop->Run();
74 }
Brian Silvermanea2c95f2021-02-10 18:10:26 -080075
76 return 0;
77}