Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/SlvCtrlArduinoSerialCommandsTransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
};
Expand Down
145 changes: 76 additions & 69 deletions src/SlvCtrlProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) ----
Expand Down Expand Up @@ -107,7 +107,7 @@ class BaseAttribute : public IAttribute {
}

void writeValue(ISlvCtrlOut& out) const override {
out.print(this->getValue());
out.send(this->getValue());
}

private:
Expand All @@ -132,8 +132,8 @@ class IntAttribute : public BaseAttribute<int32_t> {
}

void describe(ISlvCtrlOut& out) const override {
out.print(slvCtrlAccessToString(access()));
out.print("[int]");
out.send(slvCtrlAccessToString(access()));
out.send("[int]");
}
};

Expand All @@ -151,8 +151,8 @@ class FloatAttribute : public BaseAttribute<float> {
}

void describe(ISlvCtrlOut& out) const override {
out.print(slvCtrlAccessToString(access()));
out.print("[float]");
out.send(slvCtrlAccessToString(access()));
out.send("[float]");
}
};

Expand All @@ -169,12 +169,12 @@ class BoolAttribute : public BaseAttribute<bool> {
}

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");
}
};

Expand Down Expand Up @@ -216,21 +216,21 @@ class RangeAttribute : public BaseAttribute<T> {
}

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<T, int32_t>) {
out.print("int(");
out.send("int(");
}
else if constexpr (std::is_same_v<T, float>) {
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:
Expand All @@ -249,13 +249,13 @@ class StrAttribute : public BaseAttribute<const char*> {
}

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 : "");
}
};

Expand All @@ -271,6 +271,7 @@ class StrAttribute : public BaseAttribute<const char*> {
class SlvCtrlProtocol {
public:
static constexpr uint32_t protocolVersion = 10000;
static constexpr const char ETX = '\n';

template <size_t N>
SlvCtrlProtocol(const char* deviceType, uint32_t fwVersion, IAttribute* (&attrs)[N])
Expand All @@ -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) {
Expand All @@ -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:
Expand Down