diff --git a/Firmware/src/Messages/Parser.cpp b/Firmware/src/Messages/Parser.cpp index a7476ea..55c663d 100644 --- a/Firmware/src/Messages/Parser.cpp +++ b/Firmware/src/Messages/Parser.cpp @@ -1,58 +1,23 @@ #include "Parser.h" +#include +#include #include 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} {} + message::Message *message, + freertos::Queue &lightActionQueue) + : stream{message->first.begin(), message->first.size(), etl::endian::big}, + message{message}, lightActionQueue{lightActionQueue} {} auto message::parser::StateVisitor::operator()(state::ModeSelection) -> State { if (!stream.available()) { - invalidCallback("ModeSelection: Stream not available"); + // invalidCallback("ModeSelection: Stream not available"); return state::Invalid{}; } auto mode = stream.read(); if (!mode.has_value()) { - invalidCallback("ModeSelection: Mode has no value"); + // invalidCallback("ModeSelection: Mode has no value"); return state::Invalid{}; } @@ -66,20 +31,20 @@ auto message::parser::StateVisitor::operator()(state::ModeSelection) -> State { case static_cast(protocol::Mode::Command): return state::Command{}; default: - invalidCallback("ModeSelection: Invalid index"); + // invalidCallback("ModeSelection: Invalid index"); return state::Invalid{}; } } auto message::parser::StateVisitor::operator()(state::Message) -> State { if (!stream.available()) { - invalidCallback("Message: Stream not available"); + // invalidCallback("Message: Stream not available"); return state::Invalid{}; } auto mode = stream.read(); if (!mode.has_value()) { - invalidCallback("Message: Mode has no value"); + // invalidCallback("Message: Mode has no value"); return state::Invalid{}; } @@ -95,7 +60,7 @@ auto message::parser::StateVisitor::operator()(state::Message) -> State { case static_cast(protocol::Message::Success): return state::MessageSuccess{}; default: - invalidCallback("Message: Invalid index"); + // invalidCallback("Message: Invalid index"); return state::Invalid{}; } } @@ -103,84 +68,84 @@ auto message::parser::StateVisitor::operator()(state::Message) -> State { auto message::parser::StateVisitor::operator()(state::MessageLightData) -> State { if (!stream.available()) { - invalidCallback("MessageLightData: Stream not 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"); + // invalidCallback("MessageLightData: Message has no value"); return state::Invalid{}; } - messageLightDataCallback(msg.value()); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageInfo) -> State { if (!stream.available()) { - invalidCallback("MessageInfo: Stream not 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"); + // invalidCallback("MessageInfo: Message has no value"); return state::Invalid{}; } - messageInfoCallback(msg.value()); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageWarning) -> State { if (!stream.available()) { - invalidCallback("MessageWarning: Stream not 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"); + // invalidCallback("MessageWarning: Message has no value"); return state::Invalid{}; } - messageWarningCallback(msg.value()); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageError) -> State { if (!stream.available()) { - invalidCallback("MessageError: Stream not 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"); + // invalidCallback("MessageError: Message has no value"); return state::Invalid{}; } - messageErrorCallback(msg.value()); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::MessageSuccess) -> State { if (!stream.available()) { - invalidCallback("MessageSuccess: Stream not 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"); + // invalidCallback("MessageSuccess: Message has no value"); return state::Invalid{}; } - messageSuccessCallback(msg.value()); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::Settings) -> State { if (!stream.available()) { - invalidCallback("Settings: Stream not available"); + // invalidCallback("Settings: Stream not available"); return state::Invalid{}; } auto mode = stream.read(); if (!mode.has_value()) { - invalidCallback("Settings: Mode has no value"); + // invalidCallback("Settings: Mode has no value"); return state::Invalid{}; } @@ -192,69 +157,66 @@ auto message::parser::StateVisitor::operator()(state::Settings) -> State { case static_cast(protocol::Settings::SetWifiSSID): return state::SettingsWifiSSID{}; default: - invalidCallback("Settings: Invalid index"); + // invalidCallback("Settings: Invalid index"); return state::Invalid{}; } } auto message::parser::StateVisitor::operator()(state::SettingsSetBaud) -> State { if (!stream.available()) { - invalidCallback("Settings: Stream not available"); + // invalidCallback("Settings: Stream not available"); return state::Invalid{}; } auto baud = stream.read(); if (!baud.has_value()) { - invalidCallback("SettingsSetBaud: Baud has no value"); + // invalidCallback("SettingsSetBaud: Baud has no value"); return state::Invalid{}; } - settingsSetBaudCallback(baud.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::SettingsWifiPassword) -> State { if (!stream.available()) { - invalidCallback("SettingsWifiPassword: Stream not 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"); + // invalidCallback("SettingsWifiPassword: Passwd has no value"); return state::Invalid{}; } - settingsWifiPasswordCallback(passwd.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::SettingsWifiSSID) -> State { if (!stream.available()) { - invalidCallback("SettingsWifiSSID: Stream not 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"); + // invalidCallback("SettingsWifiSSID: SSID has no value"); return state::Invalid{}; } - settingsWifiSSIDCallback(ssid.value()); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControl) -> State { if (!stream.available()) { - invalidCallback("LightControl: Stream not available"); + // invalidCallback("LightControl: Stream not available"); return state::Invalid{}; } auto mode = stream.read(); if (!mode.has_value()) { - invalidCallback("LightControl: Mode has no value"); + // invalidCallback("LightControl: Mode has no value"); return state::Invalid{}; } @@ -270,83 +232,92 @@ auto message::parser::StateVisitor::operator()(state::LightControl) -> State { case static_cast(protocol::LightControl::Decrease): return state::LightControlDecrease{}; default: - invalidCallback("LightControl: Invalid index"); + // invalidCallback("LightControl: Invalid index"); return state::Invalid{}; } } auto message::parser::StateVisitor::operator()(state::LightControlOn) -> State { if (stream.available_bytes() > 0) { - invalidCallback("LightControlOn: Too many bytes left"); + // invalidCallback("LightControlOn: Too many bytes left"); return state::Invalid{}; } - lightControlOnCallback(); + + message->second.give(); + Serial.println("ON"); + lightActionQueue.push({LightController::LightActionType::ON, etl::nullopt}); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControlOff) -> State { if (stream.available_bytes() > 0) { - invalidCallback("LightControlOff: Too many bytes left"); + // invalidCallback("LightControlOff: Too many bytes left"); return state::Invalid{}; } - lightControlOffCallback(); + + message->second.give(); + Serial.println("OFF"); + lightActionQueue.push({LightController::LightActionType::OFF, etl::nullopt}); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControlToggle) -> State { if (stream.available_bytes() > 1) { - invalidCallback("LightControlToggle: Too many bytes left"); + // invalidCallback("LightControlToggle: Too many bytes left"); return state::Invalid{}; } else if (!stream.available()) { - invalidCallback("LightControlToggle: Stream not available"); + // invalidCallback("LightControlToggle: Stream not available"); return state::Invalid{}; } auto id = stream.read(); - - lightControlToggleCallback(id.value()); + message->second.give(); + Serial.println("Toggle"); + lightActionQueue.push({LightController::LightActionType::TOGGLE, id}); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControlIncrease) -> State { if (stream.available_bytes() > 1) { - invalidCallback("LightControlIncrease: Too many bytes left"); + // invalidCallback("LightControlIncrease: Too many bytes left"); return state::Invalid{}; } else if (!stream.available()) { - invalidCallback("LightControlIncrease: Stream not available"); + // invalidCallback("LightControlIncrease: Stream not available"); return state::Invalid{}; } auto id = stream.read(); - - lightControlIncreaseCallback(id.value()); + message->second.give(); + Serial.println("Increase"); + lightActionQueue.push({LightController::LightActionType::INCREASE, id}); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::LightControlDecrease) -> State { if (stream.available_bytes() > 1) { - invalidCallback("LightControlDecrease: Too many bytes left"); + // invalidCallback("LightControlDecrease: Too many bytes left"); return state::Invalid{}; } else if (!stream.available()) { - invalidCallback("LightControlDecrease: Stream not available"); + // invalidCallback("LightControlDecrease: Stream not available"); return state::Invalid{}; } auto id = stream.read(); - - lightControlDecreaseCallback(id.value()); + message->second.give(); + Serial.println("Decrease"); + lightActionQueue.push({LightController::LightActionType::DECREASE, id}); return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::Command) -> State { if (!stream.available()) { - invalidCallback("Command: Stream not available"); + // invalidCallback("Command: Stream not available"); return state::Invalid{}; } auto mode = stream.read(); if (!mode.has_value()) { - invalidCallback("Command: Mode has no value"); + // invalidCallback("Command: Mode has no value"); return state::Invalid{}; } @@ -364,58 +335,56 @@ auto message::parser::StateVisitor::operator()(state::Command) -> State { case static_cast(protocol::Command::Version): return state::CommandVersion{}; default: - invalidCallback("Command: Invalid index"); + // invalidCallback("Command: Invalid index"); return state::Invalid{}; } } auto message::parser::StateVisitor::operator()(state::CommandRequestLightData) -> State { - commandRequestLightDataCallback(); + return state::Complete{}; } auto message::parser::StateVisitor::operator()( state::CommandEnterConsoleFlashing) -> State { if (stream.available_bytes() > 0) { - invalidCallback("CommandEnterConsoleFlashing: Too many bytes left"); + // invalidCallback("CommandEnterConsoleFlashing: Too many bytes left"); return state::Invalid{}; } - commandEnterConsoleFlashingCallback(); + return state::Complete{}; } auto message::parser::StateVisitor::operator()( state::CommandExitConsoleFlashing) -> State { if (stream.available_bytes() > 0) { - invalidCallback("CommandExitConsoleFlashing: Too many bytes left"); + // invalidCallback("CommandExitConsoleFlashing: Too many bytes left"); return state::Invalid{}; } - commandExitConsoleFlashingCallback(); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::CommandPairBluetooth) -> State { if (stream.available_bytes() > 0) { - invalidCallback("CommandPairBluetooth: Too many bytes left"); + // invalidCallback("CommandPairBluetooth: Too many bytes left"); return state::Invalid{}; } - commandPairBluetoothCallback(); + return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::CommandHelp) -> State { if (stream.available_bytes() > 0) { - invalidCallback("CommandHelp: Too many bytes left"); + // 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"); + // invalidCallback("CommandVersion: Too many bytes left"); return state::Invalid{}; } - commandVersionCallback(); return state::Complete{}; } @@ -423,55 +392,36 @@ auto message::parser::StateVisitor::operator()(state::Complete) -> State { return state::Complete{}; } auto message::parser::StateVisitor::operator()(state::Invalid) -> State { + message->second.give(); return state::Invalid{}; } 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}; + message::Message *message, + freertos::Queue &lightActionQueue) -> void { + StateVisitor visitor{message, lightActionQueue}; State state{state::ModeSelection{}}; while (!etl::holds_alternative(state) && !etl::holds_alternative(state)) { state = etl::visit(visitor, state); } } + +message::parser::Parser::Parser( + freertos::Queue &lightActionQueue, + UBaseType_t queueCapacity, UBaseType_t priority, BaseType_t coreID) + : parserTask{exec, "parse received data", stackDepth, this, priority, + coreID}, + messages{queueCapacity}, lightActionQueue{lightActionQueue} {} + +void message::parser::Parser::exec(void *parserPtr) { + Parser *parser = static_cast(parserPtr); + + while (true) { + auto message = parser->messages.pop(); + Serial.println("starting parse"); + if (message.has_value()) { + parse(message.value(), parser->lightActionQueue); + } + } +} \ No newline at end of file diff --git a/Firmware/src/Messages/Parser.h b/Firmware/src/Messages/Parser.h index d9e8774..845a956 100644 --- a/Firmware/src/Messages/Parser.h +++ b/Firmware/src/Messages/Parser.h @@ -1,5 +1,9 @@ #pragma once #include "Protocol.h" +#include +#include +#include +#include #include #include #include @@ -49,53 +53,13 @@ using State = etl::variant< state::CommandExitConsoleFlashing, state::CommandPairBluetooth, state::CommandHelp, state::CommandVersion, state::Complete>; -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); +void parse(message::Message *message, + freertos::Queue &lightActionQueue); class StateVisitor { public: - 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); + StateVisitor(message::Message *message, + freertos::Queue &lightActionQueue); State operator()(state::ModeSelection); State operator()(state::Message); State operator()(state::MessageLightData); @@ -128,27 +92,22 @@ public: 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 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; + message::Message *message; + freertos::Queue &lightActionQueue; +}; + +class Parser { +public: + Parser(freertos::Queue &lightActionQueue, + UBaseType_t queueCapacity, UBaseType_t priority, BaseType_t coreID); + freertos::Queue &getMessageQueue() { return messages; } + +private: + static void exec(void *parserPtr); + freertos::Task parserTask; + static const uint32_t stackDepth = 2048; + freertos::Queue messages; + freertos::Queue &lightActionQueue; }; } // namespace parser } // namespace message