Skip to content

Commit

Permalink
JSON encapsulation in [MSG:JSON:...] on serial channels
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchBradley committed Jan 8, 2024
1 parent f680794 commit d01ac93
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 64 deletions.
49 changes: 34 additions & 15 deletions FluidNC/src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "RealtimeCmd.h" // execute_realtime_command
#include "Limits.h"
#include "Logging.h"
#include <string_view>

void Channel::flushRx() {
_linelen = 0;
Expand Down Expand Up @@ -203,29 +204,22 @@ Channel* Channel::pollLine(char* line) {
return nullptr;
}

void Channel::setAttr(int index, bool* value, const std::string& attrString) {
void Channel::setAttr(int index, bool* value, const std::string& attrString, const char* tag) {
if (value) {
_pin_values[index] = value;
}
int count = 0;
while (_ackwait && ++count < timeout) {
pollLine(NULL);
delay_ms(1);
}
if (count == timeout) {
log_error("Device not responding");
}
log_msg_to(*this, attrString);
_ackwait = true;
log_debug(attrString);
out_acked(attrString, tag);
}

void Channel::out(const std::string& s) {
log_msg_to(*this, s);
// _channel->_ackwait = true;
void Channel::out(const std::string& s, const char* tag) {
log_to(*this, s);
log_debug(s);
}

void Channel::out_acked(const std::string& s, const char* tag) {
out(s, tag);
}

void Channel::ready() {
#if 0
// At the moment this is unnecessary because initializing
Expand Down Expand Up @@ -261,3 +255,28 @@ void Channel::print_msg(MsgLevel level, const char* msg) {
println(msg);
}
}

bool Channel::is_visible(const std::string& stem, const std::string& extension) {
if (stem.length() && stem[0] == '.') {
// Exclude hidden files and directories
return false;
}
if (stem == "System Volume Information") {
// Exclude a common SD card metadata subdirectory
return false;
}
std::string_view extensions(_gcode_extensions);
int pos = 0;
while (extensions.length()) {
auto next_pos = extensions.find_first_of('|', pos);
std::string_view next_extension = extensions.substr(0, next_pos);
if (extension == next_extension) {
return true;
}
if (next_pos == extensions.npos) {
break;
}
extensions.remove_prefix(next_pos + 1);
}
return false;
}
12 changes: 9 additions & 3 deletions FluidNC/src/Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ class Channel : public Stream {
std::map<int, EventPin*> _events;
std::map<int, bool*> _pin_values;

UTF8 _utf8;
UTF8 _utf8;
std::string _gcode_extensions = ".g|.gc|.gco|.gcode|.nc|.ngc|.ncc|.txt|.cnc|.tap";

public:
Channel(const char* name, bool addCR = false) : _name(name), _linelen(0), _addCR(addCR) {}
Expand Down Expand Up @@ -124,6 +125,8 @@ class Channel : public Stream {

virtual void stopJob() {}

virtual bool is_visible(const std::string& stem, const std::string& extension);

size_t timedReadBytes(uint8_t* buffer, size_t length, TickType_t timeout) { return timedReadBytes((char*)buffer, length, timeout); }

bool setCr(bool on) {
Expand All @@ -147,8 +150,11 @@ class Channel : public Stream {
void autoReportGCodeState();

// Pin extender functions
void out(const std::string& s);
void setAttr(int index, bool* valuep, const std::string& s);
virtual void out(const std::string& s, const char* tag);
virtual void out_acked(const std::string& s, const char* tag);

void setAttr(int index, bool* valuep, const std::string& s, const char* tag);

void ready();
void registerEvent(uint8_t code, EventPin* obj);
};
7 changes: 3 additions & 4 deletions FluidNC/src/Logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
#include "Serial.h"
#include "SettingsDefinitions.h"

EnumItem messageLevels2[] = {
{ MsgLevelNone, "None" }, { MsgLevelError, "Error" }, { MsgLevelWarning, "Warn" },
{ MsgLevelInfo, "Info" }, { MsgLevelDebug, "Debug" }, { MsgLevelVerbose, "Verbose" },
};
EnumItem messageLevels2[] = { { MsgLevelNone, "None" }, { MsgLevelError, "Error" }, { MsgLevelWarning, "Warn" },
{ MsgLevelInfo, "Info" }, { MsgLevelDebug, "Debug" }, { MsgLevelVerbose, "Verbose" },
EnumItem(MsgLevelNone) };

bool atMsgLevel(MsgLevel level) {
return message_level == nullptr || message_level->get() >= level;
Expand Down
8 changes: 4 additions & 4 deletions FluidNC/src/Pins/ChannelPinDetail.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ namespace Pins {
return;
}
_value = high;
std::string s = "SET: io.";
std::string s = "io.";
s += std::to_string(_index);
s += "=";
s += std::to_string(high);
_channel->out(s);
_channel->out(s, "SET:");
}
int ChannelPinDetail::read() { return _value; }
void ChannelPinDetail::setAttr(PinAttributes attr) {
_attributes = _attributes | attr;

std::string s = "INI: io.";
std::string s = "io.";
s += std::to_string(_index);
s += "=";
if (_attributes.has(Pins::PinAttributes::Input)) {
Expand All @@ -59,7 +59,7 @@ namespace Pins {
s += ":low";
}

_channel->setAttr(_index, _attributes.has(Pins::PinAttributes::Input) ? &this->_value : nullptr, s);
_channel->setAttr(_index, _attributes.has(Pins::PinAttributes::Input) ? &this->_value : nullptr, s, "INI:");
}
PinAttributes ChannelPinDetail::getAttr() const { return _attributes; }
std::string ChannelPinDetail::toString() {
Expand Down
19 changes: 19 additions & 0 deletions FluidNC/src/UartChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ size_t UartChannel::timedReadBytes(char* buffer, size_t length, TickType_t timeo
return length - remlen;
}

void UartChannel::out(const std::string& s, const char* tag) {
std::string t(tag);
log_msg_to(*this, t + s);
log_debug(s);
}

void UartChannel::out_acked(const std::string& s, const char* tag) {
int count = 0;
while (_ackwait && ++count < _ack_timeout) {
pollLine(NULL);
delay_ms(1);
}
if (count == _ack_timeout) {
log_error("Device not responding");
}
out(s, tag);
_ackwait = true;
}

UartChannel Uart0(0, true); // Primary serial channel with LF to CRLF conversion

void uartInit() {
Expand Down
5 changes: 5 additions & 0 deletions FluidNC/src/UartChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class UartChannel : public Channel, public Configuration::Configurable {
int _uart_num = 0;
int _report_interval_ms = 0;

const int _ack_timeout = 2000;

public:
UartChannel(int num, bool addCR = false);

Expand All @@ -39,6 +41,9 @@ class UartChannel : public Channel, public Configuration::Configurable {
bool lineComplete(char* line, char c) override;
Channel* pollLine(char* line) override;

void out(const std::string& s, const char* tag) override;
void out_acked(const std::string& s, const char* tag) override;

// Configuration methods
void group(Configuration::HandlerBase& handler) override {
handler.item("report_interval_ms", _report_interval_ms);
Expand Down
29 changes: 20 additions & 9 deletions FluidNC/src/WebUI/JSONEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,20 @@ namespace WebUI {

JSONencoder::JSONencoder(bool pretty, std::string* str) : pretty(pretty), level(0), _str(str), category("nvs") { count[level] = 0; }

void JSONencoder::add(char c) { (*_str) += c; }
void JSONencoder::flush() {
if (_channel && (*_str).length()) {
// Output to channels is encapsulated in [MSG:JSON:...]
(*_channel).out_acked(*_str, "JSON:");
// *_str = "";
(*_str).clear();
}
}
void JSONencoder::add(char c) {
(*_str) += c;
if (_channel && (*_str).length() >= 100) {
flush();
}
}

// Private function to add commas between
// elements as needed, omitting the comma
Expand Down Expand Up @@ -100,16 +113,13 @@ namespace WebUI {
}
}

void JSONencoder::string(const char* s) {
comma_line();
quoted(s);
}
// Private function to implement pretty-printing
void JSONencoder::line() {
if (_channel) {
// log_to() always adds a newline
// We want that for channels because they might not
// be able to handle really long lines.
log_to(*_channel, *_str);
*_str = "";
indent();
} else {
if (!_channel) {
if (pretty) {
add('\n');
indent();
Expand All @@ -125,6 +135,7 @@ namespace WebUI {
void JSONencoder::end() {
end_object();
line();
flush();
}

// Starts a member element.
Expand Down
7 changes: 6 additions & 1 deletion FluidNC/src/WebUI/JSONEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ namespace WebUI {
void add(char c);
void comma_line();
void comma();
void quoted(const char* s);
void inc_level();
void dec_level();
void indent();
void line();

void quoted(const char* s);

// begin_member() starts the creation of a member.
void begin_member(const char* tag);

Expand All @@ -32,6 +33,8 @@ namespace WebUI {

std::string category;

void flush();

public:
// Constructor; set _pretty true for pretty printing
JSONencoder(bool pretty, Channel* channel);
Expand All @@ -44,6 +47,8 @@ namespace WebUI {

void end();

void string(const char* s);

// member() creates a "tag":"value" element
void member(const char* tag, const char* value);
void member(const char* tag, const std::string& value);
Expand Down
4 changes: 4 additions & 0 deletions FluidNC/src/WebUI/WebClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ namespace WebUI {
}
}

void WebClient::out(const std::string& s, const char* tag) { write((uint8_t*)s.c_str(), s.size()); }

void WebClient::out_acked(const std::string& s, const char* tag) { out(s, tag); }

WebClient::~WebClient() {
flush();
_webserver->sendContent(""); //close connection
Expand Down
3 changes: 3 additions & 0 deletions FluidNC/src/WebUI/WebClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ namespace WebUI {

bool anyOutput() { return _header_sent; }

void out(const std::string& s, const char* tag) override;
void out_acked(const std::string& s, const char* tag) override;

private:
bool _header_sent = false;
bool _silent = false;
Expand Down
Loading

0 comments on commit d01ac93

Please sign in to comment.