pl: async serial
This commit is contained in:
parent
bc0da6be11
commit
bda2d63e99
4 changed files with 42 additions and 49 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -252,7 +252,6 @@ dependencies = [
|
|||
"rocket",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serialport",
|
||||
"tokio",
|
||||
"tokio-modbus",
|
||||
"tokio-serial",
|
||||
|
|
|
@ -21,7 +21,6 @@ chrono = "0.4.39"
|
|||
prometheus = "0.13.4"
|
||||
env_logger = "0.11.6"
|
||||
log = "0.4.22"
|
||||
serialport = "4.6.1"
|
||||
futures = "0.3.31"
|
||||
tokio-modbus = "0.16.1"
|
||||
tokio-serial = "5.4.4"
|
||||
|
|
|
@ -69,7 +69,7 @@ impl ControllerInner {
|
|||
pub async fn refresh(&mut self) -> eyre::Result<CommonData> {
|
||||
match self {
|
||||
ControllerInner::Pl(pli) => {
|
||||
let pl_data = pli.refresh()?;
|
||||
let pl_data = pli.refresh().await?;
|
||||
Ok(pl_data)
|
||||
}
|
||||
ControllerInner::Tristar(tristar) => {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::{io::Write, time::Duration};
|
||||
|
||||
use chrono::Timelike;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serialport::SerialPort;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio_serial::{SerialPort, SerialPortBuilderExt};
|
||||
|
||||
use crate::gauges::{
|
||||
BATTERY_TEMP, BATTERY_VOLTAGE, CHARGE_STATE, INPUT_CURRENT, PL_DUTY_CYCLE, PL_LOAD_CURRENT,
|
||||
|
@ -11,7 +10,7 @@ use crate::gauges::{
|
|||
|
||||
pub struct Pli {
|
||||
friendly_name: String,
|
||||
port: Box<dyn SerialPort>,
|
||||
port: tokio_serial::SerialStream,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
|
||||
|
@ -111,10 +110,10 @@ impl Pli {
|
|||
friendly_name: &str,
|
||||
baud_rate: u32,
|
||||
timeout: u64,
|
||||
) -> Result<Self, serialport::Error> {
|
||||
let port = serialport::new(serial_port, baud_rate)
|
||||
.timeout(Duration::from_millis(timeout))
|
||||
.open()?;
|
||||
) -> Result<Self, tokio_serial::Error> {
|
||||
let port = tokio_serial::new(serial_port, baud_rate)
|
||||
.timeout(std::time::Duration::from_millis(timeout))
|
||||
.open_native_async()?;
|
||||
|
||||
Ok(Self {
|
||||
friendly_name: friendly_name.to_owned(),
|
||||
|
@ -122,8 +121,8 @@ impl Pli {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) -> eyre::Result<crate::controller::CommonData> {
|
||||
let new_state = self.read_state()?;
|
||||
pub async fn refresh(&mut self) -> eyre::Result<crate::controller::CommonData> {
|
||||
let new_state = self.read_state().await?;
|
||||
BATTERY_VOLTAGE
|
||||
.with_label_values(&[&self.friendly_name])
|
||||
.set(new_state.battery_voltage);
|
||||
|
@ -153,14 +152,14 @@ impl Pli {
|
|||
}
|
||||
|
||||
#[expect(dead_code, reason = "writing settings is not yet implemented")]
|
||||
pub fn process_request(&mut self, message: PliRequest) -> eyre::Result<()> {
|
||||
pub async fn process_request(&mut self, message: PliRequest) -> eyre::Result<()> {
|
||||
match message {
|
||||
PliRequest::ReadRam(address) => {
|
||||
let data = self.read_ram(address)?;
|
||||
let data = self.read_ram(address).await?;
|
||||
log::warn!("Read RAM at {address}: data {data}");
|
||||
}
|
||||
PliRequest::ReadEeprom(address) => {
|
||||
let data = self.read_eeprom(address)?;
|
||||
let data = self.read_eeprom(address).await?;
|
||||
log::warn!("Read EEPROM at {address}: data {data}");
|
||||
}
|
||||
PliRequest::SyncTime => {
|
||||
|
@ -168,85 +167,81 @@ impl Pli {
|
|||
let timestamp = (((now.hour() * 10) + (now.minute() / 6)) & 0xFF) as u8;
|
||||
let min = (now.minute() % 6) as u8;
|
||||
let sec = (now.second() / 2).min(29) as u8;
|
||||
self.write_ram(PlRamAddress::Hour, timestamp)?;
|
||||
self.write_ram(PlRamAddress::Min, min)?;
|
||||
self.write_ram(PlRamAddress::Sec, sec)?;
|
||||
self.write_ram(PlRamAddress::Hour, timestamp).await?;
|
||||
self.write_ram(PlRamAddress::Min, min).await?;
|
||||
self.write_ram(PlRamAddress::Sec, sec).await?;
|
||||
log::warn!(
|
||||
"Set time: {now} corresponds to {timestamp} + minutes {min} + seconds {sec}"
|
||||
);
|
||||
}
|
||||
PliRequest::SetRegulatorState(state) => {
|
||||
log::warn!("Setting regulator state to {state:?}");
|
||||
self.write_ram(PlRamAddress::Rstate, state.into())?;
|
||||
self.write_ram(PlRamAddress::Rstate, state.into()).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_state(&mut self) -> eyre::Result<PlState> {
|
||||
async fn read_state(&mut self) -> eyre::Result<PlState> {
|
||||
Ok(PlState {
|
||||
battery_voltage: f64::from(self.read_ram(PlRamAddress::Batv)?) * (4. / 10.),
|
||||
target_voltage: f64::from(self.read_ram(PlRamAddress::Vreg)?) * (4. / 10.),
|
||||
duty_cycle: f64::from(self.read_ram(PlRamAddress::Dutycyc)?) / 255.,
|
||||
internal_charge_current: f64::from(self.read_ram(PlRamAddress::Cint)?) * (4. / 10.),
|
||||
internal_load_current: f64::from(self.read_ram(PlRamAddress::Lint)?) * (4. / 10.),
|
||||
battery_temp: f64::from(self.read_ram(PlRamAddress::Battemp)?),
|
||||
regulator_state: self.read_ram(PlRamAddress::Rstate)?.into(),
|
||||
battery_voltage: f64::from(self.read_ram(PlRamAddress::Batv).await?) * (4. / 10.),
|
||||
target_voltage: f64::from(self.read_ram(PlRamAddress::Vreg).await?) * (4. / 10.),
|
||||
duty_cycle: f64::from(self.read_ram(PlRamAddress::Dutycyc).await?) / 255.,
|
||||
internal_charge_current: f64::from(self.read_ram(PlRamAddress::Cint).await?)
|
||||
* (4. / 10.),
|
||||
internal_load_current: f64::from(self.read_ram(PlRamAddress::Lint).await?) * (4. / 10.),
|
||||
battery_temp: f64::from(self.read_ram(PlRamAddress::Battemp).await?),
|
||||
regulator_state: self.read_ram(PlRamAddress::Rstate).await?.into(),
|
||||
})
|
||||
}
|
||||
|
||||
fn send_command(&mut self, req: [u8; 4]) -> eyre::Result<()> {
|
||||
async fn send_command(&mut self, req: [u8; 4]) -> eyre::Result<()> {
|
||||
self.flush()?;
|
||||
self.port.write_all(&req)?;
|
||||
self.port.write_all(&req).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> eyre::Result<()> {
|
||||
self.port.flush()?;
|
||||
while let Ok(num) = self.port.bytes_to_read() {
|
||||
if num == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let _ = self.port.read(&mut [0; 8]);
|
||||
}
|
||||
self.port.clear(tokio_serial::ClearBuffer::All)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn receive<const LENGTH: usize>(&mut self) -> eyre::Result<[u8; LENGTH]> {
|
||||
async fn receive<const LENGTH: usize>(&mut self) -> eyre::Result<[u8; LENGTH]> {
|
||||
let mut buf = [0; LENGTH];
|
||||
self.port.read_exact(&mut buf)?;
|
||||
self.port.read_exact(&mut buf).await?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn read_ram<T>(&mut self, address: T) -> eyre::Result<u8>
|
||||
async fn read_ram<T>(&mut self, address: T) -> eyre::Result<u8>
|
||||
where
|
||||
T: Into<u8>,
|
||||
{
|
||||
self.send_command(command(20, address.into(), 0))?;
|
||||
let buf = self.receive::<1>()?;
|
||||
self.send_command(command(20, address.into(), 0)).await?;
|
||||
let buf = self.receive::<1>().await?;
|
||||
if buf[0] == 200 {
|
||||
Ok(self.receive::<1>()?[0])
|
||||
Ok(self.receive::<1>().await?[0])
|
||||
} else {
|
||||
Err(eyre::eyre!("read error: result is {}", buf[0]))
|
||||
}
|
||||
}
|
||||
|
||||
fn write_ram<T>(&mut self, address: T, data: u8) -> eyre::Result<()>
|
||||
async fn write_ram<T>(&mut self, address: T, data: u8) -> eyre::Result<()>
|
||||
where
|
||||
T: Into<u8>,
|
||||
{
|
||||
self.send_command(command(152, address.into(), data))?;
|
||||
self.send_command(command(152, address.into(), data))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_eeprom<T>(&mut self, address: T) -> eyre::Result<u8>
|
||||
async fn read_eeprom<T>(&mut self, address: T) -> eyre::Result<u8>
|
||||
where
|
||||
T: Into<u8>,
|
||||
{
|
||||
self.send_command(command(72, address.into(), 0))?;
|
||||
let buf = self.receive::<1>()?;
|
||||
self.send_command(command(72, address.into(), 0)).await?;
|
||||
let buf = self.receive::<1>().await?;
|
||||
if buf[0] == 200 {
|
||||
Ok(self.receive::<1>()?[0])
|
||||
Ok(self.receive::<1>().await?[0])
|
||||
} else {
|
||||
Err(eyre::eyre!("read error: result is {}", buf[0]))
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue