diff --git a/modules/control/Firmware/src/Messages/Parser.cpp b/modules/control/Firmware/src/Messages/Parser.cpp index 0f1a898..a7476ea 100644 --- a/modules/control/Firmware/src/Messages/Parser.cpp +++ b/modules/control/Firmware/src/Messages/Parser.cpp @@ -1,7 +1,48 @@ #include "Parser.h" +#include -message::parser::StateVisitor::StateVisitor(etl::byte_stream_reader &sreader) - : stream{sreader} {} +message::parser::StateVisitor::StateVisitor( + etl::byte_stream_reader &&sreader, + etl::function invalidCallback, + etl::function> messageLightDataCallback, + etl::function> messageInfoCallback, + etl::function> messageWarningCallback, + etl::function> messageErrorCallback, + etl::function> messageSuccessCallback, + etl::function settingsSetBaudCallback, + etl::function> settingsWifiPasswordCallback, + etl::function> settingsWifiSSIDCallback, + etl::function lightControlOnCallback, + etl::function lightControlOffCallback, + etl::function lightControlToggleCallback, + etl::function lightControlIncreaseCallback, + etl::function lightControlDecreaseCallback, + etl::function commandRequestLightDataCallback, + etl::function commandEnterConsoleFlashingCallback, + etl::function commandExitConsoleFlashingCallback, + etl::function commandPairBluetoothCallback, + etl::function commandHelpCallback, + etl::function commandVersionCallback) + : stream{etl::move(sreader)}, invalidCallback{invalidCallback}, + messageLightDataCallback{messageLightDataCallback}, + messageInfoCallback{messageInfoCallback}, + messageWarningCallback{messageWarningCallback}, + messageErrorCallback{messageErrorCallback}, + messageSuccessCallback{messageSuccessCallback}, + settingsSetBaudCallback{settingsSetBaudCallback}, + settingsWifiPasswordCallback{settingsWifiPasswordCallback}, + settingsWifiSSIDCallback{settingsWifiSSIDCallback}, + lightControlOnCallback{lightControlOnCallback}, + lightControlOffCallback{lightControlOffCallback}, + lightControlToggleCallback{lightControlToggleCallback}, + lightControlIncreaseCallback{lightControlIncreaseCallback}, + lightControlDecreaseCallback{lightControlDecreaseCallback}, + commandRequestLightDataCallback{commandRequestLightDataCallback}, + commandEnterConsoleFlashingCallback{commandEnterConsoleFlashingCallback}, + commandExitConsoleFlashingCallback{commandExitConsoleFlashingCallback}, + commandPairBluetoothCallback{commandPairBluetoothCallback}, + commandHelpCallback{commandHelpCallback}, commandVersionCallback{ + commandVersionCallback} {} auto message::parser::StateVisitor::operator()(state::ModeSelection) -> State { if (!stream.available()) { @@ -58,25 +99,76 @@ auto message::parser::StateVisitor::operator()(state::Message) -> State { return state::Invalid{}; } } + auto message::parser::StateVisitor::operator()(state::MessageLightData) -> State { - messageLightDataCallback(); + if (!stream.available()) { + invalidCallback("MessageLightData: Stream not available"); + return state::Invalid{}; + } + + auto msg = stream.read(stream.available()); + if (!msg.has_value()) { + invalidCallback("MessageLightData: Message has no value"); + return state::Invalid{}; + } + messageLightDataCallback(msg.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageInfo) -> State { - messageInfoCallback(); + if (!stream.available()) { + invalidCallback("MessageInfo: Stream not available"); + return state::Invalid{}; + } + + auto msg = stream.read(stream.available()); + if (!msg.has_value()) { + invalidCallback("MessageInfo: Message has no value"); + return state::Invalid{}; + } + messageInfoCallback(msg.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageWarning) -> State { - messageWarningCallback(); + if (!stream.available()) { + invalidCallback("MessageWarning: Stream not available"); + return state::Invalid{}; + } + + auto msg = stream.read(stream.available()); + if (!msg.has_value()) { + invalidCallback("MessageWarning: Message has no value"); + return state::Invalid{}; + } + messageWarningCallback(msg.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageError) -> State { - messageErrorCallback(); + if (!stream.available()) { + invalidCallback("MessageError: Stream not available"); + return state::Invalid{}; + } + + auto msg = stream.read(stream.available()); + if (!msg.has_value()) { + invalidCallback("MessageError: Message has no value"); + return state::Invalid{}; + } + messageErrorCallback(msg.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageSuccess) -> State { - messageSuccessCallback(); + if (!stream.available()) { + invalidCallback("MessageSuccess: Stream not available"); + return state::Invalid{}; + } + + auto msg = stream.read(stream.available()); + if (!msg.has_value()) { + invalidCallback("MessageSuccess: Message has no value"); + return state::Invalid{}; + } + messageSuccessCallback(msg.value()); return state::Complete{}; } @@ -106,17 +198,51 @@ auto message::parser::StateVisitor::operator()(state::Settings) -> State { } auto message::parser::StateVisitor::operator()(state::SettingsSetBaud) -> State { - settingsSetBaudCallback(); + if (!stream.available()) { + invalidCallback("Settings: Stream not available"); + return state::Invalid{}; + } + + auto baud = stream.read(); + + if (!baud.has_value()) { + invalidCallback("SettingsSetBaud: Baud has no value"); + return state::Invalid{}; + } + + settingsSetBaudCallback(baud.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::SettingsWifiPassword) -> State { - settingsWifiPasswordCallback(); + if (!stream.available()) { + invalidCallback("SettingsWifiPassword: Stream not available"); + return state::Invalid{}; + } + + auto passwd = stream.read(stream.available()); + if (!passwd.has_value()) { + invalidCallback("SettingsWifiPassword: Passwd has no value"); + return state::Invalid{}; + } + + settingsWifiPasswordCallback(passwd.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::SettingsWifiSSID) -> State { - settingsWifiSSIDCallback(); + if (!stream.available()) { + invalidCallback("SettingsWifiSSID: Stream not available"); + return state::Invalid{}; + } + + auto ssid = stream.read(stream.available()); + if (!ssid.has_value()) { + invalidCallback("SettingsWifiSSID: SSID has no value"); + return state::Invalid{}; + } + + settingsWifiSSIDCallback(ssid.value()); return state::Complete{}; } @@ -171,8 +297,14 @@ auto message::parser::StateVisitor::operator()(state::LightControlToggle) if (stream.available_bytes() > 1) { invalidCallback("LightControlToggle: Too many bytes left"); return state::Invalid{}; + } else if (!stream.available()) { + invalidCallback("LightControlToggle: Stream not available"); + return state::Invalid{}; } - lightControlToggleCallback(); + + auto id = stream.read(); + + lightControlToggleCallback(id.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControlIncrease) @@ -180,8 +312,14 @@ auto message::parser::StateVisitor::operator()(state::LightControlIncrease) if (stream.available_bytes() > 1) { invalidCallback("LightControlIncrease: Too many bytes left"); return state::Invalid{}; + } else if (!stream.available()) { + invalidCallback("LightControlIncrease: Stream not available"); + return state::Invalid{}; } - lightControlIncreaseCallback(); + + auto id = stream.read(); + + lightControlIncreaseCallback(id.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControlDecrease) @@ -189,8 +327,14 @@ auto message::parser::StateVisitor::operator()(state::LightControlDecrease) if (stream.available_bytes() > 1) { invalidCallback("LightControlDecrease: Too many bytes left"); return state::Invalid{}; + } else if (!stream.available()) { + invalidCallback("LightControlDecrease: Stream not available"); + return state::Invalid{}; } - lightControlDecreaseCallback(); + + auto id = stream.read(); + + lightControlDecreaseCallback(id.value()); return state::Complete{}; } @@ -257,10 +401,20 @@ auto message::parser::StateVisitor::operator()(state::CommandPairBluetooth) return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::CommandHelp) -> State { + if (stream.available_bytes() > 0) { + invalidCallback("CommandHelp: Too many bytes left"); + return state::Invalid{}; + } + commandHelpCallback(); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::CommandVersion) -> State { + if (stream.available_bytes() > 0) { + invalidCallback("CommandVersion: Too many bytes left"); + return state::Invalid{}; + } + commandVersionCallback(); return state::Complete{}; } @@ -272,14 +426,52 @@ auto message::parser::StateVisitor::operator()(state::Invalid) -> State { return state::Invalid{}; } -auto message::parser::parse(etl::byte_stream_reader &reader) -> void { - StateVisitor visitor{reader}; +auto message::parser::parse( + etl::byte_stream_reader &&reader, + etl::function invalidCallback, + etl::function> messageLightDataCallback, + etl::function> messageInfoCallback, + etl::function> messageWarningCallback, + etl::function> messageErrorCallback, + etl::function> messageSuccessCallback, + etl::function settingsSetBaudCallback, + etl::function> settingsWifiPasswordCallback, + etl::function> settingsWifiSSIDCallback, + etl::function lightControlOnCallback, + etl::function lightControlOffCallback, + etl::function lightControlToggleCallback, + etl::function lightControlIncreaseCallback, + etl::function lightControlDecreaseCallback, + etl::function commandRequestLightDataCallback, + etl::function commandEnterConsoleFlashingCallback, + etl::function commandExitConsoleFlashingCallback, + etl::function commandPairBluetoothCallback, + etl::function commandHelpCallback, + etl::function commandVersionCallback) -> void { + StateVisitor visitor{etl::move(reader), + invalidCallback, + messageLightDataCallback, + messageInfoCallback, + messageWarningCallback, + messageErrorCallback, + messageSuccessCallback, + settingsSetBaudCallback, + settingsWifiPasswordCallback, + settingsWifiSSIDCallback, + lightControlOnCallback, + lightControlOffCallback, + lightControlToggleCallback, + lightControlIncreaseCallback, + lightControlDecreaseCallback, + commandRequestLightDataCallback, + commandEnterConsoleFlashingCallback, + commandExitConsoleFlashingCallback, + commandPairBluetoothCallback, + commandHelpCallback, + commandVersionCallback}; State state{state::ModeSelection{}}; while (!etl::holds_alternative(state) && !etl::holds_alternative(state)) { state = etl::visit(visitor, state); } - if (etl::holds_alternative(state)) { - // TODO: error - } } diff --git a/modules/control/Firmware/src/Messages/Parser.h b/modules/control/Firmware/src/Messages/Parser.h index dbd93aa..d9e8774 100644 --- a/modules/control/Firmware/src/Messages/Parser.h +++ b/modules/control/Firmware/src/Messages/Parser.h @@ -2,6 +2,8 @@ #include "Protocol.h" #include #include +#include +#include #include namespace message { @@ -47,11 +49,53 @@ using State = etl::variant< state::CommandExitConsoleFlashing, state::CommandPairBluetooth, state::CommandHelp, state::CommandVersion, state::Complete>; -void parse(etl::byte_stream_reader &reader); +void parse( + etl::byte_stream_reader &&reader, + etl::function invalidCallback, + etl::function> messageLightDataCallback, + etl::function> messageInfoCallback, + etl::function> messageWarningCallback, + etl::function> messageErrorCallback, + etl::function> messageSuccessCallback, + etl::function settingsSetBaudCallback, + etl::function> settingsWifiPasswordCallback, + etl::function> settingsWifiSSIDCallback, + etl::function lightControlOnCallback, + etl::function lightControlOffCallback, + etl::function lightControlToggleCallback, + etl::function lightControlIncreaseCallback, + etl::function lightControlDecreaseCallback, + etl::function commandRequestLightDataCallback, + etl::function commandEnterConsoleFlashingCallback, + etl::function commandExitConsoleFlashingCallback, + etl::function commandPairBluetoothCallback, + etl::function commandHelpCallback, + etl::function commandVersionCallback); class StateVisitor { public: - StateVisitor(etl::byte_stream_reader &); + StateVisitor( + etl::byte_stream_reader &&sreader, + etl::function invalidCallback, + etl::function> messageLightDataCallback, + etl::function> messageInfoCallback, + etl::function> messageWarningCallback, + etl::function> messageErrorCallback, + etl::function> messageSuccessCallback, + etl::function settingsSetBaudCallback, + etl::function> settingsWifiPasswordCallback, + etl::function> settingsWifiSSIDCallback, + etl::function lightControlOnCallback, + etl::function lightControlOffCallback, + etl::function lightControlToggleCallback, + etl::function lightControlIncreaseCallback, + etl::function lightControlDecreaseCallback, + etl::function commandRequestLightDataCallback, + etl::function commandEnterConsoleFlashingCallback, + etl::function commandExitConsoleFlashingCallback, + etl::function commandPairBluetoothCallback, + etl::function commandHelpCallback, + etl::function commandVersionCallback); State operator()(state::ModeSelection); State operator()(state::Message); State operator()(state::MessageLightData); @@ -86,19 +130,19 @@ private: etl::byte_stream_reader stream; // TODO: callback function parameter types etl::function invalidCallback; - etl::function messageLightDataCallback; - etl::function messageInfoCallback; - etl::function messageWarningCallback; - etl::function messageErrorCallback; - etl::function messageSuccessCallback; - etl::function settingsSetBaudCallback; - etl::function settingsWifiPasswordCallback; - etl::function settingsWifiSSIDCallback; + etl::function> messageLightDataCallback; + etl::function> messageInfoCallback; + etl::function> messageWarningCallback; + etl::function> messageErrorCallback; + etl::function> messageSuccessCallback; + etl::function settingsSetBaudCallback; + etl::function> settingsWifiPasswordCallback; + etl::function> settingsWifiSSIDCallback; etl::function lightControlOnCallback; etl::function lightControlOffCallback; - etl::function lightControlToggleCallback; - etl::function lightControlIncreaseCallback; - etl::function lightControlDecreaseCallback; + etl::function lightControlToggleCallback; + etl::function lightControlIncreaseCallback; + etl::function lightControlDecreaseCallback; etl::function commandRequestLightDataCallback; etl::function commandEnterConsoleFlashingCallback; etl::function commandExitConsoleFlashingCallback;