tether_utils/
tether_send.rs

1use clap::Args;
2use log::{debug, error, info, warn};
3use serde::Serialize;
4use tether_agent::{PlugOptionsBuilder, TetherAgent};
5
6#[derive(Args)]
7pub struct SendOptions {
8    /// Overide the auto-generated topic with your own, to use with every published message
9    #[arg(long = "plug.name")]
10    pub plug_name: Option<String>,
11
12    /// Overide Tether Agent role with your own, to use with every published message
13    #[arg(long = "plug.role")]
14    pub plug_role: Option<String>,
15
16    /// Overide Tether Agent ID with your own, to use with every published message
17    #[arg(long = "plug.id")]
18    pub plug_id: Option<String>,
19
20    /// Overide the entire topic string (ignoring any defaults or customisations applied elsewhere),
21    /// to use with every published message
22    #[arg(long = "topic")]
23    pub plug_topic: Option<String>,
24
25    /// Provide a custom message as an escaped JSON string which will be converted
26    /// into MessagePack; by default the payload will be empty.
27    #[arg(long = "message")]
28    pub message_payload_json: Option<String>,
29
30    /// Flag to generate dummy data for the MessagePack payload; useful for testing.
31    /// Any custom message will be ignored if enabled.
32    #[arg(long = "dummyData")]
33    pub use_dummy_data: bool,
34}
35
36#[derive(Serialize, Debug)]
37struct DummyData {
38    id: usize,
39    a_float: f32,
40    an_int_array: Vec<usize>,
41    a_string: String,
42}
43
44pub fn send(options: &SendOptions, tether_agent: &mut TetherAgent) -> anyhow::Result<()> {
45    info!("Tether Send Utility");
46
47    let plug_name = options.plug_name.clone().unwrap_or("testMessages".into());
48
49    let output = PlugOptionsBuilder::create_output(&plug_name)
50        .role(options.plug_role.as_deref())
51        .id(options.plug_id.as_deref())
52        .topic(options.plug_topic.as_deref())
53        .build(tether_agent)
54        .expect("failed to create output plug");
55
56    info!("Sending on topic \"{}\" ...", output.topic());
57
58    if options.use_dummy_data {
59        let payload = DummyData {
60            id: 0,
61            a_float: 42.0,
62            an_int_array: vec![1, 2, 3, 4],
63            a_string: "hello world".into(),
64        };
65        info!("Sending dummy data {:?}", payload);
66        return match tether_agent.encode_and_publish(&output, &payload) {
67            Ok(_) => {
68                info!("Sent dummy data message OK");
69                Ok(())
70            }
71            Err(e) => Err(e),
72        };
73    }
74
75    match &options.message_payload_json {
76        Some(custom_message) => {
77            debug!(
78                "Attempting to decode provided custom message \"{}\"",
79                &custom_message
80            );
81            match serde_json::from_str::<serde_json::Value>(custom_message) {
82                Ok(encoded) => {
83                    let payload =
84                        rmp_serde::to_vec_named(&encoded).expect("failed to encode msgpack");
85                    tether_agent
86                        .publish(&output, Some(&payload))
87                        .expect("failed to publish");
88                    info!("Sent message OK");
89                    Ok(())
90                }
91                Err(e) => {
92                    error!("Could not serialise String -> JSON; error: {}", e);
93                    Err(e.into())
94                }
95            }
96        }
97        None => {
98            warn!("Sending empty message");
99            match tether_agent.publish(&output, None) {
100                Ok(_) => {
101                    info!("Sent empty message OK");
102                    Ok(())
103                }
104                Err(e) => {
105                    error!("Failed to send empty message: {}", e);
106                    Err(e)
107                }
108            }
109        }
110    }
111}