]>
code.octet-stream.net Git - m17rt/blob - tools/m17rt-netclient/src/main.rs
1 use std
::{io
::stdin
, sync
::Arc
};
3 use clap
::{Arg
, value_parser
};
5 adapter
::StreamAdapter
,
7 link_setup
::M17Address
,
8 reflector
::{ReflectorClientConfig
, ReflectorClientTnc
, StatusHandler
},
10 use m17codec2
::{rx
::Codec2RxAdapter
, tx
::Codec2TxAdapter
};
13 let args
= clap
::Command
::new("m17rt-netclient")
19 .help("Domain or IP of reflector"),
25 .value_parser(value_parser
!(u16))
26 .default_value("17000")
27 .help("Reflector listening port"),
33 .value_parser(valid_callsign
)
35 .help("Your callsign for reflector registration and transmissions"),
41 .value_parser(valid_module
)
43 .help("Module to connect to (A-Z)"),
49 .help("Soundcard name for microphone, otherwise system default"),
55 .help("Soundcard name for speaker, otherwise system default"),
59 let hostname
= args
.get_one
::<String
>("hostname").unwrap
();
60 let port
= args
.get_one
::<u16>("port").unwrap
();
61 let callsign
= args
.get_one
::<M17Address
>("callsign").unwrap
();
62 let module
= args
.get_one
::<char>("module").unwrap
();
63 let input
= args
.get_one
::<String
>("input");
64 let output
= args
.get_one
::<String
>("output");
66 let mut tx
= Codec2TxAdapter
::new(callsign
.clone(), M17Address
::new_broadcast());
67 if let Some(input
) = input
{
68 tx
.set_input_card(input
);
72 let mut rx
= Codec2RxAdapter
::new();
73 if let Some(output
) = output
{
74 rx
.set_output_card(output
);
77 let config
= ReflectorClientConfig
{
78 hostname
: hostname
.clone(),
81 local_callsign
: callsign
.clone(),
83 let tnc
= ReflectorClientTnc
::new(config
, ConsoleStatusHandler
);
84 let app
= M17App
::new(tnc
);
85 app
.add_stream_adapter(ConsoleAdapter
).unwrap
();
86 app
.add_stream_adapter(tx
).unwrap
();
87 app
.add_stream_adapter(rx
).unwrap
();
90 println
!(">>> PRESS ENTER TO TOGGLE PTT <<<");
91 let mut buf
= String
::new();
94 let _
= stdin().read_line(&mut buf
);
96 println
!("PTT ON: PRESS ENTER TO END");
98 let _
= stdin().read_line(&mut buf
);
104 fn valid_module(m
: &str) -> Result
<char, String
> {
105 let m
= m
.to_ascii_uppercase();
106 if m
.len() != 1 || !m
.chars().next().unwrap
().is
_alphabet
ic
() {
107 return Err("Module must be a single letter from A to Z".to_owned());
109 Ok(m
.chars().next().unwrap
())
112 fn valid_callsign(c
: &str) -> Result
<M17Address
, String
> {
113 M17Address
::from_callsign(c
).map_err(|e
| e
.to_string())
116 struct ConsoleAdapter
;
117 impl StreamAdapter
for ConsoleAdapter
{
118 fn stream_began(&self, link_setup
: m17app
::link_setup
::LinkSetup
) {
120 "Incoming transmission begins. From: {} To: {}",
122 link_setup
.destination()
126 fn stream_data(&self, _frame_number
: u16, is_final
: bool
, _data
: Arc
<[u8; 16]>) {
128 println
!("Incoming transmission ends.");
133 struct ConsoleStatusHandler
;
134 impl StatusHandler
for ConsoleStatusHandler
{
135 fn status_changed(&mut self, status
: m17app
::reflector
::TncStatus
) {
136 println
!("Client status: {status:?}")