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

View File

@ -1,22 +1,16 @@
use log::info;
use nom::IResult;
use nom::combinator::{value, map, map_res, not, opt, all_consuming};
use nom::sequence::{terminated, preceded, pair, delimited, tuple};
use nom::bytes::complete::{take, tag, tag_no_case, take_while};
use nom::combinator::{value, map, map_res, opt, all_consuming};
use nom::sequence::{terminated, preceded, pair};
use nom::bytes::complete::{tag, tag_no_case, take_while};
use nom::character::complete::digit1;
use nom::character::is_space;
use nom::branch::alt;
use nom::branch::{permutation, alt};
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 core::convert::TryInto;
use crate::ClockSource as UrukulClockSource;
use crate::ClockSource::*;
use crate::Urukul;
use crate::Error;
@ -286,22 +280,13 @@ impl<SPI, E> MqttMux<SPI> where SPI: Transfer<u8, Error = E> {
}
}
// Topic separator parser
fn topic_separator<'a>(topic: &'a str) -> IResult<&'a str, ()> {
value((), tag("/"))(topic)
}
// Message separator parser
// Read message parameter separator (optional comma and whitespace)
fn message_separator(message: &[u8]) -> IResult<&[u8], ()> {
value(
(),
preceded(
whitespace,
preceded(
tag("/"),
whitespace
)
)
preceded(
opt(
tag(",")
),
whitespace
)(message)
}
@ -401,63 +386,48 @@ fn clock_division_message(message: &[u8]) -> IResult<&[u8], MqttCommand> {
}
// 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> {
all_consuming(
map(
delimited(
tag("{"),
tuple((
permutation((
preceded(
tag_no_case("source:"),
preceded(
whitespace,
preceded(
tag("\"source\":"),
preceded(
whitespace,
terminated(
alt((
value(UrukulClockSource::OSC, tag_no_case("OSC")),
value(UrukulClockSource::MMCX, tag_no_case("MMCX")),
value(UrukulClockSource::SMA, tag_no_case("SMA"))
)),
tag(",")
)
)
)
),
preceded(
whitespace,
preceded(
tag("\"frequency\":"),
preceded(
whitespace,
terminated(
read_frequency,
tag(",")
)
)
)
),
preceded(
whitespace,
preceded(
tag("\"division\":"),
preceded(
whitespace,
terminated(
map_res(
digit1,
|div: &[u8]| u8::from_str_radix(core::str::from_utf8(div).unwrap(), 10)
),
whitespace
)
)
terminated(
alt((
value(UrukulClockSource::OSC, tag_no_case("OSC")),
value(UrukulClockSource::MMCX, tag_no_case("MMCX")),
value(UrukulClockSource::SMA, tag_no_case("SMA"))
)),
message_separator
)
)
)),
tag("}")
),
),
preceded(
tag_no_case("frequency:"),
preceded(
whitespace,
terminated(
read_frequency,
message_separator
)
)
),
preceded(
tag_no_case("division:"),
preceded(
whitespace,
terminated(
map_res(
digit1,
|div: &[u8]| u8::from_str_radix(core::str::from_utf8(div).unwrap(), 10)
),
message_separator
)
)
)
)),
|(src, freq, div): (UrukulClockSource, f64, u8)| MqttCommand::Clock(src, freq, div)
)
)(message)
@ -512,68 +482,50 @@ fn singletone_phase_message(channel: u8, profile: u8, message: &[u8]) -> IResult
}
// 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> {
all_consuming(
map(
tuple((
permutation((
preceded(
tag("{"),
tag_no_case("frequency:"),
preceded(
whitespace,
preceded(
tag("\"frequency\":"),
preceded(
whitespace,
read_frequency
)
terminated(
read_frequency,
message_separator
)
)
),
preceded(
tag(","),
tag_no_case("phase:"),
preceded(
whitespace,
preceded(
tag("\"amplitude\":"),
terminated(
double,
preceded(
whitespace,
double
)
)
)
),
preceded(
tag(","),
preceded(
whitespace,
preceded(
tag("\"phase\":"),
preceded(
whitespace,
terminated(
double,
opt(
preceded(
opt(
preceded(
whitespace,
tag_no_case("deg")
)
),
preceded(
whitespace,
tag("}")
)
whitespace,
tag_no_case("deg")
)
)
),
message_separator
)
)
)
),
preceded(
tag_no_case("amplitude:"),
preceded(
whitespace,
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)
}