Compare commits
No commits in common. "d86edf5e9a3bfb0fdc5cd0752438fdca94b8a23c" and "f97ab5f58bf286652a9a1c222d8539370217279c" have entirely different histories.
d86edf5e9a
...
f97ab5f58b
11 changed files with 274 additions and 351 deletions
|
@ -1,61 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1701680307,
|
|
||||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1611574965,
|
|
||||||
"narHash": "sha256-IYtGS077nJFIqSq6Cb8WEJwbqqd4K7S4vUuwPZKfLeo=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs-channels",
|
|
||||||
"rev": "4762fba469e2baa82f983b262e2c06ac2fdaae67",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs-channels",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
inputs = {
|
|
||||||
nixpkgs = {
|
|
||||||
url = "github:nixos/nixpkgs-channels/nixos-unstable";
|
|
||||||
};
|
|
||||||
flake-utils = {
|
|
||||||
url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
outputs = {
|
|
||||||
nixpkgs,
|
|
||||||
flake-utils,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
flake-utils.lib.eachDefaultSystem (
|
|
||||||
system: let
|
|
||||||
pkgs = import nixpkgs {
|
|
||||||
inherit system;
|
|
||||||
};
|
|
||||||
in rec {
|
|
||||||
devShell = pkgs.mkShell {
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
platformio
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -16,12 +16,7 @@ public:
|
||||||
UBaseType_t priority, BaseType_t coreID)
|
UBaseType_t priority, BaseType_t coreID)
|
||||||
: port{port}, messageQueue{messageQueue},
|
: port{port}, messageQueue{messageQueue},
|
||||||
serialReceiverTask{
|
serialReceiverTask{
|
||||||
exec, "receive serial data", stackDepth, this, priority, coreID} {
|
exec, "receive serial data", stackDepth, this, priority, coreID} {}
|
||||||
for (size_t i = 0; i < bufferSize; ++i) {
|
|
||||||
message::Message &msg = buffer.pop();
|
|
||||||
msg.second.give();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void exec(void *receiverPtr) {
|
static void exec(void *receiverPtr) {
|
||||||
|
@ -33,32 +28,22 @@ private:
|
||||||
receiver->magicNumberBuf.clear();
|
receiver->magicNumberBuf.clear();
|
||||||
receiver->magicNumberBuf.resize(receiver->magicNumber.length());
|
receiver->magicNumberBuf.resize(receiver->magicNumber.length());
|
||||||
size_t availableBytes = receiver->port.available();
|
size_t availableBytes = receiver->port.available();
|
||||||
if (receiver->port.available() > 0 && receiver->port.peek() != 'H') {
|
if (availableBytes >= receiver->magicNumber.length() + 1) {
|
||||||
receiver->port.read();
|
|
||||||
receiver->port.println("flush");
|
|
||||||
} else if (availableBytes >= receiver->magicNumber.length() + 1) {
|
|
||||||
receiver->port.readBytes(receiver->magicNumberBuf.data(),
|
receiver->port.readBytes(receiver->magicNumberBuf.data(),
|
||||||
receiver->magicNumber.length());
|
receiver->magicNumber.length());
|
||||||
receiver->port.println("Received Magic Number:");
|
receiver->port.println(receiver->magicNumberBuf ==
|
||||||
receiver->port.println(receiver->magicNumberBuf == receiver->magicNumber
|
receiver->magicNumber);
|
||||||
? "correct"
|
|
||||||
: "incorrect");
|
|
||||||
|
|
||||||
if (receiver->magicNumberBuf == receiver->magicNumber) {
|
uint8_t size;
|
||||||
uint8_t size;
|
receiver->port.readBytes(&size, sizeof(size));
|
||||||
receiver->port.readBytes(&size, sizeof(size));
|
if (receiver->port.available() >= size) {
|
||||||
if (receiver->port.available() >= size) {
|
message::Message &msg = receiver->buffer.pop();
|
||||||
message::Message &msg = receiver->buffer.pop();
|
msg.second.lock();
|
||||||
receiver->port.printf("Current semaphore count: %u\n",
|
msg.first.clear();
|
||||||
msg.second.getCount());
|
msg.first.resize(size);
|
||||||
msg.second.take();
|
receiver->port.readBytes(msg.first.data(), size);
|
||||||
msg.first.clear();
|
msg.second.unlock();
|
||||||
msg.first.resize(size);
|
receiver->messageQueue.push(&msg);
|
||||||
receiver->port.readBytes(msg.first.data(), size);
|
|
||||||
// msg.second.unlock();
|
|
||||||
receiver->port.println("Push message to queue");
|
|
||||||
receiver->messageQueue.push(&msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,11 @@ auto freertos::BinarySemaphore::operator=(
|
||||||
}
|
}
|
||||||
auto freertos::BinarySemaphore::take(TickType_t timeout) -> bool {
|
auto freertos::BinarySemaphore::take(TickType_t timeout) -> bool {
|
||||||
BaseType_t success = xSemaphoreTake(handle, timeout);
|
BaseType_t success = xSemaphoreTake(handle, timeout);
|
||||||
return success == pdTRUE;
|
return success == pdTRUE ? true : false;
|
||||||
}
|
}
|
||||||
auto freertos::BinarySemaphore::give() -> bool {
|
auto freertos::BinarySemaphore::give() -> bool {
|
||||||
BaseType_t success = xSemaphoreGive(handle);
|
BaseType_t success = xSemaphoreGive(handle);
|
||||||
return success == pdTRUE;
|
return success == pdTRUE ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto freertos::BinarySemaphore::getCount() -> size_t {
|
auto freertos::BinarySemaphore::getCount() -> size_t {
|
||||||
|
|
|
@ -12,9 +12,9 @@ auto freertos::Mutex::operator=(const Mutex &&other) noexcept -> Mutex & {
|
||||||
}
|
}
|
||||||
auto freertos::Mutex::lock(TickType_t timeout) -> bool{
|
auto freertos::Mutex::lock(TickType_t timeout) -> bool{
|
||||||
BaseType_t success = xSemaphoreTake(handle, timeout);
|
BaseType_t success = xSemaphoreTake(handle, timeout);
|
||||||
return success == pdTRUE;
|
return success == pdTRUE ? true : false;
|
||||||
}
|
}
|
||||||
auto freertos::Mutex::unlock() -> bool {
|
auto freertos::Mutex::unlock() -> bool {
|
||||||
BaseType_t success = xSemaphoreGive(handle);
|
BaseType_t success = xSemaphoreGive(handle);
|
||||||
return success == pdTRUE;
|
return success == pdTRUE ? true : false;
|
||||||
}
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <FreeRTOS/Mutex.h>
|
|
||||||
#include <FreeRTOS/Queue.h>
|
#include <FreeRTOS/Queue.h>
|
||||||
#include <FreeRTOS/Task.h>
|
#include <FreeRTOS/Task.h>
|
||||||
#include <FreeRTOS/Util.h>
|
|
||||||
#include <etl/optional.h>
|
#include <etl/optional.h>
|
||||||
#include <etl/span.h>
|
#include <etl/span.h>
|
||||||
|
|
||||||
|
@ -13,18 +11,13 @@ using LightAction = etl::pair<LightActionType, etl::optional<uint8_t>>;
|
||||||
|
|
||||||
template <int... PIN> class Controller {
|
template <int... PIN> class Controller {
|
||||||
public:
|
public:
|
||||||
Controller(size_t actionQueueSize, UBaseType_t controllerPriority,
|
Controller(size_t actionQueueSize, UBaseType_t priority, BaseType_t coreID)
|
||||||
BaseType_t controllerCoreID, UBaseType_t faderPriority,
|
|
||||||
BaseType_t faderCoreID)
|
|
||||||
: lightPins{PIN...}, lightActions{actionQueueSize},
|
: lightPins{PIN...}, lightActions{actionQueueSize},
|
||||||
lightControllerTask{exec, "control lights", stackDepth,
|
lightControllerTask{exec, "control lights", stackDepth,
|
||||||
this, controllerPriority, controllerCoreID},
|
this, priority, coreID} {
|
||||||
lightFaderTask{execFade, "fade lights", stackDepth,
|
|
||||||
this, faderPriority, faderCoreID} {
|
|
||||||
for (int pin : lightPins) {
|
for (int pin : lightPins) {
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
}
|
}
|
||||||
lightStatesCurrent.second.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
freertos::Queue<LightAction> &getActionQueue() { return lightActions; }
|
freertos::Queue<LightAction> &getActionQueue() { return lightActions; }
|
||||||
|
@ -33,7 +26,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void exec(void *controllerPtr) {
|
static void exec(void *controllerPtr) {
|
||||||
Controller *controller{static_cast<Controller *>(controllerPtr)};
|
Controller<PIN...> *controller{
|
||||||
|
static_cast<Controller<PIN...> *>(controllerPtr)};
|
||||||
|
etl::array<uint8_t, sizeof...(PIN)> lightStates;
|
||||||
|
const uint8_t step = 5;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto action{controller->getActionQueue().pop()};
|
auto action{controller->getActionQueue().pop()};
|
||||||
|
@ -43,84 +39,45 @@ private:
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LightActionType::INCREASE:
|
case LightActionType::INCREASE:
|
||||||
if (index.has_value() &&
|
if (index.has_value() && index.value() < lightStates.size() &&
|
||||||
index.value() < controller->lightStatesFinal.size() &&
|
lightStates[index.value()] <= 255 - step) {
|
||||||
controller->lightStatesFinal[index.value()] <=
|
lightStates[index.value()] += step;
|
||||||
255 - controller->step) {
|
|
||||||
controller->lightStatesFinal[index.value()] += controller->step;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LightActionType::DECREASE:
|
case LightActionType::DECREASE:
|
||||||
if (index.has_value() &&
|
if (index.has_value() && index.value() < lightStates.size() &&
|
||||||
index.value() < controller->lightStatesFinal.size() &&
|
lightStates[index.value()] >= 0) {
|
||||||
controller->lightStatesFinal[index.value()] >= 0) {
|
lightStates[index.value()] -= step;
|
||||||
controller->lightStatesFinal[index.value()] -= controller->step;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LightActionType::TOGGLE:
|
case LightActionType::TOGGLE:
|
||||||
if (index.has_value() &&
|
if (index.has_value() && index.value() < lightStates.size()) {
|
||||||
index.value() < controller->lightStatesFinal.size()) {
|
lightStates[index.value()] =
|
||||||
controller->lightStatesCurrent.second.lock();
|
lightStates[index.value()] == 0 ? 255 : 0;
|
||||||
controller->lightStatesFinal[index.value()] =
|
|
||||||
controller->lightStatesFinal[index.value()] == 0 ? 255 : 0;
|
|
||||||
controller->lightStatesCurrent.first[index.value()] =
|
|
||||||
controller->lightStatesFinal[index.value()];
|
|
||||||
controller->lightStatesCurrent.second.unlock();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LightActionType::ON:
|
case LightActionType::ON:
|
||||||
controller->lightStatesCurrent.second.lock();
|
lightStates.fill(255);
|
||||||
controller->lightStatesFinal.fill(255);
|
|
||||||
controller->lightStatesCurrent.first.fill(255);
|
|
||||||
controller->lightStatesCurrent.second.unlock();
|
|
||||||
break;
|
break;
|
||||||
case LightActionType::OFF:
|
case LightActionType::OFF:
|
||||||
controller->lightStatesCurrent.second.lock();
|
lightStates.fill(0);
|
||||||
controller->lightStatesFinal.fill(0);
|
|
||||||
controller->lightStatesCurrent.first.fill(0);
|
|
||||||
controller->lightStatesCurrent.second.unlock();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void execFade(void *controllerPtr) {
|
for (size_t lightIndex = 0; lightIndex < lightStates.size();
|
||||||
Controller *controller{static_cast<Controller *>(controllerPtr)};
|
++lightIndex) {
|
||||||
while (true) {
|
analogWrite(controller->getPins()[lightIndex],
|
||||||
freertos::sleep(controller->fadeRate);
|
lightStates[lightIndex]);
|
||||||
controller->lightStatesCurrent.second.lock();
|
|
||||||
for (size_t i = 0; i < controller->lightStatesFinal.size(); i++) {
|
|
||||||
if (controller->lightStatesCurrent.first[i] <
|
|
||||||
controller->lightStatesFinal[i]) {
|
|
||||||
controller->lightStatesCurrent.first[i] += 1;
|
|
||||||
} else if (controller->lightStatesCurrent.first[i] >
|
|
||||||
controller->lightStatesFinal[i]) {
|
|
||||||
controller->lightStatesCurrent.first[i] -= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t lightIndex = 0;
|
|
||||||
lightIndex < controller->lightStatesCurrent.first.size();
|
|
||||||
++lightIndex) {
|
|
||||||
analogWrite(controller->getPins()[lightIndex],
|
|
||||||
controller->lightStatesCurrent.first[lightIndex]);
|
|
||||||
}
|
|
||||||
controller->lightStatesCurrent.second.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t stackDepth = 2048;
|
static const uint32_t stackDepth = 2048;
|
||||||
const uint8_t step = 5;
|
|
||||||
const size_t fadeRate = 50;
|
|
||||||
etl::array<int, sizeof...(PIN)> lightPins;
|
etl::array<int, sizeof...(PIN)> lightPins;
|
||||||
freertos::Queue<LightAction> lightActions;
|
freertos::Queue<LightAction> lightActions;
|
||||||
freertos::Task lightControllerTask;
|
freertos::Task lightControllerTask;
|
||||||
freertos::Task lightFaderTask;
|
|
||||||
etl::array<uint8_t, sizeof...(PIN)> lightStatesFinal;
|
|
||||||
etl::pair<etl::array<uint8_t, sizeof...(PIN)>, freertos::Mutex>
|
|
||||||
lightStatesCurrent;
|
|
||||||
};
|
};
|
||||||
} // namespace LightController
|
} // namespace LightController
|
||||||
|
|
|
@ -1,21 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
#include <etl/optional.h>
|
|
||||||
#include <etl/span.h>
|
|
||||||
#include <etl/string.h>
|
#include <etl/string.h>
|
||||||
|
|
||||||
namespace message {
|
namespace message {
|
||||||
namespace composer {
|
namespace composer {
|
||||||
enum class ComposableType {
|
|
||||||
MESSAGE_LIGHTDATA,
|
|
||||||
MESSAGE_INFO,
|
|
||||||
MESSAGE_WARNING,
|
|
||||||
MESSAGE_ERROR,
|
|
||||||
MESSAGE_SUCCESS,
|
|
||||||
COMMAND_HELP,
|
|
||||||
COMMAND_VERSION,
|
|
||||||
};
|
|
||||||
using Composable = etl::pair<ComposableType, etl::optional<etl::span<uint8_t>>>;
|
|
||||||
bool sendMessage(protocol::Message type, etl::string_view content);
|
bool sendMessage(protocol::Message type, etl::string_view content);
|
||||||
} // namespace composer
|
} // namespace composer
|
||||||
} // namespace message
|
} // namespace message
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <FreeRTOS/BinarySemaphore.h>
|
#include <FreeRTOS/Mutex.h>
|
||||||
#include <Messages/Protocol.h>
|
#include <Messages/Protocol.h>
|
||||||
#include <etl/utility.h>
|
#include <etl/utility.h>
|
||||||
#include <etl/vector.h>
|
#include <etl/vector.h>
|
||||||
|
|
||||||
namespace message {
|
namespace message {
|
||||||
/// @brief first: data, second: data ready to reuse
|
|
||||||
using Message =
|
using Message =
|
||||||
etl::pair<etl::vector<uint8_t, message::protocol::MAX_PAYLOAD_LEN>,
|
etl::pair<etl::vector<uint8_t, message::protocol::MAX_PAYLOAD_LEN>,
|
||||||
freertos::BinarySemaphore>;
|
freertos::Mutex>;
|
||||||
} // namespace message
|
} // namespace message
|
||||||
|
|
|
@ -1,23 +1,58 @@
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
#include <FreeRTOS/Util.h>
|
|
||||||
#include <PinMap/PinMap.h>
|
|
||||||
#include <etl/vector.h>
|
#include <etl/vector.h>
|
||||||
|
|
||||||
message::parser::StateVisitor::StateVisitor(
|
message::parser::StateVisitor::StateVisitor(
|
||||||
message::Message *message,
|
etl::byte_stream_reader &&sreader,
|
||||||
freertos::Queue<LightController::LightAction> &lightActionQueue)
|
etl::function<void, etl::string_view> invalidCallback,
|
||||||
: stream{message->first.begin(), message->first.size(), etl::endian::big},
|
etl::function<void, etl::span<const char>> messageLightDataCallback,
|
||||||
message{message}, lightActionQueue{lightActionQueue} {}
|
etl::function<void, etl::span<const char>> messageInfoCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageWarningCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageErrorCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageSuccessCallback,
|
||||||
|
etl::function<void, uint32_t> settingsSetBaudCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiPasswordCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiSSIDCallback,
|
||||||
|
etl::function<void, void> lightControlOnCallback,
|
||||||
|
etl::function<void, void> lightControlOffCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlToggleCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlIncreaseCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlDecreaseCallback,
|
||||||
|
etl::function<void, void> commandRequestLightDataCallback,
|
||||||
|
etl::function<void, void> commandEnterConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandExitConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandPairBluetoothCallback,
|
||||||
|
etl::function<void, void> commandHelpCallback,
|
||||||
|
etl::function<void, void> 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 {
|
auto message::parser::StateVisitor::operator()(state::ModeSelection) -> State {
|
||||||
if (!stream.available<uint8_t>()) {
|
if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("ModeSelection: Stream not available");
|
invalidCallback("ModeSelection: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mode = stream.read<uint8_t>();
|
auto mode = stream.read<uint8_t>();
|
||||||
if (!mode.has_value()) {
|
if (!mode.has_value()) {
|
||||||
// invalidCallback("ModeSelection: Mode has no value");
|
invalidCallback("ModeSelection: Mode has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,20 +66,20 @@ auto message::parser::StateVisitor::operator()(state::ModeSelection) -> State {
|
||||||
case static_cast<uint8_t>(protocol::Mode::Command):
|
case static_cast<uint8_t>(protocol::Mode::Command):
|
||||||
return state::Command{};
|
return state::Command{};
|
||||||
default:
|
default:
|
||||||
// invalidCallback("ModeSelection: Invalid index");
|
invalidCallback("ModeSelection: Invalid index");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message::parser::StateVisitor::operator()(state::Message) -> State {
|
auto message::parser::StateVisitor::operator()(state::Message) -> State {
|
||||||
if (!stream.available<uint8_t>()) {
|
if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("Message: Stream not available");
|
invalidCallback("Message: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mode = stream.read<uint8_t>();
|
auto mode = stream.read<uint8_t>();
|
||||||
if (!mode.has_value()) {
|
if (!mode.has_value()) {
|
||||||
// invalidCallback("Message: Mode has no value");
|
invalidCallback("Message: Mode has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +95,7 @@ auto message::parser::StateVisitor::operator()(state::Message) -> State {
|
||||||
case static_cast<uint8_t>(protocol::Message::Success):
|
case static_cast<uint8_t>(protocol::Message::Success):
|
||||||
return state::MessageSuccess{};
|
return state::MessageSuccess{};
|
||||||
default:
|
default:
|
||||||
// invalidCallback("Message: Invalid index");
|
invalidCallback("Message: Invalid index");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,84 +103,84 @@ auto message::parser::StateVisitor::operator()(state::Message) -> State {
|
||||||
auto message::parser::StateVisitor::operator()(state::MessageLightData)
|
auto message::parser::StateVisitor::operator()(state::MessageLightData)
|
||||||
-> State {
|
-> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("MessageLightData: Stream not available");
|
invalidCallback("MessageLightData: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto msg = stream.read<char>(stream.available<char>());
|
auto msg = stream.read<char>(stream.available<char>());
|
||||||
if (!msg.has_value()) {
|
if (!msg.has_value()) {
|
||||||
// invalidCallback("MessageLightData: Message has no value");
|
invalidCallback("MessageLightData: Message has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
messageLightDataCallback(msg.value());
|
||||||
return state::Invalid{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::MessageInfo) -> State {
|
auto message::parser::StateVisitor::operator()(state::MessageInfo) -> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("MessageInfo: Stream not available");
|
invalidCallback("MessageInfo: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto msg = stream.read<char>(stream.available<char>());
|
auto msg = stream.read<char>(stream.available<char>());
|
||||||
if (!msg.has_value()) {
|
if (!msg.has_value()) {
|
||||||
// invalidCallback("MessageInfo: Message has no value");
|
invalidCallback("MessageInfo: Message has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
messageInfoCallback(msg.value());
|
||||||
return state::Invalid{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::MessageWarning) -> State {
|
auto message::parser::StateVisitor::operator()(state::MessageWarning) -> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("MessageWarning: Stream not available");
|
invalidCallback("MessageWarning: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto msg = stream.read<char>(stream.available<char>());
|
auto msg = stream.read<char>(stream.available<char>());
|
||||||
if (!msg.has_value()) {
|
if (!msg.has_value()) {
|
||||||
// invalidCallback("MessageWarning: Message has no value");
|
invalidCallback("MessageWarning: Message has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
messageWarningCallback(msg.value());
|
||||||
return state::Invalid{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::MessageError) -> State {
|
auto message::parser::StateVisitor::operator()(state::MessageError) -> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("MessageError: Stream not available");
|
invalidCallback("MessageError: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto msg = stream.read<char>(stream.available<char>());
|
auto msg = stream.read<char>(stream.available<char>());
|
||||||
if (!msg.has_value()) {
|
if (!msg.has_value()) {
|
||||||
// invalidCallback("MessageError: Message has no value");
|
invalidCallback("MessageError: Message has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
messageErrorCallback(msg.value());
|
||||||
return state::Invalid{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::MessageSuccess) -> State {
|
auto message::parser::StateVisitor::operator()(state::MessageSuccess) -> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("MessageSuccess: Stream not available");
|
invalidCallback("MessageSuccess: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto msg = stream.read<char>(stream.available<char>());
|
auto msg = stream.read<char>(stream.available<char>());
|
||||||
if (!msg.has_value()) {
|
if (!msg.has_value()) {
|
||||||
// invalidCallback("MessageSuccess: Message has no value");
|
invalidCallback("MessageSuccess: Message has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
messageSuccessCallback(msg.value());
|
||||||
return state::Invalid{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message::parser::StateVisitor::operator()(state::Settings) -> State {
|
auto message::parser::StateVisitor::operator()(state::Settings) -> State {
|
||||||
if (!stream.available<uint8_t>()) {
|
if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("Settings: Stream not available");
|
invalidCallback("Settings: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mode = stream.read<uint8_t>();
|
auto mode = stream.read<uint8_t>();
|
||||||
if (!mode.has_value()) {
|
if (!mode.has_value()) {
|
||||||
// invalidCallback("Settings: Mode has no value");
|
invalidCallback("Settings: Mode has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,66 +192,69 @@ auto message::parser::StateVisitor::operator()(state::Settings) -> State {
|
||||||
case static_cast<uint8_t>(protocol::Settings::SetWifiSSID):
|
case static_cast<uint8_t>(protocol::Settings::SetWifiSSID):
|
||||||
return state::SettingsWifiSSID{};
|
return state::SettingsWifiSSID{};
|
||||||
default:
|
default:
|
||||||
// invalidCallback("Settings: Invalid index");
|
invalidCallback("Settings: Invalid index");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::SettingsSetBaud)
|
auto message::parser::StateVisitor::operator()(state::SettingsSetBaud)
|
||||||
-> State {
|
-> State {
|
||||||
if (!stream.available<uint32_t>()) {
|
if (!stream.available<uint32_t>()) {
|
||||||
// invalidCallback("Settings: Stream not available");
|
invalidCallback("Settings: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto baud = stream.read<uint32_t>();
|
auto baud = stream.read<uint32_t>();
|
||||||
|
|
||||||
if (!baud.has_value()) {
|
if (!baud.has_value()) {
|
||||||
// invalidCallback("SettingsSetBaud: Baud has no value");
|
invalidCallback("SettingsSetBaud: Baud has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
return state::Invalid{};
|
settingsSetBaudCallback(baud.value());
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::SettingsWifiPassword)
|
auto message::parser::StateVisitor::operator()(state::SettingsWifiPassword)
|
||||||
-> State {
|
-> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("SettingsWifiPassword: Stream not available");
|
invalidCallback("SettingsWifiPassword: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto passwd = stream.read<char>(stream.available<char>());
|
auto passwd = stream.read<char>(stream.available<char>());
|
||||||
if (!passwd.has_value()) {
|
if (!passwd.has_value()) {
|
||||||
// invalidCallback("SettingsWifiPassword: Passwd has no value");
|
invalidCallback("SettingsWifiPassword: Passwd has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
return state::Invalid{};
|
settingsWifiPasswordCallback(passwd.value());
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::SettingsWifiSSID)
|
auto message::parser::StateVisitor::operator()(state::SettingsWifiSSID)
|
||||||
-> State {
|
-> State {
|
||||||
if (!stream.available<char>()) {
|
if (!stream.available<char>()) {
|
||||||
// invalidCallback("SettingsWifiSSID: Stream not available");
|
invalidCallback("SettingsWifiSSID: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ssid = stream.read<char>(stream.available<char>());
|
auto ssid = stream.read<char>(stream.available<char>());
|
||||||
if (!ssid.has_value()) {
|
if (!ssid.has_value()) {
|
||||||
// invalidCallback("SettingsWifiSSID: SSID has no value");
|
invalidCallback("SettingsWifiSSID: SSID has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
return state::Invalid{};
|
settingsWifiSSIDCallback(ssid.value());
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message::parser::StateVisitor::operator()(state::LightControl) -> State {
|
auto message::parser::StateVisitor::operator()(state::LightControl) -> State {
|
||||||
if (!stream.available<uint8_t>()) {
|
if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("LightControl: Stream not available");
|
invalidCallback("LightControl: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mode = stream.read<uint8_t>();
|
auto mode = stream.read<uint8_t>();
|
||||||
if (!mode.has_value()) {
|
if (!mode.has_value()) {
|
||||||
// invalidCallback("LightControl: Mode has no value");
|
invalidCallback("LightControl: Mode has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,92 +270,83 @@ auto message::parser::StateVisitor::operator()(state::LightControl) -> State {
|
||||||
case static_cast<uint8_t>(protocol::LightControl::Decrease):
|
case static_cast<uint8_t>(protocol::LightControl::Decrease):
|
||||||
return state::LightControlDecrease{};
|
return state::LightControlDecrease{};
|
||||||
default:
|
default:
|
||||||
// invalidCallback("LightControl: Invalid index");
|
invalidCallback("LightControl: Invalid index");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message::parser::StateVisitor::operator()(state::LightControlOn) -> State {
|
auto message::parser::StateVisitor::operator()(state::LightControlOn) -> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("LightControlOn: Too many bytes left");
|
invalidCallback("LightControlOn: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
lightControlOnCallback();
|
||||||
message->second.give();
|
|
||||||
Serial.println("ON");
|
|
||||||
lightActionQueue.push({LightController::LightActionType::ON, etl::nullopt});
|
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::LightControlOff)
|
auto message::parser::StateVisitor::operator()(state::LightControlOff)
|
||||||
-> State {
|
-> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("LightControlOff: Too many bytes left");
|
invalidCallback("LightControlOff: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
lightControlOffCallback();
|
||||||
message->second.give();
|
|
||||||
Serial.println("OFF");
|
|
||||||
lightActionQueue.push({LightController::LightActionType::OFF, etl::nullopt});
|
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::LightControlToggle)
|
auto message::parser::StateVisitor::operator()(state::LightControlToggle)
|
||||||
-> State {
|
-> State {
|
||||||
if (stream.available_bytes() > 1) {
|
if (stream.available_bytes() > 1) {
|
||||||
// invalidCallback("LightControlToggle: Too many bytes left");
|
invalidCallback("LightControlToggle: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
} else if (!stream.available<uint8_t>()) {
|
} else if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("LightControlToggle: Stream not available");
|
invalidCallback("LightControlToggle: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto id = stream.read<uint8_t>();
|
auto id = stream.read<uint8_t>();
|
||||||
message->second.give();
|
|
||||||
Serial.println("Toggle");
|
lightControlToggleCallback(id.value());
|
||||||
lightActionQueue.push({LightController::LightActionType::TOGGLE, id});
|
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::LightControlIncrease)
|
auto message::parser::StateVisitor::operator()(state::LightControlIncrease)
|
||||||
-> State {
|
-> State {
|
||||||
if (stream.available_bytes() > 1) {
|
if (stream.available_bytes() > 1) {
|
||||||
// invalidCallback("LightControlIncrease: Too many bytes left");
|
invalidCallback("LightControlIncrease: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
} else if (!stream.available<uint8_t>()) {
|
} else if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("LightControlIncrease: Stream not available");
|
invalidCallback("LightControlIncrease: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto id = stream.read<uint8_t>();
|
auto id = stream.read<uint8_t>();
|
||||||
message->second.give();
|
|
||||||
Serial.println("Increase");
|
lightControlIncreaseCallback(id.value());
|
||||||
lightActionQueue.push({LightController::LightActionType::INCREASE, id});
|
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::LightControlDecrease)
|
auto message::parser::StateVisitor::operator()(state::LightControlDecrease)
|
||||||
-> State {
|
-> State {
|
||||||
if (stream.available_bytes() > 1) {
|
if (stream.available_bytes() > 1) {
|
||||||
// invalidCallback("LightControlDecrease: Too many bytes left");
|
invalidCallback("LightControlDecrease: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
} else if (!stream.available<uint8_t>()) {
|
} else if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("LightControlDecrease: Stream not available");
|
invalidCallback("LightControlDecrease: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto id = stream.read<uint8_t>();
|
auto id = stream.read<uint8_t>();
|
||||||
message->second.give();
|
|
||||||
Serial.println("Decrease");
|
lightControlDecreaseCallback(id.value());
|
||||||
lightActionQueue.push({LightController::LightActionType::DECREASE, id});
|
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message::parser::StateVisitor::operator()(state::Command) -> State {
|
auto message::parser::StateVisitor::operator()(state::Command) -> State {
|
||||||
if (!stream.available<uint8_t>()) {
|
if (!stream.available<uint8_t>()) {
|
||||||
// invalidCallback("Command: Stream not available");
|
invalidCallback("Command: Stream not available");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mode = stream.read<uint8_t>();
|
auto mode = stream.read<uint8_t>();
|
||||||
if (!mode.has_value()) {
|
if (!mode.has_value()) {
|
||||||
// invalidCallback("Command: Mode has no value");
|
invalidCallback("Command: Mode has no value");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,62 +363,59 @@ auto message::parser::StateVisitor::operator()(state::Command) -> State {
|
||||||
return state::CommandHelp{};
|
return state::CommandHelp{};
|
||||||
case static_cast<uint8_t>(protocol::Command::Version):
|
case static_cast<uint8_t>(protocol::Command::Version):
|
||||||
return state::CommandVersion{};
|
return state::CommandVersion{};
|
||||||
case static_cast<uint8_t>(protocol::Command::Reset):
|
|
||||||
return state::CommandReset{};
|
|
||||||
default:
|
default:
|
||||||
// invalidCallback("Command: Invalid index");
|
invalidCallback("Command: Invalid index");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::CommandRequestLightData)
|
auto message::parser::StateVisitor::operator()(state::CommandRequestLightData)
|
||||||
-> State {
|
-> State {
|
||||||
return state::Invalid{};
|
commandRequestLightDataCallback();
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(
|
auto message::parser::StateVisitor::operator()(
|
||||||
state::CommandEnterConsoleFlashing) -> State {
|
state::CommandEnterConsoleFlashing) -> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("CommandEnterConsoleFlashing: Too many bytes left");
|
invalidCallback("CommandEnterConsoleFlashing: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
return state::Invalid{};
|
commandEnterConsoleFlashingCallback();
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(
|
auto message::parser::StateVisitor::operator()(
|
||||||
state::CommandExitConsoleFlashing) -> State {
|
state::CommandExitConsoleFlashing) -> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("CommandExitConsoleFlashing: Too many bytes left");
|
invalidCallback("CommandExitConsoleFlashing: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
return state::Invalid{};
|
commandExitConsoleFlashingCallback();
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::CommandPairBluetooth)
|
auto message::parser::StateVisitor::operator()(state::CommandPairBluetooth)
|
||||||
-> State {
|
-> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("CommandPairBluetooth: Too many bytes left");
|
invalidCallback("CommandPairBluetooth: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
return state::Invalid{};
|
commandPairBluetoothCallback();
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::CommandHelp) -> State {
|
auto message::parser::StateVisitor::operator()(state::CommandHelp) -> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("CommandHelp: Too many bytes left");
|
invalidCallback("CommandHelp: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
return state::Invalid{};
|
|
||||||
|
commandHelpCallback();
|
||||||
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::CommandVersion) -> State {
|
auto message::parser::StateVisitor::operator()(state::CommandVersion) -> State {
|
||||||
if (stream.available_bytes() > 0) {
|
if (stream.available_bytes() > 0) {
|
||||||
// invalidCallback("CommandVersion: Too many bytes left");
|
invalidCallback("CommandVersion: Too many bytes left");
|
||||||
return state::Invalid{};
|
return state::Invalid{};
|
||||||
}
|
}
|
||||||
return state::Invalid{};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto message::parser::StateVisitor::operator()(state::CommandReset) -> State {
|
commandVersionCallback();
|
||||||
if (stream.available_bytes() > 0) {
|
|
||||||
// invalidCallback("CommandVersion: Too many bytes left");
|
|
||||||
return state::Invalid{};
|
|
||||||
}
|
|
||||||
ESP.restart();
|
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,35 +423,55 @@ auto message::parser::StateVisitor::operator()(state::Complete) -> State {
|
||||||
return state::Complete{};
|
return state::Complete{};
|
||||||
}
|
}
|
||||||
auto message::parser::StateVisitor::operator()(state::Invalid) -> State {
|
auto message::parser::StateVisitor::operator()(state::Invalid) -> State {
|
||||||
message->second.give();
|
return state::Invalid{};
|
||||||
return state::Complete{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto message::parser::parse(
|
auto message::parser::parse(
|
||||||
message::Message *message,
|
etl::byte_stream_reader &&reader,
|
||||||
freertos::Queue<LightController::LightAction> &lightActionQueue) -> void {
|
etl::function<void, etl::string_view> invalidCallback,
|
||||||
StateVisitor visitor{message, lightActionQueue};
|
etl::function<void, etl::span<const char>> messageLightDataCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageInfoCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageWarningCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageErrorCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageSuccessCallback,
|
||||||
|
etl::function<void, uint32_t> settingsSetBaudCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiPasswordCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiSSIDCallback,
|
||||||
|
etl::function<void, void> lightControlOnCallback,
|
||||||
|
etl::function<void, void> lightControlOffCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlToggleCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlIncreaseCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlDecreaseCallback,
|
||||||
|
etl::function<void, void> commandRequestLightDataCallback,
|
||||||
|
etl::function<void, void> commandEnterConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandExitConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandPairBluetoothCallback,
|
||||||
|
etl::function<void, void> commandHelpCallback,
|
||||||
|
etl::function<void, void> 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{}};
|
State state{state::ModeSelection{}};
|
||||||
while (!etl::holds_alternative<state::Complete>(state)) {
|
while (!etl::holds_alternative<state::Invalid>(state) &&
|
||||||
|
!etl::holds_alternative<state::Complete>(state)) {
|
||||||
state = etl::visit(visitor, state);
|
state = etl::visit(visitor, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message::parser::Parser::Parser(
|
|
||||||
freertos::Queue<LightController::LightAction> &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<Parser *>(parserPtr);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
auto message = parser->messages.pop();
|
|
||||||
Serial.println("starting parse");
|
|
||||||
if (message.has_value()) {
|
|
||||||
parse(message.value(), parser->lightActionQueue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
#include <FreeRTOS/Queue.h>
|
|
||||||
#include <FreeRTOS/Task.h>
|
|
||||||
#include <LightController/Controller.h>
|
|
||||||
#include <Messages/Message.h>
|
|
||||||
#include <etl/byte_stream.h>
|
#include <etl/byte_stream.h>
|
||||||
#include <etl/function.h>
|
#include <etl/function.h>
|
||||||
#include <etl/span.h>
|
#include <etl/span.h>
|
||||||
|
@ -38,7 +34,6 @@ struct CommandExitConsoleFlashing {};
|
||||||
struct CommandPairBluetooth {};
|
struct CommandPairBluetooth {};
|
||||||
struct CommandHelp {};
|
struct CommandHelp {};
|
||||||
struct CommandVersion {};
|
struct CommandVersion {};
|
||||||
struct CommandReset {};
|
|
||||||
struct Complete {};
|
struct Complete {};
|
||||||
} // namespace state
|
} // namespace state
|
||||||
|
|
||||||
|
@ -52,16 +47,55 @@ using State = etl::variant<
|
||||||
state::LightControlIncrease, state::LightControlDecrease, state::Command,
|
state::LightControlIncrease, state::LightControlDecrease, state::Command,
|
||||||
state::CommandRequestLightData, state::CommandEnterConsoleFlashing,
|
state::CommandRequestLightData, state::CommandEnterConsoleFlashing,
|
||||||
state::CommandExitConsoleFlashing, state::CommandPairBluetooth,
|
state::CommandExitConsoleFlashing, state::CommandPairBluetooth,
|
||||||
state::CommandHelp, state::CommandVersion, state::CommandReset,
|
state::CommandHelp, state::CommandVersion, state::Complete>;
|
||||||
state::Complete>;
|
|
||||||
|
|
||||||
void parse(message::Message *message,
|
void parse(
|
||||||
freertos::Queue<LightController::LightAction> &lightActionQueue);
|
etl::byte_stream_reader &&reader,
|
||||||
|
etl::function<void, etl::string_view> invalidCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageLightDataCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageInfoCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageWarningCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageErrorCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageSuccessCallback,
|
||||||
|
etl::function<void, uint32_t> settingsSetBaudCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiPasswordCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiSSIDCallback,
|
||||||
|
etl::function<void, void> lightControlOnCallback,
|
||||||
|
etl::function<void, void> lightControlOffCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlToggleCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlIncreaseCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlDecreaseCallback,
|
||||||
|
etl::function<void, void> commandRequestLightDataCallback,
|
||||||
|
etl::function<void, void> commandEnterConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandExitConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandPairBluetoothCallback,
|
||||||
|
etl::function<void, void> commandHelpCallback,
|
||||||
|
etl::function<void, void> commandVersionCallback);
|
||||||
|
|
||||||
class StateVisitor {
|
class StateVisitor {
|
||||||
public:
|
public:
|
||||||
StateVisitor(message::Message *message,
|
StateVisitor(
|
||||||
freertos::Queue<LightController::LightAction> &lightActionQueue);
|
etl::byte_stream_reader &&sreader,
|
||||||
|
etl::function<void, etl::string_view> invalidCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageLightDataCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageInfoCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageWarningCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageErrorCallback,
|
||||||
|
etl::function<void, etl::span<const char>> messageSuccessCallback,
|
||||||
|
etl::function<void, uint32_t> settingsSetBaudCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiPasswordCallback,
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiSSIDCallback,
|
||||||
|
etl::function<void, void> lightControlOnCallback,
|
||||||
|
etl::function<void, void> lightControlOffCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlToggleCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlIncreaseCallback,
|
||||||
|
etl::function<void, uint8_t> lightControlDecreaseCallback,
|
||||||
|
etl::function<void, void> commandRequestLightDataCallback,
|
||||||
|
etl::function<void, void> commandEnterConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandExitConsoleFlashingCallback,
|
||||||
|
etl::function<void, void> commandPairBluetoothCallback,
|
||||||
|
etl::function<void, void> commandHelpCallback,
|
||||||
|
etl::function<void, void> commandVersionCallback);
|
||||||
State operator()(state::ModeSelection);
|
State operator()(state::ModeSelection);
|
||||||
State operator()(state::Message);
|
State operator()(state::Message);
|
||||||
State operator()(state::MessageLightData);
|
State operator()(state::MessageLightData);
|
||||||
|
@ -88,29 +122,33 @@ public:
|
||||||
State operator()(state::CommandPairBluetooth);
|
State operator()(state::CommandPairBluetooth);
|
||||||
State operator()(state::CommandHelp);
|
State operator()(state::CommandHelp);
|
||||||
State operator()(state::CommandVersion);
|
State operator()(state::CommandVersion);
|
||||||
State operator()(state::CommandReset);
|
|
||||||
|
|
||||||
State operator()(state::Complete);
|
State operator()(state::Complete);
|
||||||
State operator()(state::Invalid);
|
State operator()(state::Invalid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
etl::byte_stream_reader stream;
|
etl::byte_stream_reader stream;
|
||||||
message::Message *message;
|
// TODO: callback function parameter types
|
||||||
freertos::Queue<LightController::LightAction> &lightActionQueue;
|
etl::function<void, etl::string_view> invalidCallback;
|
||||||
};
|
etl::function<void, etl::span<const char>> messageLightDataCallback;
|
||||||
|
etl::function<void, etl::span<const char>> messageInfoCallback;
|
||||||
class Parser {
|
etl::function<void, etl::span<const char>> messageWarningCallback;
|
||||||
public:
|
etl::function<void, etl::span<const char>> messageErrorCallback;
|
||||||
Parser(freertos::Queue<LightController::LightAction> &lightActionQueue,
|
etl::function<void, etl::span<const char>> messageSuccessCallback;
|
||||||
UBaseType_t queueCapacity, UBaseType_t priority, BaseType_t coreID);
|
etl::function<void, uint32_t> settingsSetBaudCallback;
|
||||||
freertos::Queue<message::Message *> &getMessageQueue() { return messages; }
|
etl::function<void, etl::span<const char>> settingsWifiPasswordCallback;
|
||||||
|
etl::function<void, etl::span<const char>> settingsWifiSSIDCallback;
|
||||||
private:
|
etl::function<void, void> lightControlOnCallback;
|
||||||
static void exec(void *parserPtr);
|
etl::function<void, void> lightControlOffCallback;
|
||||||
freertos::Task parserTask;
|
etl::function<void, uint8_t> lightControlToggleCallback;
|
||||||
static const uint32_t stackDepth = 2048;
|
etl::function<void, uint8_t> lightControlIncreaseCallback;
|
||||||
freertos::Queue<message::Message *> messages;
|
etl::function<void, uint8_t> lightControlDecreaseCallback;
|
||||||
freertos::Queue<LightController::LightAction> &lightActionQueue;
|
etl::function<void, void> commandRequestLightDataCallback;
|
||||||
|
etl::function<void, void> commandEnterConsoleFlashingCallback;
|
||||||
|
etl::function<void, void> commandExitConsoleFlashingCallback;
|
||||||
|
etl::function<void, void> commandPairBluetoothCallback;
|
||||||
|
etl::function<void, void> commandHelpCallback;
|
||||||
|
etl::function<void, void> commandVersionCallback;
|
||||||
};
|
};
|
||||||
} // namespace parser
|
} // namespace parser
|
||||||
} // namespace message
|
} // namespace message
|
||||||
|
|
|
@ -47,7 +47,6 @@ enum class Command : uint8_t {
|
||||||
PairBluetooth = 0x3,
|
PairBluetooth = 0x3,
|
||||||
Help = 0x4,
|
Help = 0x4,
|
||||||
Version = 0x5,
|
Version = 0x5,
|
||||||
Reset = 0x6,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using Submode = etl::variant<Mode, Message, Settings, LightControl, Command>;
|
using Submode = etl::variant<Mode, Message, Settings, LightControl, Command>;
|
||||||
|
|
Loading…
Reference in a new issue