1use std::{time::Duration, collections::HashMap, net::{IpAddr, SocketAddr, Ipv4Addr}};
2
3use serde_json::Value;
4
5use crate::{*, apdu::{ScanResponsePack, GenericMessage, BindResponsePack}, vars::VarName};
6
7pub type MacAddr = String;
8
9#[derive(Debug, Clone, Copy)]
11pub struct GreeClientConfig {
12 pub buffer_size: usize,
14 pub recv_timeout: Duration,
16 pub bind_addr: SocketAddr,
18 pub max_count: usize,
20 pub bcast_addr: IpAddr,
22}
23
24impl GreeClientConfig {
25 pub const DEFAULT_BUFFER_SIZE: usize = 2048;
26 pub const DEFAULT_MAX_COUNT: usize = 10;
27 pub const DEFAULT_BROADCAST_ADDR: [u8; 4] = [10, 0, 0, 255];
28 pub const DEFAULT_RECV_TIMEOUT: Duration = Duration::from_secs(3);
29}
30
31impl Default for GreeClientConfig {
32
33 fn default() -> Self {
34 Self {
35 buffer_size: Self::DEFAULT_BUFFER_SIZE,
36 recv_timeout: Self::DEFAULT_RECV_TIMEOUT,
37 bind_addr: (Ipv4Addr::UNSPECIFIED, 0).into(),
38 max_count: Self::DEFAULT_MAX_COUNT,
39 bcast_addr: Self::DEFAULT_BROADCAST_ADDR.into(),
40 }
41 }
42}
43
44#[derive(Debug, Clone)]
46pub struct GreeConfig {
47 pub client_config: GreeClientConfig,
49 pub min_scan_age: Duration,
51 pub max_scan_age: Duration,
53 pub aliases: HashMap<String, MacAddr>,
55}
56
57impl GreeConfig {
58
59 pub const DEFAULT_MIN_SCAN_AGE: Duration = Duration::from_secs(60);
60 pub const DEFAULT_MAX_SCAN_AGE: Duration = Duration::from_secs(3600 * 24);
61}
62
63impl Default for GreeConfig {
64 fn default() -> Self {
65 Self {
66 client_config: Default::default(),
67 min_scan_age: Self::DEFAULT_MIN_SCAN_AGE,
68 max_scan_age: Self::DEFAULT_MAX_SCAN_AGE,
69 aliases: HashMap::new(),
70 }
71 }
72}
73
74pub struct GreeState {
76 pub devices: HashMap<MacAddr, Device>,
77}
78
79impl GreeState {
80 pub fn new() -> Self { Self { devices: HashMap::new() } }
81 pub fn scan_ind(&mut self, scan_result: Vec<(IpAddr, GenericMessage, ScanResponsePack)>) {
82 self.devices = scan_result.into_iter().map(|(ip, _, scan_result)| (
83 scan_result.mac.clone(),
84 Device { ip, scan_result, key: None }
85 )).collect();
86 }
87}
88
89pub struct Device {
93 pub ip: IpAddr,
95
96 pub scan_result: ScanResponsePack,
98
99 pub key: Option<String>,
101}
102
103impl Device {
104 pub fn bind_ind(&mut self, pack: BindResponsePack) {
105 self.key = Some(pack.key)
106 }
107}
108
109
110pub trait NetVar {
114 fn net_set(&mut self, value: Value);
116 fn net_get(&self) -> &Value;
118 fn is_net_read_pending(&self) -> bool;
120 fn is_net_write_pending(&self) -> bool;
122 fn clear_net_write_pending(&mut self);
124}
125
126
127pub struct SimpleNetVar {
129 value: Value,
130 net_read_pending: bool,
131 net_write_pending: bool,
132}
133
134impl SimpleNetVar {
135 pub fn new() -> Self {
136 Self { value: Value::Null, net_read_pending: true, net_write_pending: false }
137 }
138
139 pub fn add_nv_to(mut bag: NetVarBag<Self>, (name, value): (impl AsRef<str>, impl AsRef<str>)) -> Result<NetVarBag<Self>> {
141 let name = vars::name_of(name.as_ref())
142 .ok_or_else(|| Error::InvalidVar(name.as_ref().to_owned()))?;
143 let value = vars::parse_value(name, value)?;
144 bag.insert(name, Self::from_value(value));
145 Ok(bag)
146 }
147
148 pub fn add_n_to(mut bag: NetVarBag<Self>, name: impl AsRef<str>) -> Result<NetVarBag<Self>> {
150 let name = vars::name_of(name.as_ref())
151 .ok_or_else(|| Error::InvalidVar(name.as_ref().to_owned()))?;
152 bag.insert(name, Self::new());
153 Ok(bag)
154 }
155
156 pub fn from_value(value: Value) -> Self {
158 Self { value, net_read_pending: false, net_write_pending: true }
159 }
160
161 pub fn user_set(&mut self, value: Value) {
163 self.value = value;
164 self.net_write_pending = true;
165 }
166
167 pub fn user_get(&self) -> &Value {
169 &self.value
170 }
171}
172
173impl NetVar for SimpleNetVar {
174 fn net_set(&mut self, value: Value) {
176 self.value = value;
177 self.net_read_pending = false;
178 }
179 fn net_get(&self) -> &Value { &self.value }
180 fn is_net_read_pending(&self) -> bool { self.net_read_pending }
181 fn is_net_write_pending(&self) -> bool { self.net_write_pending }
182 fn clear_net_write_pending(&mut self) { self.net_write_pending = false }
183}
184
185pub type NetVarBag<T> = HashMap<VarName, T>;
187
188pub fn net_var_bag_from_names<'t, S: AsRef<str> + 't>(mut ns: impl Iterator<Item = &'t S>) -> Result<NetVarBag<SimpleNetVar>> {
190 ns.try_fold(std::collections::HashMap::new(), SimpleNetVar::add_n_to)
191}
192
193pub fn net_var_bag_from_nvs<'t, S: AsRef<str> + 't>(mut nvs: impl Iterator<Item = (&'t S, &'t S)>) -> Result<NetVarBag<SimpleNetVar>> {
195 nvs.try_fold(std::collections::HashMap::new(), SimpleNetVar::add_nv_to)
196}
197
198pub fn net_var_bag_to_json<T: NetVar>(b: &NetVarBag<T>) -> HashMap<VarName, Value> {
200 b.into_iter().map(|(k, v)| (*k, v.net_get().clone())).collect()
201}
202
203#[macro_export]
205macro_rules! net_var_bag {
206 ($($var:expr => $val:expr),+) => {
207 [$(($var, $val)),+].into_iter().try_fold(std::collections::HashMap::new(), gree::SimpleNetVar::add_nv_to)
208 };
209 ($($var:expr),+) => {
210 [$($var),+].into_iter().try_fold(std::collections::HashMap::new(), gree::SimpleNetVar::add_n_to)
211 };
212}
213
214#[derive(Debug)]
216pub enum Op<'t, T: NetVar> {
217 Bind,
218 NetRead(&'t mut NetVarBag<T>),
219 NetWrite(&'t mut NetVarBag<T>),
220}