diff --git a/src/SlvCtrlArduinoSerialCommandsTransport.h b/src/SlvCtrlArduinoSerialCommandsTransport.h index 807bfc4..e88b5c5 100644 --- a/src/SlvCtrlArduinoSerialCommandsTransport.h +++ b/src/SlvCtrlArduinoSerialCommandsTransport.h @@ -10,32 +10,32 @@ class SlvCtrlArduinoOut final : public ISlvCtrlOut { public: explicit SlvCtrlArduinoOut(Stream& s) : s_(s) {} - void print(const char* s) override { + void send(const char* s) override { s_.print(s ? s : ""); } - void print(int32_t v) override { + void send(char v) override { + s_.print(v); + } + + void send(int32_t v) override { // Arduino Print uses long for signed integers s_.print((long)v); } - void print(uint32_t v) override { + void send(uint32_t v) override { // Arduino Print uses unsigned long for unsigned integers s_.print((unsigned long)v); } - void print(float v, uint8_t decimals = 3) override { + void send(float v, uint8_t decimals = 3) override { s_.print(v, decimals); } - void print(bool v) override { + void send(bool v) override { s_.print(v); } - void println(const char* s = "") override { - s_.println(s ? s : ""); - } - private: Stream& s_; }; diff --git a/src/SlvCtrlProtocol.h b/src/SlvCtrlProtocol.h index 80a5d2c..b68db36 100644 --- a/src/SlvCtrlProtocol.h +++ b/src/SlvCtrlProtocol.h @@ -51,12 +51,12 @@ struct ISlvCtrlTransport { // ---- Output abstraction (no Stream) ---- struct ISlvCtrlOut { virtual ~ISlvCtrlOut() = default; - virtual void print(const char* s) = 0; - virtual void print(uint32_t v) = 0; - virtual void print(int32_t v) = 0; - virtual void print(float v, uint8_t decimals = 3) = 0; - virtual void print(bool v) = 0; - virtual void println(const char* s = "") = 0; + virtual void send(const char* s) = 0; + virtual void send(char c) = 0; + virtual void send(uint32_t v) = 0; + virtual void send(int32_t v) = 0; + virtual void send(float v, uint8_t decimals = 3) = 0; + virtual void send(bool v) = 0; }; // ---- Command context abstraction (no SerialCommands) ---- @@ -107,7 +107,7 @@ class BaseAttribute : public IAttribute { } void writeValue(ISlvCtrlOut& out) const override { - out.print(this->getValue()); + out.send(this->getValue()); } private: @@ -132,8 +132,8 @@ class IntAttribute : public BaseAttribute { } void describe(ISlvCtrlOut& out) const override { - out.print(slvCtrlAccessToString(access())); - out.print("[int]"); + out.send(slvCtrlAccessToString(access())); + out.send("[int]"); } }; @@ -151,8 +151,8 @@ class FloatAttribute : public BaseAttribute { } void describe(ISlvCtrlOut& out) const override { - out.print(slvCtrlAccessToString(access())); - out.print("[float]"); + out.send(slvCtrlAccessToString(access())); + out.send("[float]"); } }; @@ -169,12 +169,12 @@ class BoolAttribute : public BaseAttribute { } void describe(ISlvCtrlOut& out) const override { - out.print(slvCtrlAccessToString(access())); - out.print("[bool]"); + out.send(slvCtrlAccessToString(access())); + out.send("[bool]"); } void writeValue(ISlvCtrlOut& out) const override { - out.print(this->getValue() ? "true" : "false"); + out.send(this->getValue() ? "true" : "false"); } }; @@ -216,21 +216,21 @@ class RangeAttribute : public BaseAttribute { } void describe(ISlvCtrlOut& out) const override { - out.print(slvCtrlAccessToString(this->access())); - out.print("["); + out.send(slvCtrlAccessToString(this->access())); + out.send("["); if constexpr (std::is_same_v) { - out.print("int("); + out.send("int("); } else if constexpr (std::is_same_v) { - out.print("float("); + out.send("float("); } else { - out.print("?("); + out.send("?("); } - out.print(min_); - out.print(".."); - out.print(max_); - out.print(")]"); + out.send(min_); + out.send(".."); + out.send(max_); + out.send(")]"); } private: @@ -249,13 +249,13 @@ class StrAttribute : public BaseAttribute { } void describe(ISlvCtrlOut& out) const override { - out.print(slvCtrlAccessToString(access())); - out.print("[str]"); + out.send(slvCtrlAccessToString(access())); + out.send("[str]"); } void writeValue(ISlvCtrlOut& out) const override { const char* s = this->getValue(); - out.print(s ? s : ""); + out.send(s ? s : ""); } }; @@ -271,6 +271,7 @@ class StrAttribute : public BaseAttribute { class SlvCtrlProtocol { public: static constexpr uint32_t protocolVersion = 10000; + static constexpr const char ETX = '\n'; template SlvCtrlProtocol(const char* deviceType, uint32_t fwVersion, IAttribute* (&attrs)[N]) @@ -281,69 +282,71 @@ class SlvCtrlProtocol { void cmdIntroduce(ISlvCtrlCmdCtx& ctx) { auto& o = ctx.out(); - o.print("introduce;type:"); - o.print(deviceType_); - o.print(",fw:"); - o.print(fwVersion_); - o.print(",protocol:"); - o.print(protocolVersion); - o.println(";status:ok"); + o.send("introduce;type:"); + o.send(deviceType_); + o.send(",fw:"); + o.send(fwVersion_); + o.send(",protocol:"); + o.send(protocolVersion); + o.send(";status:ok"); + o.send(ETX); } void cmdAttributes(ISlvCtrlCmdCtx& ctx) { auto& o = ctx.out(); - o.print("attributes;"); + o.send("attributes;"); bool first = true; for (size_t i = 0; i < attrCount_; ++i) { IAttribute* a = attrs_[i]; if (!a) continue; - if (!first) o.print(","); + if (!first) o.send(","); first = false; - o.print(a->name()); - o.print(":"); + o.send(a->name()); + o.send(":"); a->describe(o); } - o.print(";status:ok"); - o.println(); + o.send(";status:ok"); + o.send(ETX); } void cmdStatus(ISlvCtrlCmdCtx& ctx) { auto& o = ctx.out(); - o.print("status;"); + o.send("status;"); bool first = true; for (size_t i = 0; i < attrCount_; ++i) { IAttribute* a = attrs_[i]; if (!a || !canRead(a->access())) continue; - if (!first) o.print(","); + if (!first) o.send(","); first = false; - o.print(a->name()); - o.print(":"); + o.send(a->name()); + o.send(":"); a->writeValue(o); } - o.print(";status:ok"); - o.println(); + o.send(";status:ok"); + o.send(ETX); } void cmdGet(ISlvCtrlCmdCtx& ctx) { auto& o = ctx.out(); const char* name = ctx.next(); - if (!name) { o.println("get;;status:error,reason:missing_attribute_name_arg"); return; } + if (!name) { o.send("get;;status:error,reason:missing_attribute_name_arg"); o.send(ETX); return; } IAttribute* a = findAttr(name); - if (!a) { o.print("get "); o.print(name); o.println(";;status:error,reason:unknown_attribute"); return; } - if (!canRead(a->access())) { o.print("get "); o.print(name); o.println(";;status:error,reason:write_only_attribute"); return; } + if (!a) { o.send("get "); o.send(name); o.send(";;status:error,reason:unknown_attribute"); o.send(ETX); return; } + if (!canRead(a->access())) { o.send("get "); o.send(name); o.send(";;status:error,reason:write_only_attribute"); o.send(ETX); return; } - o.print("get "); - o.print(a->name()); - o.print(";value:"); + o.send("get "); + o.send(a->name()); + o.send(";value:"); a->writeValue(o); - o.println(";status:ok"); + o.send(";status:ok"); + o.send(ETX); } void cmdSet(ISlvCtrlCmdCtx& ctx) { @@ -352,42 +355,46 @@ class SlvCtrlProtocol { const char* value = ctx.next(); if (!name) { - o.println("set;;status:error,reason:attribute_name_missing"); + o.send("set;;status:error,reason:attribute_name_missing"); + o.send(ETX); return; } if (!value) { - o.print("set "); - o.print(name); - o.println(";;status:error,reason:attribute_value_missing"); + o.send("set "); + o.send(name); + o.send(";;status:error,reason:attribute_value_missing"); + o.send(ETX); return; } IAttribute* a = findAttr(name); - if (!a) { o.print("set "); o.print(name); o.println(";;status:error,reason:unknown_attribute"); return; } - if (!canWrite(a->access())) { o.print("set "); o.print(name); o.println(";;status:error,reason:read_only_attribute"); return; } + if (!a) { o.send("set "); o.send(name); o.send(";;status:error,reason:unknown_attribute"); o.send(ETX); return; } + if (!canWrite(a->access())) { o.send("set "); o.send(name); o.send(";;status:error,reason:read_only_attribute"); o.send(ETX); return; } SlvCtrlParseError err = a->setFromCString(value); - o.print("set "); - o.print(name); - o.print(" "); - o.print(value); - o.print(";;"); + o.send("set "); + o.send(name); + o.send(" "); + o.send(value); + o.send(";;"); if (err == SlvCtrlParseError::Ok) { - o.println("status:ok"); + o.send("status:ok"); } else { - o.print("status:error,reason:"); - o.println(slvCtrlParseErrorToString(err)); + o.send("status:error,reason:"); + o.send(slvCtrlParseErrorToString(err)); } + + o.send(ETX); } void cmdUnrecognized(ISlvCtrlCmdCtx& ctx, const char* cmd) { auto& o = ctx.out(); - o.print(cmd ? cmd : ""); - o.print(";;status:error,reason:unknown_command"); - o.println(); + o.send(cmd ? cmd : ""); + o.send(";;status:error,reason:unknown_command"); + o.send(ETX); } private: