mqtt_to_scpi: strip away expected topic
This commit is contained in:
parent
b502b42c92
commit
331d1ff86f
|
@ -33,6 +33,12 @@ branch = "issue-4"
|
|||
default-features = false
|
||||
features = [ "build-info", "unit-frequency" ]
|
||||
|
||||
# Use below SCPI dependency when need to modify SCPI fork offline
|
||||
# [dependencies.scpi]
|
||||
# path = "../scpi-fork/scpi"
|
||||
# default-features = false
|
||||
# features = [ "build-info", "unit-frequency" ]
|
||||
|
||||
[[example]]
|
||||
name = "ethernet"
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ use firmware::{
|
|||
Channel3AttenuationCommand,
|
||||
ClockSourceCommand,
|
||||
ClockDivisionCommand,
|
||||
ProfileCommand
|
||||
},
|
||||
Urukul, scpi_root, recursive_scpi_tree, scpi_tree
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@ use firmware::{
|
|||
Channel3AttenuationCommand,
|
||||
ClockSourceCommand,
|
||||
ClockDivisionCommand,
|
||||
ProfileCommand,
|
||||
},
|
||||
Urukul, scpi_root, recursive_scpi_tree, scpi_tree
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![no_std]
|
||||
#![feature(generic_associated_types)]
|
||||
#![feature(str_strip)]
|
||||
extern crate embedded_hal;
|
||||
use embedded_hal::{
|
||||
digital::v2::OutputPin,
|
||||
|
@ -156,6 +157,7 @@ pub trait UrukulTraits {
|
|||
fn set_clock_source(&mut self, source: ClockSource, frequency: f64) -> Result<(), Self::Error>;
|
||||
fn set_clock_division(&mut self, division: u8) -> Result<(), Self::Error>;
|
||||
fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Self::Error>;
|
||||
fn set_profile(&mut self, profile: u8) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
impl<SPI, E> UrukulTraits for Urukul<SPI>
|
||||
|
@ -234,4 +236,10 @@ where
|
|||
fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Self::Error> {
|
||||
self.attenuator.set_channel_attenuation(channel, attenuation)
|
||||
}
|
||||
|
||||
fn set_profile(&mut self, profile: u8) -> Result<(), Self::Error> {
|
||||
self.config_register.set_configurations(&mut [
|
||||
(CFGMask::PROFILE, profile.into())
|
||||
]).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
|
66
src/scpi.rs
66
src/scpi.rs
|
@ -114,30 +114,27 @@ macro_rules! scpi_root {
|
|||
macro_rules! scpi_tree {
|
||||
() => {
|
||||
scpi_root!(
|
||||
["Control"] => {
|
||||
["Urukul"] => {
|
||||
"CHANNEL0" => {
|
||||
"SWitch" => Channel0SwitchCommand,
|
||||
"Attenuation" => Channel0AttenuationCommand
|
||||
},
|
||||
"CHANNEL1" => {
|
||||
"SWitch" => Channel1SwitchCommand,
|
||||
"Attenuation" => Channel1AttenuationCommand
|
||||
},
|
||||
"CHANNEL2" => {
|
||||
"SWitch" => Channel2SwitchCommand,
|
||||
"Attenuation" => Channel2AttenuationCommand
|
||||
},
|
||||
"CHANNEL3" => {
|
||||
"SWitch" => Channel3SwitchCommand,
|
||||
"Attenuation" => Channel3AttenuationCommand
|
||||
},
|
||||
"CLOCK" => {
|
||||
"SOURCE" => ClockSourceCommand,
|
||||
"DIVision" => ClockDivisionCommand
|
||||
}
|
||||
}
|
||||
"CHANNEL0" => {
|
||||
"SWitch" => Channel0SwitchCommand,
|
||||
"Attenuation" => Channel0AttenuationCommand
|
||||
},
|
||||
"CHANNEL1" => {
|
||||
"SWitch" => Channel1SwitchCommand,
|
||||
"Attenuation" => Channel1AttenuationCommand
|
||||
},
|
||||
"CHANNEL2" => {
|
||||
"SWitch" => Channel2SwitchCommand,
|
||||
"Attenuation" => Channel2AttenuationCommand
|
||||
},
|
||||
"CHANNEL3" => {
|
||||
"SWitch" => Channel3SwitchCommand,
|
||||
"Attenuation" => Channel3AttenuationCommand
|
||||
},
|
||||
"CLOCK" => {
|
||||
"SOURCE" => ClockSourceCommand,
|
||||
"DIVision" => ClockDivisionCommand
|
||||
},
|
||||
"PROFILE" => ProfileCommand,
|
||||
["EXAMple"] => {
|
||||
"HELLO" => {
|
||||
"WORLD" => HelloWorldCommand
|
||||
|
@ -171,6 +168,7 @@ pub struct Channel0AttenuationCommand {}
|
|||
pub struct Channel1AttenuationCommand {}
|
||||
pub struct Channel2AttenuationCommand {}
|
||||
pub struct Channel3AttenuationCommand {}
|
||||
pub struct ProfileCommand {}
|
||||
|
||||
impl<T: Device + UrukulTraits> Command<T> for Channel0SwitchCommand {
|
||||
nquery!();
|
||||
|
@ -356,6 +354,28 @@ impl<T:Device + UrukulTraits> Command<T> for Channel3AttenuationCommand {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T:Device + UrukulTraits> Command<T> for ProfileCommand {
|
||||
nquery!();
|
||||
|
||||
fn event(&self, context: &mut Context<T>, args: &mut Tokenizer) -> Result<()> {
|
||||
let profile :f32 = args.next_data(false)?
|
||||
.map_or(Err(Error::new(ErrorCode::IllegalParameterValue)),
|
||||
|token| token.try_into())?;
|
||||
if ((profile as u8) as f32) != profile {
|
||||
return Err(Error::new(ErrorCode::IllegalParameterValue));
|
||||
}
|
||||
|
||||
trace!("Selected Profile :{}", profile);
|
||||
let profile = profile as u8;
|
||||
if profile >= 8 {
|
||||
Err(Error::new(ErrorCode::IllegalParameterValue))
|
||||
} else {
|
||||
context.device.set_profile(profile)
|
||||
.map_err(|_| Error::new(ErrorCode::HardwareError))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement "Device" trait from SCPI
|
||||
* TODO: Implement mandatory commands
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use scpi::prelude::*;
|
||||
use scpi::Context;
|
||||
use scpi::error::Result;
|
||||
use log::trace;
|
||||
use log::{trace, info};
|
||||
use arrayvec::{ArrayVec};
|
||||
|
||||
pub trait MqttScpiTranslator {
|
||||
|
@ -15,11 +15,19 @@ impl<'a, T: Device> MqttScpiTranslator for Context<'a, T> {
|
|||
where
|
||||
FMT: Formatter,
|
||||
{
|
||||
if !topic.starts_with("Urukul/Control") {
|
||||
info!("Received a publish, but not for control! Topic: {}", topic);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let command_topic = topic.strip_prefix("Urukul/Control/")
|
||||
.unwrap_or("");
|
||||
|
||||
// Create a fixed-size buffer to handle slice operation
|
||||
let mut buffer = ArrayVec::<[u8; 1024]>::new();
|
||||
|
||||
// Copy MQTT topic, convert it into SCPI header format
|
||||
for i in topic.chars() {
|
||||
for i in command_topic.chars() {
|
||||
if i == '/' {
|
||||
// The topic separator is colon(':') in SCPI, and slash('/') in MQTT
|
||||
buffer.try_push(b':')
|
||||
|
|
Loading…
Reference in New Issue