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