Prototype of the first automation stull ugly
This commit is contained in:
@@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use anyhow::Context;
|
||||
use substrate::transport::QuicMessage;
|
||||
use substrate::transport::{QuicMessage, SensorType};
|
||||
use tokio::time::MissedTickBehavior;
|
||||
|
||||
use crate::profile::{SensorSlot, generate_value};
|
||||
@@ -97,6 +97,7 @@ pub async fn run_t3_emitter(
|
||||
ticker.set_missed_tick_behavior(MissedTickBehavior::Skip);
|
||||
let mut sent: u64 = 0;
|
||||
let mut timeouts: u64 = 0;
|
||||
let mut last_relay_state = 0.0;
|
||||
|
||||
loop {
|
||||
ticker.tick().await;
|
||||
@@ -115,9 +116,20 @@ pub async fn run_t3_emitter(
|
||||
slot.seq = slot.seq.wrapping_add(1);
|
||||
|
||||
match tokio::time::timeout(timeout, t3_one_request(&conn, &cmd)).await {
|
||||
Ok(Ok(_ack)) => {
|
||||
Ok(Ok(ack)) => {
|
||||
sent += 1;
|
||||
sent_counter.store(sent, Ordering::Relaxed);
|
||||
|
||||
if ack.sensor_type == SensorType::Relay.as_u8() {
|
||||
let is_on = ack.raw_value > 0.5;
|
||||
let was_on = last_relay_state > 0.5;
|
||||
if is_on && !was_on {
|
||||
tracing::info!(device = %ack.device_id, "Relay triggered ON (machine stopped)!");
|
||||
} else if !is_on && was_on {
|
||||
tracing::info!(device = %ack.device_id, "Relay turned OFF.");
|
||||
}
|
||||
last_relay_state = ack.raw_value;
|
||||
}
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
tracing::warn!(error = %e, "T3 request failed");
|
||||
|
||||
@@ -214,6 +214,50 @@ async fn main() -> anyhow::Result<()> {
|
||||
None
|
||||
};
|
||||
|
||||
let presence_slot_opt = slots.iter().find(|s| s.sensor_type == SensorType::Presence).cloned();
|
||||
let conn_clone = client.conn.clone();
|
||||
if let Some(presence_slot) = presence_slot_opt {
|
||||
tokio::spawn(async move {
|
||||
if let Ok(listener) = tokio::net::TcpListener::bind("0.0.0.0:9002").await {
|
||||
tracing::info!("Simulator HTTP trigger API listening on 0.0.0.0:9002");
|
||||
while let Ok((mut socket, _)) = listener.accept().await {
|
||||
let conn = conn_clone.clone();
|
||||
let slot = presence_slot.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut buf = [0; 1024];
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
if let Ok(n) = socket.read(&mut buf).await {
|
||||
let req = String::from_utf8_lossy(&buf[..n]);
|
||||
if req.starts_with("OPTIONS") {
|
||||
let res = "HTTP/1.1 204 No Content\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: POST, OPTIONS\r\n\r\n";
|
||||
let _ = socket.write_all(res.as_bytes()).await;
|
||||
} else if req.starts_with("POST /trigger") {
|
||||
if let Ok(mut send) = conn.open_uni().await {
|
||||
let msg = QuicMessage {
|
||||
device_id: slot.device_id,
|
||||
sensor_id: slot.sensor_id,
|
||||
raw_value: 0.0,
|
||||
timestamp_us: now_us(),
|
||||
sequence_number: 0,
|
||||
sensor_type: slot.sensor_type.as_u8(),
|
||||
};
|
||||
let _ = send.write_all(&msg.to_bytes()).await;
|
||||
let _ = send.finish();
|
||||
tracing::info!("HTTP API triggered: pushed Presence=0.0 over T2");
|
||||
}
|
||||
let res = "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\n\r\nTriggered";
|
||||
let _ = socket.write_all(res.as_bytes()).await;
|
||||
} else {
|
||||
let res = "HTTP/1.1 404 Not Found\r\nAccess-Control-Allow-Origin: *\r\n\r\n";
|
||||
let _ = socket.write_all(res.as_bytes()).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let started = Instant::now();
|
||||
let mut t1_sent: u64 = 0;
|
||||
let mut send_errors: u64 = 0;
|
||||
|
||||
@@ -57,6 +57,8 @@ pub fn build_slots(
|
||||
(2, SensorType::Pressure),
|
||||
(3, SensorType::Voltage),
|
||||
(4, SensorType::Current),
|
||||
(5, SensorType::Presence),
|
||||
(6, SensorType::Relay),
|
||||
] {
|
||||
slots.push(SensorSlot {
|
||||
device_id,
|
||||
@@ -83,6 +85,8 @@ pub fn generate_value(t: SensorType, seq: u32) -> f64 {
|
||||
SensorType::Pressure => 1013.0 + 5.0 * (t_phase / 20.0).cos(),
|
||||
SensorType::Voltage => 230.0 + 0.5 * (t_phase / 3.0).sin(),
|
||||
SensorType::Current => 10.0 + 2.0 * (t_phase / 5.0).cos(),
|
||||
SensorType::Presence => 2.0 + 1.5 * (t_phase / 5.0).sin(), // Drops below 1.0 occasionally
|
||||
SensorType::Relay => 0.0, // Relay always sends 0.0 as its command (a pure read request)
|
||||
SensorType::Generic => t_phase.sin(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user