2020-09-15 12:17:42 +08:00
|
|
|
use scpi::prelude::*;
|
|
|
|
use scpi::Context;
|
|
|
|
use scpi::error::Result;
|
2020-09-15 17:50:35 +08:00
|
|
|
use log::{trace, info};
|
2020-09-15 14:03:59 +08:00
|
|
|
use arrayvec::{ArrayVec};
|
2020-09-15 12:17:42 +08:00
|
|
|
|
|
|
|
pub trait MqttScpiTranslator {
|
2020-09-15 13:03:54 +08:00
|
|
|
// Convert an MQTT publish message into SCPI compatible command
|
|
|
|
// The argument part/ MQTT message must follow SCPI standard for parameter formatting
|
|
|
|
fn run_with_mqtt<FMT: Formatter>(&mut self, topic: &str, args: &str, response: &mut FMT) -> Result<()>;
|
2020-09-15 12:17:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: Device> MqttScpiTranslator for Context<'a, T> {
|
2020-09-15 13:03:54 +08:00
|
|
|
fn run_with_mqtt<FMT>(&mut self, topic: &str, args: &str, response: &mut FMT) -> Result<()>
|
2020-09-15 12:17:42 +08:00
|
|
|
where
|
|
|
|
FMT: Formatter,
|
|
|
|
{
|
2020-09-15 17:50:35 +08:00
|
|
|
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("");
|
|
|
|
|
2020-09-15 13:03:54 +08:00
|
|
|
// 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
|
2020-09-15 17:50:35 +08:00
|
|
|
for i in command_topic.chars() {
|
2020-09-15 13:03:54 +08:00
|
|
|
if i == '/' {
|
|
|
|
// The topic separator is colon(':') in SCPI, and slash('/') in MQTT
|
|
|
|
buffer.try_push(b':')
|
2020-09-15 14:03:59 +08:00
|
|
|
.map_err(|_| ErrorCode::OutOfMemory)?;
|
2020-09-15 12:17:42 +08:00
|
|
|
} else {
|
2020-09-15 13:03:54 +08:00
|
|
|
buffer.try_push(i as u8)
|
2020-09-15 14:03:59 +08:00
|
|
|
.map_err(|_| ErrorCode::OutOfMemory)?;
|
2020-09-15 12:17:42 +08:00
|
|
|
}
|
|
|
|
}
|
2020-09-15 13:03:54 +08:00
|
|
|
|
|
|
|
// Place a space bar between header and parameter
|
|
|
|
buffer.try_push(b' ')
|
|
|
|
.map_err(|_| ErrorCode::OutOfMemory)?;
|
|
|
|
|
|
|
|
// Copy the arguments into the buffer
|
|
|
|
for i in args.chars() {
|
|
|
|
buffer.try_push(i as u8)
|
|
|
|
.map_err(|_| ErrorCode::OutOfMemory)?;
|
|
|
|
}
|
|
|
|
|
2020-09-15 14:03:59 +08:00
|
|
|
// Pass the message to SCPI processing unit
|
|
|
|
trace!("Translated MQTT message into SCPI. Translated command: {}",
|
|
|
|
core::str::from_utf8(buffer.as_slice()).unwrap());
|
2020-09-15 13:03:54 +08:00
|
|
|
self.run(buffer.as_slice(), response)
|
2020-09-15 12:17:42 +08:00
|
|
|
}
|
|
|
|
}
|