v0.7.13
This commit is contained in:
+36
-1
@@ -1,4 +1,4 @@
|
||||
use std::{collections::HashSet, net::{Ipv4Addr, SocketAddr, SocketAddrV4}, sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}}, time::Duration};
|
||||
use std::{collections::{HashMap, HashSet}, net::{Ipv4Addr, SocketAddr, SocketAddrV4}, sync::{Arc, Mutex, atomic::{AtomicBool, AtomicU64, Ordering}}, time::Duration};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use chrono::Utc;
|
||||
use serde_json::{json, Value};
|
||||
@@ -22,6 +22,8 @@ pub struct GreeClient {
|
||||
interface: Option<String>,
|
||||
debug_events: Option<broadcast::Sender<ApiEvent>>,
|
||||
debug_gree_frames: Arc<AtomicBool>,
|
||||
received_frames_total: Arc<AtomicU64>,
|
||||
received_frames_by_device: Arc<Mutex<HashMap<String, u64>>>,
|
||||
buzzer_unsupported: Arc<Mutex<HashSet<String>>>,
|
||||
quiet_unsupported: Arc<Mutex<HashSet<String>>>,
|
||||
sleep_unsupported: Arc<Mutex<HashSet<String>>>,
|
||||
@@ -39,12 +41,43 @@ impl GreeClient {
|
||||
interface,
|
||||
debug_events,
|
||||
debug_gree_frames,
|
||||
received_frames_total: Arc::new(AtomicU64::new(0)),
|
||||
received_frames_by_device: Arc::new(Mutex::new(HashMap::new())),
|
||||
buzzer_unsupported: Arc::new(Mutex::new(HashSet::new())),
|
||||
quiet_unsupported: Arc::new(Mutex::new(HashSet::new())),
|
||||
sleep_unsupported: Arc::new(Mutex::new(HashSet::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn received_frame_stats(&self) -> (u64, HashMap<String, u64>) {
|
||||
let total = self.received_frames_total.load(Ordering::Relaxed);
|
||||
let by_device = self.received_frames_by_device.lock()
|
||||
.map(|counts| counts.clone())
|
||||
.unwrap_or_default();
|
||||
(total, by_device)
|
||||
}
|
||||
|
||||
fn record_received_frame(&self, device: &Device) {
|
||||
let total = self.received_frames_total.fetch_add(1, Ordering::Relaxed).saturating_add(1);
|
||||
let device_count = self.received_frames_by_device.lock().ok().map(|mut counts| {
|
||||
let count = counts.entry(device.id.clone()).or_insert(0);
|
||||
*count = (*count).saturating_add(1);
|
||||
*count
|
||||
}).unwrap_or(0);
|
||||
if let Some(events) = &self.debug_events {
|
||||
let _ = events.send(ApiEvent {
|
||||
event: "gree.frame_received".into(),
|
||||
timestamp: Utc::now(),
|
||||
data: json!({
|
||||
"device_id": device.id,
|
||||
"device_name": device.name,
|
||||
"total": total,
|
||||
"device_count": device_count,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_frame(&self, direction: &str, device: &Device, target: SocketAddr, protocol: u8, payload: &Value) {
|
||||
if !self.debug_gree_frames.load(Ordering::Relaxed) { return; }
|
||||
let Some(events) = &self.debug_events else { return; };
|
||||
@@ -323,6 +356,7 @@ impl GreeClient {
|
||||
let remaining = scan_deadline.saturating_duration_since(Instant::now());
|
||||
match timeout(remaining, socket.recv_from(&mut scan_buf)).await {
|
||||
Ok(Ok((_size, source))) if source.ip() == target.ip() => {
|
||||
self.record_received_frame(device);
|
||||
tracing::debug!(device=%device.id, source=%source, "Received scan response immediately before bind");
|
||||
break;
|
||||
}
|
||||
@@ -667,6 +701,7 @@ impl GreeClient {
|
||||
Err(_) => break,
|
||||
};
|
||||
if source.ip() != target.ip() { continue; }
|
||||
self.record_received_frame(device);
|
||||
let response: Value = match serde_json::from_slice(&buffer[..size]) {
|
||||
Ok(value) => value,
|
||||
Err(err) => { last_decode_error = Some(anyhow!("invalid GREE JSON response: {err}")); continue; }
|
||||
|
||||
Reference in New Issue
Block a user