v0.2:重写项目。 #6

Merged
Ivan merged 20 commits from v0.2 into master 2022-09-12 11:58:32 +08:00
6 changed files with 130 additions and 41 deletions
Showing only changes of commit 3c8fdd124b - Show all commits

View File

@ -24,6 +24,8 @@ esp-idf-hal = "0.38.0"
esp-idf-svc = "0.42.1" esp-idf-svc = "0.42.1"
esp-idf-sys = { version = "0.31.6", features = ["binstart"] } esp-idf-sys = { version = "0.31.6", features = ["binstart"] }
log = "0.4.17" log = "0.4.17"
serde = {version="1.0.144", features = ["derive"]}
serde_json = "1.0.83"
[build-dependencies] [build-dependencies]

View File

@ -38,10 +38,10 @@ where
break; break;
} }
self.toggle().unwrap(); self.toggle().unwrap();
thread::sleep(Duration::from_millis(30)); thread::sleep(Duration::from_millis(10));
self.toggle().unwrap(); self.toggle().unwrap();
thread::sleep(Duration::from_millis(1930)); thread::sleep(Duration::from_millis(990));
} }
} }
} }

0
src/eventloop.rs Normal file
View File

View File

@ -1,5 +1,6 @@
use embedded_svc::mqtt::client::{Publish, QoS}; use embedded_svc::event_bus::EventBus;
use esp_idf_sys as _; use esp_idf_svc::eventloop::{Background, EspBackgroundEventLoop, EspEventLoop};
use esp_idf_sys::{self as _, EspError};
use log::*; use log::*;
use std::{ use std::{
env, env,
@ -10,13 +11,16 @@ use std::{
mod blink; mod blink;
mod message_queue; mod message_queue;
mod time; mod time;
mod wifi;
mod voltage_detection; mod voltage_detection;
mod wifi;
use crate::voltage_detection::VoltageDetectionWorker;
use crate::{ use crate::{
message_queue::MessageQueue, time::Time, wifi::Internet, voltage_detection::VoltageDetection, message_queue::MessageQueue, time::Time, voltage_detection::VoltageDetection, wifi::Internet,
}; };
static mut EVENTLOOP: Option<EspEventLoop<esp_idf_svc::eventloop::User<Background>>> = None;
fn main() { fn main() {
env::set_var("DEFMT_LOG", "trace"); env::set_var("DEFMT_LOG", "trace");
env::set_var("RUST_BACKTRACE", "1"); env::set_var("RUST_BACKTRACE", "1");
@ -40,6 +44,12 @@ fn main() {
let sda_pin = peripherals.pins.gpio4; let sda_pin = peripherals.pins.gpio4;
let scl_pin = peripherals.pins.gpio10; let scl_pin = peripherals.pins.gpio10;
info!("About to start a background event loop");
match EspBackgroundEventLoop::new(&Default::default()) {
Ok(eventloop) => unsafe { EVENTLOOP = Some(eventloop) },
Err(err) => error!("Init Event Loop failed. {:?}", err),
};
thread::spawn(move || { thread::spawn(move || {
let mut blink = blink::Blink::new( let mut blink = blink::Blink::new(
blink_pin blink_pin
@ -51,7 +61,9 @@ fn main() {
let mut voltage_detection = VoltageDetection::new(); let mut voltage_detection = VoltageDetection::new();
voltage_detection.watching().expect("Can not watch voltages."); voltage_detection
.watching()
.expect("Can not watch voltages.");
let _wifi = Internet::new().unwrap(); let _wifi = Internet::new().unwrap();
@ -61,21 +73,35 @@ fn main() {
let mut time = Time::new(); let mut time = Time::new();
time.sync().unwrap(); time.sync().unwrap();
let _subscription;
if let Some(eventloop) = unsafe { EVENTLOOP.as_mut() } {
_subscription = eventloop
.subscribe(move |message: &VoltageDetectionWorker| {
info!("Event Loop Value");
if let Ok(json_str) = serde_json::to_string(&message) {
if let Err(err) = mq.publish("voltage", json_str.as_bytes()) {
warn!("Can not publish message to MQTT. {}", err);
}
}
})
.expect(" Listening Event Loop Failed");
}
loop { loop {
sleep(Duration::from_millis(1000)); sleep(Duration::from_millis(1000));
if let Some(ref mut mq_client) = mq.client { // if let Some(ref mut mq_client) = mq.client {
let timestamps = time.get_time().as_millis(); // let timestamps = time.get_time().as_millis();
info!("timestamps {}", timestamps); // info!("timestamps {}", timestamps);
mq_client // mq_client
.publish( // .publish(
"ups-0.2/heartbeat", // "ups-0.2/heartbeat",
QoS::AtMostOnce, // QoS::AtMostOnce,
false, // false,
timestamps.to_string().as_bytes(), // timestamps.to_string().as_bytes(),
) // )
.map_err(|err| warn!("publish heartbeat failed {}", err)) // .map_err(|err| warn!("publish heartbeat failed {}", err))
.unwrap(); // .unwrap();
} // }
} }
} }

View File

@ -61,13 +61,16 @@ impl MessageQueue {
anyhow::Ok(()) anyhow::Ok(())
} }
pub fn publish(&mut self, bytes: &[u8]) -> Result<u32> { pub fn publish(&mut self, topic: &str, bytes: &[u8]) -> Result<u32> {
self.client self.client
.as_mut() .as_mut()
.unwrap() .unwrap()
.publish("", QoS::AtMostOnce, false, bytes) .publish(
.map_err(|err| { format!("{}/{}", "ups_0_2", topic).as_str(),
anyhow::anyhow!("publish message to queue was failed!. {}", err) QoS::AtMostOnce,
}) false,
bytes,
)
.map_err(|err| anyhow::anyhow!("publish message to queue was failed!. {}", err))
} }
} }

View File

@ -3,24 +3,41 @@ use std::{
time::Duration, time::Duration,
}; };
use embedded_hal::{adc::Channel, prelude::_embedded_hal_adc_OneShot, digital::v2::OutputPin}; use embedded_hal::{adc::Channel, prelude::_embedded_hal_adc_OneShot};
use embedded_svc::timer::{PeriodicTimer, TimerService}; use embedded_svc::{
event_bus::Postbox,
timer::{PeriodicTimer, TimerService},
};
use esp_idf_hal::{ use esp_idf_hal::{
adc::{ adc::{
config::{self}, config::{self},
Analog, PoweredAdc, ADC1, Analog, PoweredAdc, ADC1,
}, },
gpio::{Gpio1, Gpio2, Gpio3, Input, Pull}, gpio::{Gpio1, Gpio2, Gpio3, Input},
}; };
use esp_idf_svc::timer::{EspTimer, EspTimerService}; use esp_idf_svc::{
eventloop::{
EspEventFetchData, EspEventPostData, EspTypedEventDeserializer, EspTypedEventSerializer,
EspTypedEventSource,
},
timer::{EspTimer, EspTimerService},
};
use esp_idf_sys::c_types;
use log::{info, warn}; use log::{info, warn};
use serde::{Deserialize, Serialize};
use crate::EVENTLOOP;
const ADAPTER_OFFSET: f32 = 12002f32 / 900f32;
const BATTERY_OFFSET: f32 = 12002f32 / 900f32;
const OUTPUT_OFFSET: f32 = 12002f32 / 900f32;
pub struct VoltageDetection { pub struct VoltageDetection {
pub worker: VoltageDetectionWorker, pub worker: VoltageDetectionWorker,
watch_timer: Option<EspTimer>, watch_timer: Option<EspTimer>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, Serialize, Deserialize)]
pub struct VoltageDetectionWorker { pub struct VoltageDetectionWorker {
pub adapter_voltage: u16, pub adapter_voltage: u16,
pub battery_voltage: u16, pub battery_voltage: u16,
@ -39,7 +56,7 @@ impl VoltageDetection {
let worker = Arc::new(Mutex::new(self.worker)); let worker = Arc::new(Mutex::new(self.worker));
let mut timer = EspTimerService::new()?.timer(move || { let mut timer = EspTimerService::new()?.timer(move || {
info!("One-shot timer triggered"); info!("One-shot timer triggered");
match worker.as_ref().lock().as_mut() { match worker.lock().as_mut() {
Ok(worker) => { Ok(worker) => {
if let Err(err) = worker.read_once() { if let Err(err) = worker.read_once() {
warn!("Read Failed. {}", err); warn!("Read Failed. {}", err);
@ -48,6 +65,22 @@ impl VoltageDetection {
"Adapter: {},\tBattery: {},\t Output: {}", "Adapter: {},\tBattery: {},\t Output: {}",
worker.adapter_voltage, worker.battery_voltage, worker.output_voltage worker.adapter_voltage, worker.battery_voltage, worker.output_voltage
); );
if let Some(eventloop) = unsafe { EVENTLOOP.as_mut() } {
if let Err(err) = eventloop.post(
&mut VoltageDetectionWorker {
adapter_voltage: worker.adapter_voltage,
battery_voltage: worker.battery_voltage,
output_voltage: worker.output_voltage,
},
None,
) {
warn!("Post Result to Event Loop failed. {}", err);
} else {
info!("Event Loop Post");
}
} else {
warn!("EVENTLOOP IS NONE");
}
} }
Err(err) => { Err(err) => {
warn!("Lock VoltageDetection Worker Failed. {}", err) warn!("Lock VoltageDetection Worker Failed. {}", err)
@ -60,6 +93,7 @@ impl VoltageDetection {
return anyhow::Ok(()); return anyhow::Ok(());
} }
} }
impl VoltageDetectionWorker { impl VoltageDetectionWorker {
pub fn new() -> Self { pub fn new() -> Self {
return Self { return Self {
@ -71,11 +105,11 @@ impl VoltageDetectionWorker {
pub fn read_once(&mut self) -> anyhow::Result<()> { pub fn read_once(&mut self) -> anyhow::Result<()> {
let adapter_pin = unsafe { Gpio1::<Input>::new() } let adapter_pin = unsafe { Gpio1::<Input>::new() }
.into_analog_atten_11db() .into_analog_atten_6db()
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?; .map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?;
match self.read_pin_once(adapter_pin) { match self.read_pin_once(adapter_pin) {
Ok(voltage) => { Ok(voltage) => {
self.adapter_voltage = voltage; self.adapter_voltage = ((voltage as f32) * ADAPTER_OFFSET) as u16;
} }
Err(err) => { Err(err) => {
warn!("Adapter Voltage read failed: {:?}", err); warn!("Adapter Voltage read failed: {:?}", err);
@ -83,11 +117,11 @@ impl VoltageDetectionWorker {
} }
let battery_pin = unsafe { Gpio2::<Input>::new() } let battery_pin = unsafe { Gpio2::<Input>::new() }
.into_analog_atten_11db() .into_analog_atten_6db()
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?; .map_err(|err| anyhow::anyhow!("Failed to set GPIO 2 as analog input. {}", err))?;
match self.read_pin_once(battery_pin) { match self.read_pin_once(battery_pin) {
Ok(voltage) => { Ok(voltage) => {
self.battery_voltage = voltage; self.battery_voltage = ((voltage as f32) * BATTERY_OFFSET) as u16;
} }
Err(err) => { Err(err) => {
warn!("Adapter Voltage read failed: {:?}", err); warn!("Adapter Voltage read failed: {:?}", err);
@ -95,11 +129,11 @@ impl VoltageDetectionWorker {
} }
let output_pin = unsafe { Gpio3::<Input>::new() } let output_pin = unsafe { Gpio3::<Input>::new() }
.into_analog_atten_11db() .into_analog_atten_6db()
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 1 as analog input. {}", err))?; .map_err(|err| anyhow::anyhow!("Failed to set GPIO 3 as analog input. {}", err))?;
match self.read_pin_once(output_pin) { match self.read_pin_once(output_pin) {
Ok(voltage) => { Ok(voltage) => {
self.output_voltage = voltage; self.output_voltage = ((voltage as f32) * OUTPUT_OFFSET) as u16;
} }
Err(err) => { Err(err) => {
warn!("Adapter Voltage read failed: {:?}", err); warn!("Adapter Voltage read failed: {:?}", err);
@ -115,10 +149,34 @@ impl VoltageDetectionWorker {
let mut adc = PoweredAdc::new(unsafe { ADC1::new() }, config::Config::new())?; let mut adc = PoweredAdc::new(unsafe { ADC1::new() }, config::Config::new())?;
let voltage = adc.read(&mut pin); let voltage = adc.read(&mut pin);
match voltage { match voltage {
Ok(voltage) => anyhow::Ok((self.adapter_voltage + voltage * 10) / 11), Ok(voltage) => anyhow::Ok(voltage),
Err(err) => { Err(err) => {
anyhow::bail!("Adapter Voltage read failed: {:?}", err) anyhow::bail!("Adapter Voltage read failed: {:?}", err)
} }
} }
} }
} }
impl EspTypedEventSource for VoltageDetectionWorker {
fn source() -> *const c_types::c_char {
b"VOLTAGES\0".as_ptr() as *const _
}
}
impl EspTypedEventSerializer<VoltageDetectionWorker> for VoltageDetectionWorker {
fn serialize<R>(
event: &VoltageDetectionWorker,
f: impl for<'a> FnOnce(&'a EspEventPostData) -> R,
) -> R {
f(&unsafe { EspEventPostData::new(Self::source(), Self::event_id(), event) })
}
}
impl EspTypedEventDeserializer<VoltageDetectionWorker> for VoltageDetectionWorker {
fn deserialize<R>(
data: &EspEventFetchData,
f: &mut impl for<'a> FnMut(&'a VoltageDetectionWorker) -> R,
) -> R {
f(unsafe { data.as_payload() })
}
}