mqtt_mux: make one-command setter less chunky

This commit is contained in:
occheung 2020-09-23 12:34:13 +08:00
parent 2ef6bb393c
commit bd80274e86
1 changed files with 69 additions and 117 deletions

View File

@ -1,22 +1,16 @@
use log::info; use log::info;
use nom::IResult; use nom::IResult;
use nom::combinator::{value, map, map_res, not, opt, all_consuming}; use nom::combinator::{value, map, map_res, opt, all_consuming};
use nom::sequence::{terminated, preceded, pair, delimited, tuple}; use nom::sequence::{terminated, preceded, pair};
use nom::bytes::complete::{take, tag, tag_no_case, take_while}; use nom::bytes::complete::{tag, tag_no_case, take_while};
use nom::character::complete::digit1; use nom::character::complete::digit1;
use nom::character::is_space; use nom::character::is_space;
use nom::branch::alt; use nom::branch::{permutation, alt};
use nom::number::complete::{float, double}; use nom::number::complete::{float, double};
use uom::si::f64::Frequency;
use uom::si::frequency::{hertz, kilohertz, megahertz, gigahertz};
use arrayvec::ArrayVec;
use embedded_hal::blocking::spi::Transfer; use embedded_hal::blocking::spi::Transfer;
use core::convert::TryInto; use core::convert::TryInto;
use crate::ClockSource as UrukulClockSource; use crate::ClockSource as UrukulClockSource;
use crate::ClockSource::*;
use crate::Urukul; use crate::Urukul;
use crate::Error; use crate::Error;
@ -286,22 +280,13 @@ impl<SPI, E> MqttMux<SPI> where SPI: Transfer<u8, Error = E> {
} }
} }
// Topic separator parser // Read message parameter separator (optional comma and whitespace)
fn topic_separator<'a>(topic: &'a str) -> IResult<&'a str, ()> {
value((), tag("/"))(topic)
}
// Message separator parser
fn message_separator(message: &[u8]) -> IResult<&[u8], ()> { fn message_separator(message: &[u8]) -> IResult<&[u8], ()> {
value(
(),
preceded( preceded(
whitespace, opt(
preceded( tag(",")
tag("/"), ),
whitespace whitespace
)
)
)(message) )(message)
} }
@ -401,18 +386,12 @@ fn clock_division_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
} }
// Parser for one-command master clock setup message // Parser for one-command master clock setup message
// Possible improvements: Chop off redundant braces and quotes
// Allow optional parameters/permutation of parameters
fn clock_message(message: &[u8]) -> IResult<&[u8], MqttCommand> { fn clock_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
all_consuming( all_consuming(
map( map(
delimited( permutation((
tag("{"),
tuple((
preceded( preceded(
whitespace, tag_no_case("source:"),
preceded(
tag("\"source\":"),
preceded( preceded(
whitespace, whitespace,
terminated( terminated(
@ -421,28 +400,22 @@ fn clock_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
value(UrukulClockSource::MMCX, tag_no_case("MMCX")), value(UrukulClockSource::MMCX, tag_no_case("MMCX")),
value(UrukulClockSource::SMA, tag_no_case("SMA")) value(UrukulClockSource::SMA, tag_no_case("SMA"))
)), )),
tag(",") message_separator
)
) )
) )
), ),
preceded( preceded(
whitespace, tag_no_case("frequency:"),
preceded(
tag("\"frequency\":"),
preceded( preceded(
whitespace, whitespace,
terminated( terminated(
read_frequency, read_frequency,
tag(",") message_separator
)
) )
) )
), ),
preceded( preceded(
whitespace, tag_no_case("division:"),
preceded(
tag("\"division\":"),
preceded( preceded(
whitespace, whitespace,
terminated( terminated(
@ -450,14 +423,11 @@ fn clock_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
digit1, digit1,
|div: &[u8]| u8::from_str_radix(core::str::from_utf8(div).unwrap(), 10) |div: &[u8]| u8::from_str_radix(core::str::from_utf8(div).unwrap(), 10)
), ),
whitespace message_separator
)
) )
) )
) )
)), )),
tag("}")
),
|(src, freq, div): (UrukulClockSource, f64, u8)| MqttCommand::Clock(src, freq, div) |(src, freq, div): (UrukulClockSource, f64, u8)| MqttCommand::Clock(src, freq, div)
) )
)(message) )(message)
@ -512,45 +482,22 @@ fn singletone_phase_message(channel: u8, profile: u8, message: &[u8]) -> IResult
} }
// Parser for one-command singletone profile Command // Parser for one-command singletone profile Command
// Using JSON like command structure
// Possible improvements: Chop off redundant braces and quotes
// Allow optional parameters/permutation of parameters
fn singletone_message(channel: u8, profile: u8, message: &[u8]) -> IResult<&[u8], MqttCommand> { fn singletone_message(channel: u8, profile: u8, message: &[u8]) -> IResult<&[u8], MqttCommand> {
all_consuming( all_consuming(
map( map(
tuple(( permutation((
preceded( preceded(
tag("{"), tag_no_case("frequency:"),
preceded( preceded(
whitespace, whitespace,
preceded( terminated(
tag("\"frequency\":"), read_frequency,
preceded( message_separator
whitespace,
read_frequency
)
) )
) )
), ),
preceded( preceded(
tag(","), tag_no_case("phase:"),
preceded(
whitespace,
preceded(
tag("\"amplitude\":"),
preceded(
whitespace,
double
)
)
)
),
preceded(
tag(","),
preceded(
whitespace,
preceded(
tag("\"phase\":"),
preceded( preceded(
whitespace, whitespace,
terminated( terminated(
@ -562,18 +509,23 @@ fn singletone_message(channel: u8, profile: u8, message: &[u8]) -> IResult<&[u8]
tag_no_case("deg") tag_no_case("deg")
) )
), ),
message_separator
)
)
)
),
preceded(
tag_no_case("amplitude:"),
preceded( preceded(
whitespace, whitespace,
tag("}") terminated(
) double,
) message_separator
)
)
) )
) )
) )
)), )),
|(freq, ampl, phase): (f64, f64, f64)| MqttCommand::Singletone(channel, profile, freq, phase, ampl) |(freq, phase, ampl): (f64, f64, f64)| MqttCommand::Singletone(channel, profile, freq, phase, ampl)
) )
)(message) )(message)
} }