From cc8c13b240f98bba7653447e62087d2c662a2155 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 16:08:09 +0100 Subject: [PATCH] Update xdrv_08_serial_bridge.ino SerialBridge revisited --- sonoff/xdrv_08_serial_bridge.ino | 69 ++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 74915935c..ba83f11ec 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -31,12 +31,13 @@ enum SerialBridgeCommands { CMND_SSERIALSEND, CMND_SBAUDRATE }; const char kSerialBridgeCommands[] PROGMEM = D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE; -TasmotaSerial *SerialBridgeSerial; +TasmotaSerial *SerialBridgeSerial = NULL; -uint8_t serial_bridge_active = 1; -uint8_t serial_bridge_in_byte_counter = 0; unsigned long serial_bridge_polling_window = 0; char *serial_bridge_buffer = NULL; +int serial_bridge_in_byte_counter = 0; +bool serial_bridge_active = true; +bool serial_bridge_raw = false; void SerialBridgeInput(void) { @@ -44,25 +45,37 @@ void SerialBridgeInput(void) yield(); uint8_t serial_in_byte = SerialBridgeSerial->read(); - if (serial_in_byte > 127) { // binary data... + if ((serial_in_byte > 127) && !serial_bridge_raw) { // Discard binary data above 127 if no raw reception allowed serial_bridge_in_byte_counter = 0; SerialBridgeSerial->flush(); return; } - if (serial_in_byte) { - if ((serial_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits + if (serial_in_byte || serial_bridge_raw) { // Any char between 1 and 127 or any char (0 - 255) + + if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && // Add char to string if it still fits and ... + ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || // Any char between 32 and 127 + (serial_in_byte != Settings.serial_delimiter) || // Any char between 1 and 127 and not being delimiter + serial_bridge_raw)) { // Any char between 0 and 255 serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; - serial_bridge_polling_window = millis(); // Wait for more data + serial_bridge_polling_window = millis(); // Wait for more data } else { - serial_bridge_polling_window = 0; // Publish now + serial_bridge_polling_window = 0; // Publish now break; } } } if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { - serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // serial data completed - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); + serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed + if (!serial_bridge_raw) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"")); + for (int i = 0; i < serial_bridge_in_byte_counter; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_bridge_buffer[i]); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); // XdrvRulesProcess(); serial_bridge_in_byte_counter = 0; @@ -73,15 +86,18 @@ void SerialBridgeInput(void) void SerialBridgeInit(void) { - serial_bridge_active = 0; + serial_bridge_active = false; if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) { - serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); - if (serial_bridge_buffer != NULL) { - SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); - if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte - serial_bridge_active = 1; - SerialBridgeSerial->flush(); + SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); + if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte + if (SerialBridgeSerial->hardwareSerial()) { + ClaimSerial(); + serial_bridge_buffer = serial_in_buffer; // Use idle serial buffer to save RAM + } else { + serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); } + serial_bridge_active = true; + SerialBridgeSerial->flush(); } } } @@ -100,18 +116,19 @@ bool SerialBridgeCommand(void) serviced = false; // Unknown command } else if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - if (XdrvMailbox.data_len > 0) { // "Hello Tiger\n" + serial_bridge_raw = (XdrvMailbox.index > 3); + if (XdrvMailbox.data_len > 0) { if (1 == XdrvMailbox.index) { - SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); - SerialBridgeSerial->write("\n"); + SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); // "Hello Tiger" + SerialBridgeSerial->write("\n"); // "\n" } - else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { // "Hello Tiger" or "A0" - SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); + else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { + SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); // "Hello Tiger" or "A0" } - else if (3 == XdrvMailbox.index) { // "Hello\f" + else if (3 == XdrvMailbox.index) { // "Hello\f" SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len); } - else if (5 == XdrvMailbox.index) { // "AA004566" as hex values + else if (5 == XdrvMailbox.index) { char *p; char stemp[3]; uint8_t code; @@ -122,7 +139,7 @@ bool SerialBridgeCommand(void) while (size > 0) { snprintf(stemp, sizeof(stemp), codes); code = strtol(stemp, &p, 16); - SerialBridgeSerial->write(code); + SerialBridgeSerial->write(code); // "AA004566" as hex values size -= 2; codes += 2; } @@ -159,7 +176,7 @@ bool Xdrv08(uint8_t function) SerialBridgeInit(); break; case FUNC_LOOP: - SerialBridgeInput(); + if (SerialBridgeSerial) { SerialBridgeInput(); } break; case FUNC_COMMAND: result = SerialBridgeCommand();