demo handler
This commit is contained in:
1 parent
6cbd3d3271
commit
95fea92235
10 files changed
+429
-83
No files matched your search
Generated
+174
@@ -2,6 +2,180 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||
|
||||
[[package]]
|
||||
name = "devicehandling_traits"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"simplelog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"termcolor",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
@@ -4,3 +4,5 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.30"
|
||||
simplelog = "0.12"
|
||||
+29
-2
@@ -1,6 +1,33 @@
|
||||
use devicehandling_traits::io;
|
||||
use devicehandling_traits::device_handlers::demo_handler::{self, DemoHandler, FirstTelecommandData, SecondTelecommandData, Telecommands as DemoTelecommands};
|
||||
use devicehandling_traits::{init_logging, runtime};
|
||||
use devicehandling_traits::interfaces::echo_interface::EchoInterface;
|
||||
use devicehandling_traits::runtime::{DeviceHandlerRuntime, Mode};
|
||||
|
||||
type RuntimeTelecommands = runtime::Telecommands<DemoHandler>;
|
||||
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
init_logging(log::LevelFilter::Trace);
|
||||
log::info!("Running Demo Handler\n");
|
||||
|
||||
let demo_handler = DemoHandler::new();
|
||||
let mut echo_interface = EchoInterface::new();
|
||||
|
||||
let mut runtime = DeviceHandlerRuntime::new(demo_handler);
|
||||
|
||||
let mode_on_tc = RuntimeTelecommands::Mode(Mode::On);
|
||||
|
||||
runtime.run_once(&mode_on_tc, &mut echo_interface);
|
||||
|
||||
let demo_tc_1 = DemoTelecommands::FirstTelecommand(FirstTelecommandData{a_number: 13});
|
||||
|
||||
runtime.run_once(&RuntimeTelecommands::Device(demo_tc_1), &mut echo_interface);
|
||||
|
||||
let demo_tc_2 = DemoTelecommands::SecondTelecommand(SecondTelecommandData{a_float: 1.2});
|
||||
|
||||
runtime.run_once(&RuntimeTelecommands::Device(demo_tc_2), &mut echo_interface);
|
||||
|
||||
let mode_off_tc = RuntimeTelecommands::Mode(Mode::Off);
|
||||
|
||||
runtime.run_once(&mode_off_tc, &mut echo_interface);
|
||||
}
|
||||
+6
-4
@@ -1,7 +1,9 @@
|
||||
use crate::io::ReadWrite;
|
||||
use crate::io;
|
||||
use core::fmt::Debug;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
Io(io::Error),
|
||||
ParsingError,
|
||||
@@ -18,11 +20,11 @@ impl From<io::Error> for Error{
|
||||
|
||||
pub type Result<T> = core::result::Result<T,Error>;
|
||||
|
||||
pub trait DeviceHandler {
|
||||
pub trait DeviceHandler : Debug {
|
||||
/// Type definition for the Telecommands that the handler will receive
|
||||
type Telecommands;
|
||||
type Telecommands: Debug;
|
||||
// Type definition for the Telemetry that the handler will create
|
||||
type Telemetry;
|
||||
type Telemetry: Debug;
|
||||
|
||||
/// Configure a device which has just been switched on
|
||||
fn init(&mut self, interface: &mut impl ReadWrite) -> Result<()>;
|
||||
@@ -44,7 +46,7 @@ pub trait DeviceHandler {
|
||||
/// Handle telecommand
|
||||
fn handle_telecommand(
|
||||
&mut self,
|
||||
telecommand: Self::Telecommands,
|
||||
telecommand: &Self::Telecommands,
|
||||
interface: &mut impl ReadWrite,
|
||||
) -> Result<Option<Self::Telemetry>>;
|
||||
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
use crate::device::{DeviceHandler, Error::*};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FirstTelecommandData {
|
||||
a_number: u8,
|
||||
pub a_number: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SecondTelecommandData {
|
||||
a_float: f32,
|
||||
pub a_float: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Telecommands {
|
||||
FirstTelecommand(FirstTelecommandData),
|
||||
SecondTelecommand(SecondTelecommandData),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TelemetryData {
|
||||
a_value: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Telemetry {
|
||||
TheOneAndOnlyTelemetry(TelemetryData),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DemoHandler {
|
||||
io_buffer: [u8; 10],
|
||||
}
|
||||
|
||||
impl DemoHandler {
|
||||
const fn new() -> Self {
|
||||
pub const fn new() -> Self {
|
||||
Self { io_buffer: [0; 10] }
|
||||
}
|
||||
|
||||
@@ -52,7 +58,8 @@ impl DemoHandler {
|
||||
data: &FirstTelecommandData,
|
||||
interface: &mut impl crate::io::ReadWrite,
|
||||
) -> crate::device::Result<()> {
|
||||
Ok(())
|
||||
let bytes = [data.a_number,0];
|
||||
self.send_generic_device_command(&bytes, interface)
|
||||
}
|
||||
/// This function converts pub structured data into a byte slice which is then passed to the function building the device's protocol
|
||||
fn send_second_device_command(
|
||||
@@ -60,7 +67,7 @@ impl DemoHandler {
|
||||
data: &SecondTelecommandData,
|
||||
interface: &mut impl crate::io::ReadWrite,
|
||||
) -> crate::device::Result<()> {
|
||||
Ok(())
|
||||
self.send_generic_device_command(&[], interface)
|
||||
}
|
||||
|
||||
/// This fn is stateless and as such not implemented as a member fn
|
||||
@@ -103,6 +110,7 @@ impl DeviceHandler for DemoHandler {
|
||||
type Telemetry = Telemetry;
|
||||
|
||||
fn init(&mut self, interface: &mut impl crate::io::ReadWrite) -> crate::device::Result<()> {
|
||||
log::trace!("Init...");
|
||||
// this is a special write to the device, do it manually:
|
||||
self.io_buffer[0] = 1;
|
||||
self.io_buffer[1] = 2;
|
||||
@@ -125,7 +133,7 @@ impl DeviceHandler for DemoHandler {
|
||||
|
||||
// Use the already implemented fn to handle tc
|
||||
// Again, `?` to simply exit on error
|
||||
let tm = self.handle_telecommand(tc, interface)?;
|
||||
let tm = self.handle_telecommand(&tc, interface)?;
|
||||
|
||||
// Check the reply
|
||||
let Some(Telemetry::TheOneAndOnlyTelemetry(telemetry_data)) = tm else {
|
||||
@@ -141,13 +149,14 @@ impl DeviceHandler for DemoHandler {
|
||||
}
|
||||
|
||||
fn to_on(&mut self, interface: &mut impl crate::io::ReadWrite) -> crate::device::Result<()> {
|
||||
log::trace!("To on...");
|
||||
// use a predefined telecommand
|
||||
let tc = Telecommands::SecondTelecommand(SecondTelecommandData { a_float: 21.0 });
|
||||
|
||||
// Use the already implemented fn to handle tc
|
||||
// Again, `?` to simply exit on error
|
||||
// This tc is expected to generate not reply and no tm
|
||||
let None = self.handle_telecommand(tc, interface)? else {
|
||||
// This tc is expected to generate no reply and no tm
|
||||
let None = self.handle_telecommand(&tc, interface)? else {
|
||||
return Err(UnrequestedReply);
|
||||
};
|
||||
|
||||
@@ -157,14 +166,14 @@ impl DeviceHandler for DemoHandler {
|
||||
|
||||
fn handle_telecommand(
|
||||
&mut self,
|
||||
telecommand: Self::Telecommands,
|
||||
telecommand: &Self::Telecommands,
|
||||
interface: &mut impl crate::io::ReadWrite,
|
||||
) -> crate::device::Result<Option<Self::Telemetry>> {
|
||||
// there might be better ways to pub structure this fn, depending on the device and its commands...
|
||||
|
||||
// Send the device command corresponding to the telecommand, check if the reply matches
|
||||
match telecommand {
|
||||
Telecommands::FirstTelecommand(ref data) => {
|
||||
Telecommands::FirstTelecommand(data) => {
|
||||
self.send_first_device_command(data, interface)?;
|
||||
let reply = interface.read(&mut self.io_buffer)?;
|
||||
let tm = Self::parse_device_reply(reply)?;
|
||||
@@ -175,10 +184,10 @@ impl DeviceHandler for DemoHandler {
|
||||
// };
|
||||
Ok(Some(tm))
|
||||
}
|
||||
Telecommands::SecondTelecommand(ref data) => {
|
||||
Telecommands::SecondTelecommand(data) => {
|
||||
self.send_second_device_command(data, interface)?;
|
||||
let reply = interface.read(&mut self.io_buffer)?;
|
||||
if reply.len() != 0 {
|
||||
if reply.len() != 2 {
|
||||
return Err(UnrequestedReply);
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -198,6 +207,7 @@ impl DeviceHandler for DemoHandler {
|
||||
&mut self,
|
||||
_interface: &mut impl crate::io::ReadWrite,
|
||||
) -> crate::device::Result<()> {
|
||||
log::trace!("Shutdown...");
|
||||
// Nothing to do
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
use crate::io::{Read, Write};
|
||||
|
||||
pub struct EchoInterface{
|
||||
last_received: Vec<u8>
|
||||
}
|
||||
|
||||
impl Read for EchoInterface{
|
||||
fn read<'a>(&self, buffer: &'a mut [u8]) -> crate::io::Result<&'a [u8]> {
|
||||
let buffer_len = buffer.len();
|
||||
if self.last_received.len() >= buffer_len {
|
||||
buffer.copy_from_slice(&self.last_received[..buffer.len()]);
|
||||
Ok(buffer)
|
||||
} else {
|
||||
let result = &mut buffer[..self.last_received.len()];
|
||||
result.copy_from_slice(&self.last_received);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for EchoInterface{
|
||||
fn put(&mut self, data: &[u8]) -> crate::io::Result<()> {
|
||||
self.last_received.extend_from_slice(data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn putc(&mut self, data: u8) -> crate::io::Result<()> {
|
||||
self.last_received.push(data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> crate::io::Result<()> {
|
||||
// there is no actual output...
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//! Simple Interface, which echos previously written data when read
|
||||
//!
|
||||
//! Does not really emulate output queues, so reading after `put`ing will return data
|
||||
|
||||
use crate::io::{Read, Write};
|
||||
|
||||
pub struct EchoInterface {
|
||||
last_received: Vec<u8>,
|
||||
need_to_clear: bool,
|
||||
}
|
||||
|
||||
impl EchoInterface {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
last_received: Vec::new(),
|
||||
need_to_clear: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for EchoInterface {
|
||||
fn read<'a>(&self, buffer: &'a mut [u8]) -> crate::io::Result<&'a [u8]> {
|
||||
let buffer_len = buffer.len();
|
||||
if self.last_received.len() >= buffer_len {
|
||||
buffer.copy_from_slice(&self.last_received[..buffer.len()]);
|
||||
log::trace!("Reading {buffer:02x?}");
|
||||
Ok(buffer)
|
||||
} else {
|
||||
let result = &mut buffer[..self.last_received.len()];
|
||||
result.copy_from_slice(&self.last_received);
|
||||
log::trace!("Reading {result:02x?}");
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for EchoInterface {
|
||||
fn put(&mut self, data: &[u8]) -> crate::io::Result<()> {
|
||||
if self.need_to_clear {
|
||||
self.need_to_clear = false;
|
||||
self.last_received.clear();
|
||||
}
|
||||
log::trace!("Writing {data:02x?}");
|
||||
self.last_received.extend_from_slice(data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn putc(&mut self, data: u8) -> crate::io::Result<()> {
|
||||
if self.need_to_clear {
|
||||
self.need_to_clear = false;
|
||||
self.last_received.clear();
|
||||
}
|
||||
log::trace!("Writing {data:02x?}");
|
||||
self.last_received.push(data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> crate::io::Result<()> {
|
||||
log::trace!("Flushing");
|
||||
// the next write access will be a new buffer, remember to clear
|
||||
self.need_to_clear = true;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod echo_interface;
|
||||
+25
-2
@@ -1,5 +1,28 @@
|
||||
use log::LevelFilter;
|
||||
use simplelog::{ColorChoice, ConfigBuilder, TermLogger, TerminalMode};
|
||||
|
||||
pub mod device;
|
||||
pub mod device_handlers;
|
||||
pub mod echo_interface;
|
||||
pub mod interfaces;
|
||||
pub mod io;
|
||||
pub mod runtime;
|
||||
pub mod runtime;
|
||||
|
||||
pub fn init_logging(level: log::LevelFilter) {
|
||||
// - PRINTOUT ----------------------------------------------
|
||||
// Disable printing of thread id
|
||||
let config = ConfigBuilder::new()
|
||||
.set_thread_level(LevelFilter::Off)
|
||||
.build();
|
||||
// Init the Terminal logger:
|
||||
// * Print messages at Debug level and above
|
||||
// * use config built above to disable thread id printout
|
||||
// * Mixed Mode: Errors go to stderr, rest goes to stdout
|
||||
// * Print colors if able
|
||||
TermLogger::init(
|
||||
level,
|
||||
config,
|
||||
TerminalMode::Mixed,
|
||||
ColorChoice::Auto,
|
||||
)
|
||||
.expect("Logger init failed");
|
||||
}
|
||||
+106
-27
@@ -1,52 +1,131 @@
|
||||
use crate::device::DeviceHandler;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use crate::{device::DeviceHandler, io::ReadWrite};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum Mode{
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub enum Mode {
|
||||
On,
|
||||
Off
|
||||
Off,
|
||||
}
|
||||
|
||||
pub enum Telecommands<T: DeviceHandler>{
|
||||
#[derive(Debug)]
|
||||
pub enum Telecommands<T: DeviceHandler> {
|
||||
Mode(Mode),
|
||||
Device(T::Telecommands),
|
||||
}
|
||||
|
||||
struct DeviceHandlerRuntime<T: DeviceHandler>{
|
||||
pub struct DeviceHandlerRuntime<T: DeviceHandler> {
|
||||
handler: T,
|
||||
mode: Mode,
|
||||
}
|
||||
|
||||
impl<T:DeviceHandler> DeviceHandlerRuntime<T> {
|
||||
fn run_once(&mut self, telecommand: Telecommands<T>) -> Option<T::Telemetry>{
|
||||
|
||||
impl<T: DeviceHandler> DeviceHandlerRuntime<T> {
|
||||
pub const fn new(handler: T) -> Self {
|
||||
Self {
|
||||
handler,
|
||||
mode: Mode::Off,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_mode_tc(&mut self, mode: Mode) {
|
||||
// Off to Off is a no-op
|
||||
if mode == Mode::Off && self.mode == Mode::Off {
|
||||
return;
|
||||
}
|
||||
match mode{
|
||||
Mode::Off => {match self.mode {
|
||||
Mode::Off => (),
|
||||
Mode::On => {
|
||||
self.handler.init(interface);
|
||||
self.handler.to_on(interface);
|
||||
self.mode = mode;
|
||||
pub fn run_once(
|
||||
&mut self,
|
||||
telecommand: &Telecommands<T>,
|
||||
interface: &mut impl ReadWrite,
|
||||
) -> Option<T::Telemetry> {
|
||||
let tm = match telecommand {
|
||||
Telecommands::Mode(commanded_mode) => {
|
||||
self.handle_mode_tc(*commanded_mode, interface);
|
||||
None
|
||||
}
|
||||
Telecommands::Device(device_tc) => self.handle_device_tc(device_tc, interface),
|
||||
};
|
||||
log::info!("Executed {telecommand:?}, got {tm:?}");
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_mode_tc(&mut self, commanded_mode: Mode, interface: &mut impl ReadWrite) {
|
||||
match self.mode {
|
||||
Mode::Off => {
|
||||
match commanded_mode {
|
||||
Mode::Off => {
|
||||
// no-op, announce anyway:
|
||||
self.set_mode(commanded_mode);
|
||||
return;
|
||||
}
|
||||
Mode::On => {
|
||||
log::trace!("Going to on from off");
|
||||
// we are in off mode, so we first need to initialize the device
|
||||
let result = self.handler.init(interface);
|
||||
|
||||
if result.is_err() {
|
||||
log::error!("Device failed to init: {:?}", result);
|
||||
return;
|
||||
};
|
||||
|
||||
// .. then we can switch to on mode
|
||||
let result = self.handler.to_on(interface);
|
||||
|
||||
if result.is_ok() {
|
||||
self.set_mode(commanded_mode);
|
||||
} else {
|
||||
log::error!("Device failed to transition to on mode: {:?}", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
Mode::On => (),
|
||||
}
|
||||
Mode::On => {
|
||||
match commanded_mode {
|
||||
Mode::Off => {
|
||||
log::trace!("Going to off from on");
|
||||
// goint to off, call shutdown
|
||||
let result = self.handler.shutdown(interface);
|
||||
if result.is_err() {
|
||||
log::error!(
|
||||
"Device failed to shutdown, powering off anyway: {:?}",
|
||||
result
|
||||
);
|
||||
}
|
||||
// in this simple implementation, device always goes to off
|
||||
self.set_mode(commanded_mode);
|
||||
return;
|
||||
}
|
||||
Mode::On => {
|
||||
log::trace!("Going to on from on");
|
||||
// we are already in on mode, but transitions are performed whenever commanded:
|
||||
let result = self.handler.to_on(interface);
|
||||
|
||||
if result.is_ok() {
|
||||
self.set_mode(commanded_mode);
|
||||
} else {
|
||||
log::error!("Device failed to transition to on mode: {:?}", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn handle_device_tc(&mut self, tc: T::Telecommands) {
|
||||
|
||||
fn handle_device_tc(
|
||||
&mut self,
|
||||
tc: &T::Telecommands,
|
||||
interface: &mut impl ReadWrite,
|
||||
) -> Option<T::Telemetry> {
|
||||
if self.mode == Mode::Off {
|
||||
log::error!("received device command in mode Off, ignoring...");
|
||||
return None;
|
||||
}
|
||||
let result = self.handler.handle_telecommand(tc, interface);
|
||||
if let Ok(tm) = result {
|
||||
log::trace!("Executed telecommand {tc:?}");
|
||||
tm
|
||||
} else {
|
||||
log::error!("Failed to execute telecommand {tc:?}");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn set_mode(&mut self, mode: Mode) {
|
||||
log::info!("Mode changed from {:?} to {:?}", self.mode, mode);
|
||||
self.mode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user