use ector::{Actor, ActorRequest, Address, DynamicAddress, Request};
use embassy_sync::{
blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex},
mutex::Mutex,
};
use embedded_hal_async as hal;
use hal::i2c::I2c;
use heapless::Vec;
use crate::{Emc230x, Error, FanSelect};
type Transaction = Request<Message, Result<Response, Error>>;
#[derive(Clone, Copy, Debug)]
pub struct DeviceSelect(pub u8);
#[derive(Clone, Copy, Debug)]
pub enum Message {
GetDeviceCount,
GetDutyCycle(DeviceSelect, FanSelect),
SetDutyCycle(DeviceSelect, FanSelect, u8),
GetFanCount(DeviceSelect),
GetSpeed(DeviceSelect, FanSelect),
SetSpeed(DeviceSelect, FanSelect, u16),
}
pub enum Response {
Ack,
DeviceCount(u8),
DutyCycle(u8),
FanCount(u8),
Speed(u16),
}
pub struct Service<I2C, const N: usize> {
dev_list: Vec<Emc230x<I2C>, N>,
}
impl<I2C: I2c, const N: usize> Service<I2C, N> {
pub fn new(devs: Vec<Emc230x<I2C>, N>) -> Self {
Self { dev_list: devs }
}
}
impl<I2C: I2c, const N: usize> Actor for Service<I2C, N> {
type Message = Transaction;
async fn on_mount<M>(&mut self, _: DynamicAddress<Self::Message>, mut inbox: M) -> !
where
M: ector::Inbox<Self::Message>,
{
loop {
let request = inbox.next().await;
let msg = request.as_ref();
log::info!("Received message: {:?}", msg);
let reply = match msg {
Message::GetDeviceCount => Ok(Response::DeviceCount(self.dev_list.len() as u8)),
Message::SetDutyCycle(dev, fan, duty) => {
if let Some(dev) = self.dev_list.get_mut(dev.0 as usize) {
match dev.set_duty_cycle(*fan, *duty).await {
Ok(_) => Ok(Response::Ack),
Err(e) => Err(e),
}
} else {
Err(Error::InvalidDeviceSelection)
}
}
Message::GetDutyCycle(dev, fan) => {
if let Some(dev) = self.dev_list.get_mut(dev.0 as usize) {
match dev.duty_cycle(*fan).await {
Ok(duty) => Ok(Response::DutyCycle(duty)),
Err(e) => Err(e),
}
} else {
Err(Error::InvalidDeviceSelection)
}
}
Message::GetFanCount(dev) => {
if let Some(dev) = self.dev_list.get_mut(dev.0 as usize) {
Ok(Response::FanCount(dev.count()))
} else {
Err(Error::InvalidDeviceSelection)
}
}
Message::GetSpeed(dev, fan) => {
if let Some(dev) = self.dev_list.get_mut(dev.0 as usize) {
match dev.rpm(*fan).await {
Ok(speed) => Ok(Response::Speed(speed)),
Err(e) => Err(e),
}
} else {
Err(Error::InvalidDeviceSelection)
}
}
Message::SetSpeed(dev, fan, speed) => {
if let Some(dev) = self.dev_list.get_mut(dev.0 as usize) {
match dev.set_rpm(*fan, *speed).await {
Ok(_) => Ok(Response::Ack),
Err(e) => Err(e),
}
} else {
Err(Error::InvalidDeviceSelection)
}
}
};
request.reply(reply).await;
}
}
}
use embassy_sync::channel::Sender;
trait Fan {
async fn set_duty_cycle(&self, duty: u8) -> Result<(), Error>;
async fn duty_cycle(&self) -> Result<u8, Error>;
async fn set_speed(&self, speed: u16) -> Result<(), Error>;
async fn speed(&self) -> Result<u16, Error>;
}
pub struct Emc230xFan<M: ector::mutex::RawMutex + 'static, const N: usize> {
dev: DeviceSelect,
fan: FanSelect,
tx: Address<Transaction, M, N>,
}
impl<M: ector::mutex::RawMutex, const N: usize> Emc230xFan<M, N> {
pub async fn new_list<const V: usize>(
addr: Address<Transaction, M, N>,
) -> Result<Vec<Self, V>, Error> {
let dev_count = match addr.request(Message::GetDeviceCount).await? {
Response::DeviceCount(c) => c,
_ => return Err(Error::UnexpectedServiceMessageType),
};
let mut fans = Vec::new();
for dev in 0..dev_count {
let fan_count = match addr
.request(Message::GetFanCount(DeviceSelect(dev)))
.await?
{
Response::FanCount(c) => c,
_ => return Err(Error::UnexpectedServiceMessageType),
};
for fan in 1..=fan_count {
let res = fans.push(Self {
dev: DeviceSelect(dev),
fan: FanSelect(fan),
tx: addr.clone(),
});
if res.is_err() {
return Err(Error::ServiceDeviceVectorFull);
}
}
}
Ok(fans)
}
}
impl<M: ector::mutex::RawMutex, const N: usize> Fan for Emc230xFan<M, N> {
async fn set_duty_cycle(&self, duty: u8) -> Result<(), Error> {
match self
.tx
.request(Message::SetDutyCycle(self.dev, self.fan, duty))
.await
{
Ok(Response::Ack) => Ok(()),
Err(e) => Err(e),
_ => Err(Error::UnexpectedServiceMessageType),
}
}
async fn duty_cycle(&self) -> Result<u8, Error> {
match self
.tx
.request(Message::GetDutyCycle(self.dev, self.fan))
.await
{
Ok(Response::DutyCycle(duty)) => Ok(duty),
Err(e) => Err(e),
_ => Err(Error::UnexpectedServiceMessageType),
}
}
async fn set_speed(&self, speed: u16) -> Result<(), Error> {
match self
.tx
.request(Message::SetSpeed(self.dev, self.fan, speed))
.await
{
Ok(Response::Ack) => Ok(()),
Err(e) => Err(e),
_ => Err(Error::UnexpectedServiceMessageType),
}
}
async fn speed(&self) -> Result<u16, Error> {
match self.tx.request(Message::GetSpeed(self.dev, self.fan)).await {
Ok(Response::Speed(s)) => Ok(s),
Err(e) => Err(e),
_ => Err(Error::UnexpectedServiceMessageType),
}
}
}