mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
new Nextion
This commit is contained in:
657
src/modules/display/Nextion/ESPNexUpload.cpp
Normal file
657
src/modules/display/Nextion/ESPNexUpload.cpp
Normal file
@@ -0,0 +1,657 @@
|
||||
/**
|
||||
* @file NexUpload.cpp
|
||||
*
|
||||
* The implementation of uploading tft file for nextion displays.
|
||||
*
|
||||
* Original version (a part of https://github.com/itead/ITEADLIB_Arduino_Nextion)
|
||||
* @author Chen Zengpeng (email:<zengpeng.chen@itead.cc>)
|
||||
* @date 2016/3/29
|
||||
* @copyright
|
||||
* Copyright (C) 2014-2015 ITEAD Intelligent Systems Co., Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define DEBUG_SERIAL_ENABLE
|
||||
#include "ESPNexUpload.h"
|
||||
|
||||
#ifdef DEBUG_SERIAL_ENABLE
|
||||
#define dbSerialPrint(a) Serial.print(a)
|
||||
#define dbSerialPrintHex(a) Serial.print(a, HEX)
|
||||
#define dbSerialPrintln(a) Serial.println(a)
|
||||
#define dbSerialBegin(a) Serial.begin(a)
|
||||
#else
|
||||
#define dbSerialPrint(a) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define dbSerialPrintHex(a) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define dbSerialPrintln(a) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define dbSerialBegin(a) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
ESPNexUpload::ESPNexUpload(uint32_t upload_baudrate, int line, int rx, int tx)
|
||||
{
|
||||
_upload_baudrate = upload_baudrate;
|
||||
_rx = rx;
|
||||
_tx = tx;
|
||||
_line = line;
|
||||
|
||||
#if defined ESP8266
|
||||
nexSerial = new SoftwareSerial(_rx, _tx);
|
||||
#else
|
||||
if (line >= 0) {
|
||||
nexSerial = new HardwareSerial(line);
|
||||
// ((HardwareSerial*)nexSerial)->begin(_upload_baudrate, SERIAL_8N1, _rx, _tx);
|
||||
} else {
|
||||
nexSerial = new SoftwareSerial(_rx, _tx);
|
||||
// ((SoftwareSerial*)nexSerial)->begin(_upload_baudrate);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void ESPNexUpload::nexSerialBegin(uint32_t _speed, int _line, int _rx, int _tx)
|
||||
{
|
||||
#if defined ESP8266
|
||||
nexSerial->begin(_speed);
|
||||
#else
|
||||
if (_line >= 0) {
|
||||
((HardwareSerial*)nexSerial)->begin(_speed, SERIAL_8N1, _rx, _tx);
|
||||
} else {
|
||||
((SoftwareSerial*)nexSerial)->begin(_speed);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ESPNexUpload::connect()
|
||||
{
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
dbSerialBegin(115200);
|
||||
_printInfoLine(F("serial tests & connect"));
|
||||
|
||||
if (_getBaudrate() == 0)
|
||||
{
|
||||
statusMessage = F("get baudrate error");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
_setRunningMode();
|
||||
|
||||
if (!_echoTest("mystop_yesABC"))
|
||||
{
|
||||
statusMessage = F("echo test failed");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_handlingSleepAndDim())
|
||||
{
|
||||
statusMessage = F("handling sleep and dim settings failed");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_setPrepareForFirmwareUpdate(_upload_baudrate))
|
||||
{
|
||||
statusMessage = F("modifybaudrate error");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESPNexUpload::prepareUpload(uint32_t file_size)
|
||||
{
|
||||
_undownloadByte = file_size;
|
||||
return this->connect();
|
||||
}
|
||||
|
||||
uint16_t ESPNexUpload::_getBaudrate(void)
|
||||
{
|
||||
|
||||
_baudrate = 0;
|
||||
uint32_t baudrate_array[7] = {115200, 19200, 9600, 57600, 38400, 4800, 2400};
|
||||
for (uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
if (_searchBaudrate(baudrate_array[i]))
|
||||
{
|
||||
_baudrate = baudrate_array[i];
|
||||
_printInfoLine(F("baudrate determined"));
|
||||
break;
|
||||
}
|
||||
delay(1500); // wait for 1500 ms
|
||||
}
|
||||
return _baudrate;
|
||||
}
|
||||
|
||||
bool ESPNexUpload::_searchBaudrate(uint32_t baudrate)
|
||||
{
|
||||
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
String response = String("");
|
||||
_printInfoLine();
|
||||
dbSerialPrint(F("init nextion serial interface on baudrate: "));
|
||||
dbSerialPrintln(baudrate);
|
||||
|
||||
nexSerialBegin(baudrate, _line, _rx, _tx);
|
||||
_printInfoLine(F("ESP baudrate established, try to connect to display"));
|
||||
const char _nextion_FF_FF[3] = {0xFF, 0xFF, 0x00};
|
||||
|
||||
this->sendCommand("DRAKJHSUYDGBNCJHGJKSHBDN");
|
||||
this->sendCommand("", true, true); // 0x00 0xFF 0xFF 0xFF
|
||||
|
||||
this->recvRetString(response);
|
||||
if (response[0] != 0x1A)
|
||||
{
|
||||
_printInfoLine(F("first indication that baudrate is wrong"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_printInfoLine(F("first respone from display, first indication that baudrate is correct"));
|
||||
}
|
||||
|
||||
this->sendCommand("connect"); // first connect attempt
|
||||
|
||||
this->recvRetString(response);
|
||||
if (response.indexOf(F("comok")) == -1)
|
||||
{
|
||||
_printInfoLine(F("display doesn't accept the first connect request"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_printInfoLine(F("display accept the first connect request"));
|
||||
}
|
||||
|
||||
response = String("");
|
||||
delay(110); // based on serial analyser from Nextion editor V0.58 to Nextion display NX4024T032_011R
|
||||
this->sendCommand(_nextion_FF_FF, false);
|
||||
|
||||
this->sendCommand("connect"); // second attempt
|
||||
this->recvRetString(response);
|
||||
if (response.indexOf(F("comok")) == -1 && response[0] != 0x1A)
|
||||
{
|
||||
_printInfoLine(F("display doesn't accept the second connect request"));
|
||||
_printInfoLine(F("conclusion, wrong baudrate"));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_printInfoLine(F("display accept the second connect request"));
|
||||
_printInfoLine(F("conclusion, correct baudrate"));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ESPNexUpload::sendCommand(const char *cmd, bool tail, bool null_head)
|
||||
{
|
||||
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
if (null_head)
|
||||
{
|
||||
((HardwareSerial*)nexSerial)->write(0x00);
|
||||
}
|
||||
|
||||
while (nexSerial->available())
|
||||
{
|
||||
nexSerial->read();
|
||||
}
|
||||
|
||||
nexSerial->print(cmd);
|
||||
if (tail)
|
||||
{
|
||||
nexSerial->write(0xFF);
|
||||
nexSerial->write(0xFF);
|
||||
nexSerial->write(0xFF);
|
||||
}
|
||||
_printSerialData(true, cmd);
|
||||
}
|
||||
|
||||
uint16_t ESPNexUpload::recvRetString(String &response, uint32_t timeout, bool recv_flag)
|
||||
{
|
||||
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
uint16_t ret = 0;
|
||||
uint8_t c = 0;
|
||||
uint8_t nr_of_FF_bytes = 0;
|
||||
long start;
|
||||
bool exit_flag = false;
|
||||
bool ff_flag = false;
|
||||
if (timeout != 500)
|
||||
_printInfoLine("timeout setting serial read: " + String(timeout));
|
||||
|
||||
start = millis();
|
||||
|
||||
while (millis() - start <= timeout)
|
||||
{
|
||||
|
||||
while (nexSerial->available())
|
||||
{
|
||||
|
||||
c = nexSerial->read();
|
||||
if (c == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == 0xFF)
|
||||
nr_of_FF_bytes++;
|
||||
else
|
||||
{
|
||||
nr_of_FF_bytes = 0;
|
||||
ff_flag = false;
|
||||
}
|
||||
|
||||
if (nr_of_FF_bytes >= 3)
|
||||
ff_flag = true;
|
||||
|
||||
response += (char)c;
|
||||
|
||||
if (recv_flag)
|
||||
{
|
||||
if (response.indexOf(0x05) != -1)
|
||||
{
|
||||
exit_flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exit_flag || ff_flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
_printSerialData(false, response);
|
||||
|
||||
// if the exit flag and the ff flag are both not found, than there is a timeout
|
||||
// if(!exit_flag && !ff_flag)
|
||||
// _printInfoLine(F("recvRetString: timeout"));
|
||||
|
||||
if (ff_flag)
|
||||
response = response.substring(0, response.length() - 3); // Remove last 3 0xFF
|
||||
|
||||
ret = response.length();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ESPNexUpload::_setPrepareForFirmwareUpdate(uint32_t upload_baudrate)
|
||||
{
|
||||
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
String response = String("");
|
||||
String cmd = String("");
|
||||
|
||||
cmd = F("00");
|
||||
this->sendCommand(cmd.c_str());
|
||||
delay(0.1);
|
||||
|
||||
this->recvRetString(response, 800, true); // normal response time is 400ms
|
||||
|
||||
String filesize_str = String(_undownloadByte, 10);
|
||||
String baudrate_str = String(upload_baudrate);
|
||||
cmd = "whmi-wri " + filesize_str + "," + baudrate_str + ",0";
|
||||
|
||||
this->sendCommand(cmd.c_str());
|
||||
|
||||
// Without flush, the whmi command will NOT transmitted by the ESP in the current baudrate
|
||||
// because switching to another baudrate (nexSerialBegin command) has an higher prio.
|
||||
// The ESP will first jump to the new 'upload_baudrate' and than process the serial 'transmit buffer'
|
||||
// The flush command forced the ESP to wait until the 'transmit buffer' is empty
|
||||
nexSerial->flush();
|
||||
|
||||
nexSerialBegin(upload_baudrate, _line, _rx, _tx);
|
||||
_printInfoLine(F("changing upload baudrate..."));
|
||||
_printInfoLine(String(upload_baudrate));
|
||||
|
||||
this->recvRetString(response, 800, true); // normal response time is 400ms
|
||||
|
||||
// The Nextion display will, if it's ready to accept data, send a 0x05 byte.
|
||||
if (response.indexOf(0x05) != -1)
|
||||
{
|
||||
_printInfoLine(F("preparation for firmware update done"));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_printInfoLine(F("preparation for firmware update failed"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ESPNexUpload::setUpdateProgressCallback(THandlerFunction value)
|
||||
{
|
||||
_updateProgressCallback = value;
|
||||
}
|
||||
|
||||
bool ESPNexUpload::upload(const uint8_t *file_buf, size_t buf_size)
|
||||
{
|
||||
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
uint8_t c;
|
||||
uint8_t timeout = 0;
|
||||
String string = String("");
|
||||
|
||||
for (uint16_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
|
||||
// Users must split the .tft file contents into 4096 byte sized packets with the final partial packet size equal to the last remaining bytes (<4096 bytes).
|
||||
if (_sent_packets == 4096)
|
||||
{
|
||||
|
||||
// wait for the Nextion to return its 0x05 byte confirming reception and readiness to receive the next packets
|
||||
this->recvRetString(string, 500, true);
|
||||
if (string.indexOf(0x05) != -1)
|
||||
{
|
||||
|
||||
// reset sent packets counter
|
||||
_sent_packets = 0;
|
||||
|
||||
// reset receive String
|
||||
string = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timeout >= 8)
|
||||
{
|
||||
statusMessage = F("serial connection lost");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
timeout++;
|
||||
}
|
||||
|
||||
// delay current byte
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read buffer
|
||||
c = file_buf[i];
|
||||
|
||||
// write byte to nextion over serial
|
||||
nexSerial->write(c);
|
||||
|
||||
// update sent packets counter
|
||||
_sent_packets++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESPNexUpload::upload(Stream &myFile)
|
||||
{
|
||||
#if defined ESP8266
|
||||
yield();
|
||||
#endif
|
||||
|
||||
// create buffer for read
|
||||
uint8_t buff[2048] = {0};
|
||||
|
||||
// read all data from server
|
||||
while (_undownloadByte > 0 || _undownloadByte == -1)
|
||||
{
|
||||
|
||||
// get available data size
|
||||
size_t size = myFile.available();
|
||||
|
||||
if (size)
|
||||
{
|
||||
// read up to 2048 byte into the buffer
|
||||
int c = myFile.readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
|
||||
|
||||
// Write the buffered bytes to the nextion. If this fails, return false.
|
||||
if (!this->upload(buff, c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_updateProgressCallback)
|
||||
{
|
||||
_updateProgressCallback();
|
||||
}
|
||||
}
|
||||
|
||||
if (_undownloadByte > 0)
|
||||
{
|
||||
_undownloadByte -= c;
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESPNexUpload::softReset(void)
|
||||
{
|
||||
// soft reset nextion device
|
||||
this->sendCommand("rest");
|
||||
}
|
||||
|
||||
void ESPNexUpload::end()
|
||||
{
|
||||
|
||||
// wait for the nextion to finish internal processes
|
||||
delay(1600);
|
||||
|
||||
// soft reset the nextion
|
||||
this->softReset();
|
||||
|
||||
// end Serial connection
|
||||
((HardwareSerial*)nexSerial)->end();
|
||||
|
||||
// reset sent packets counter
|
||||
_sent_packets = 0;
|
||||
|
||||
statusMessage = F("upload ok");
|
||||
_printInfoLine(statusMessage + F("\r\n"));
|
||||
}
|
||||
|
||||
void ESPNexUpload::_setRunningMode(void)
|
||||
{
|
||||
String cmd = String("");
|
||||
delay(100);
|
||||
cmd = F("runmod=2");
|
||||
this->sendCommand(cmd.c_str());
|
||||
delay(60);
|
||||
}
|
||||
|
||||
bool ESPNexUpload::_echoTest(String input)
|
||||
{
|
||||
String cmd = String("");
|
||||
String response = String("");
|
||||
|
||||
cmd = "print \"" + input + "\"";
|
||||
this->sendCommand(cmd.c_str());
|
||||
|
||||
uint32_t duration_ms = calculateTransmissionTimeMs(cmd) * 2 + 10; // times 2 (send + receive) and 10 ms extra
|
||||
this->recvRetString(response, duration_ms);
|
||||
|
||||
return (response.indexOf(input) != -1);
|
||||
}
|
||||
|
||||
bool ESPNexUpload::_handlingSleepAndDim(void)
|
||||
{
|
||||
String cmd = String("");
|
||||
String response = String("");
|
||||
bool set_sleep = false;
|
||||
bool set_dim = false;
|
||||
|
||||
cmd = F("get sleep");
|
||||
this->sendCommand(cmd.c_str());
|
||||
|
||||
this->recvRetString(response);
|
||||
|
||||
if (response[0] != 0x71)
|
||||
{
|
||||
statusMessage = F("unknown response from 'get sleep' request");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response[1] != 0x00)
|
||||
{
|
||||
_printInfoLine(F("sleep enabled"));
|
||||
set_sleep = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_printInfoLine(F("sleep disabled"));
|
||||
}
|
||||
|
||||
response = String("");
|
||||
cmd = F("get dim");
|
||||
this->sendCommand(cmd.c_str());
|
||||
|
||||
this->recvRetString(response);
|
||||
|
||||
if (response[0] != 0x71)
|
||||
{
|
||||
statusMessage = F("unknown response from 'get dim' request");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response[1] == 0x00)
|
||||
{
|
||||
_printInfoLine(F("dim is 0%, backlight from display is turned off"));
|
||||
set_dim = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_printInfoLine();
|
||||
dbSerialPrint(F("dim "));
|
||||
dbSerialPrint((uint8_t)response[1]);
|
||||
dbSerialPrintln(F("%"));
|
||||
}
|
||||
|
||||
if (!_echoTest("ABC"))
|
||||
{
|
||||
statusMessage = F("echo test in 'handling sleep and dim' failed");
|
||||
_printInfoLine(statusMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (set_sleep)
|
||||
{
|
||||
cmd = F("sleep=0");
|
||||
this->sendCommand(cmd.c_str());
|
||||
// Unfortunately the display doesn't send any respone on the wake up request (sleep=0)
|
||||
// Let the ESP wait for one second, this is based on serial analyser from Nextion editor V0.58 to Nextion display NX4024T032_011R
|
||||
// This gives the Nextion display some time to wake up
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
if (set_dim)
|
||||
{
|
||||
cmd = F("dim=100");
|
||||
this->sendCommand(cmd.c_str());
|
||||
delay(15);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESPNexUpload::_printSerialData(bool esp_request, String input)
|
||||
{
|
||||
|
||||
char c;
|
||||
if (esp_request)
|
||||
dbSerialPrint(F("ESP request: "));
|
||||
else
|
||||
dbSerialPrint(F("Nextion respone: "));
|
||||
|
||||
if (input.length() == 0)
|
||||
{
|
||||
dbSerialPrintln(F("none"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < input.length(); i++)
|
||||
{
|
||||
|
||||
c = input[i];
|
||||
if ((uint8_t)c >= 0x20 && (uint8_t)c <= 0x7E)
|
||||
dbSerialPrint(c);
|
||||
else
|
||||
{
|
||||
dbSerialPrint(F("0x"));
|
||||
dbSerialPrintHex(c);
|
||||
dbSerialPrint(F(" "));
|
||||
}
|
||||
}
|
||||
dbSerialPrintln();
|
||||
}
|
||||
|
||||
uint32_t ESPNexUpload::calculateTransmissionTimeMs(String message)
|
||||
{
|
||||
// In general, 1 second (s) = 1000 (10^-3) millisecond (ms) or
|
||||
// 1 second (s) = 1000 000 (10^-6) microsecond (us).
|
||||
// To calculate how much microsecond one BIT of data takes with a certain baudrate you have to divide
|
||||
// the baudrate by one second.
|
||||
// For example 9600 baud = 1000 000 us / 9600 ≈ 104 us
|
||||
// The time to transmit one DATA byte (if we use default UART modulation) takes 10 bits.
|
||||
// 8 DATA bits and one START and one STOP bit makes 10 bits.
|
||||
// In this example (9600 baud) a byte will take 1041 us to send or receive.
|
||||
// Multiply this value by the length of the message (number of bytes) and the total transmit/ receive time
|
||||
// is calculated.
|
||||
|
||||
uint32_t duration_one_byte_us = 10000000 / _baudrate; // 1000 000 * 10 bits / baudrate
|
||||
uint16_t nr_of_bytes = message.length() + 3; // 3 times 0xFF byte
|
||||
uint32_t duration_message_us = nr_of_bytes * duration_one_byte_us;
|
||||
uint32_t return_value_ms = duration_message_us / 1000;
|
||||
|
||||
_printInfoLine("calculated transmission time: " + String(return_value_ms) + " ms");
|
||||
return return_value_ms;
|
||||
}
|
||||
|
||||
void ESPNexUpload::_printInfoLine(String line)
|
||||
{
|
||||
dbSerialPrint(F("Status info: "));
|
||||
if (line.length() != 0)
|
||||
dbSerialPrintln(line);
|
||||
}
|
||||
288
src/modules/display/Nextion/ESPNexUpload.h
Normal file
288
src/modules/display/Nextion/ESPNexUpload.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* @file NexUpload.h
|
||||
* The definition of class NexUpload.
|
||||
*
|
||||
*
|
||||
* 1 - BugFix when display baudrate is diffrent from initial ESP baudrate
|
||||
* 2 - Improved debug information
|
||||
* 3 - Make delay commands dependent on the baudrate
|
||||
* @author Machiel Mastenbroek (machiel.mastenbroek@gmail.com)
|
||||
* @date 2019/11/04
|
||||
* @version 0.5.5
|
||||
*
|
||||
* Stability improvement, Nextion display doesn’t freeze after the seconds 4096 trance of firmware bytes.
|
||||
* Now the firmware upload process is stabled without the need of a hard Display power off-on intervention.
|
||||
* Undocumented features (not mentioned in nextion-hmi-upload-protocol-v1-1 specification) are added.
|
||||
* This implementation is based in on a reverse engineering with a UART logic analyser between
|
||||
* the Nextion editor v0.58 and a NX4024T032_011R Display.
|
||||
*
|
||||
* @author Machiel Mastenbroek (machiel.mastenbroek@gmail.com)
|
||||
* @date 2019/10/24
|
||||
* @version 0.5.0
|
||||
*
|
||||
* Modified to work with ESP32, HardwareSerial and removed SPIFFS dependency
|
||||
* @author Onno Dirkzwager (onno.dirkzwager@gmail.com)
|
||||
* @date 2018/12/26
|
||||
* @version 0.3.0
|
||||
*
|
||||
* Modified to work with ESP8266 and SoftwareSerial
|
||||
* @author Ville Vilpas (psoden@gmail.com)
|
||||
* @date 2018/2/3
|
||||
* @version 0.2.0
|
||||
*
|
||||
* Original version (a part of https://github.com/itead/ITEADLIB_Arduino_Nextion)
|
||||
* @author Chen Zengpeng (email:<zengpeng.chen@itead.cc>)
|
||||
* @date 2016/3/29
|
||||
* @copyright
|
||||
* Copyright (C) 2014-2015 ITEAD Intelligent Systems Co., Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ESPNEXUPLOAD_H__
|
||||
#define __ESPNEXUPLOAD_H__
|
||||
#include <functional>
|
||||
#include <Arduino.h>
|
||||
#include <StreamString.h>
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <SoftwareSerial.h>
|
||||
#else
|
||||
#include <HardwareSerial.h>
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup CoreAPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
// callback template definition
|
||||
typedef std::function<void(void)> THandlerFunction;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides the API for nextion to upload the ftf file.
|
||||
*/
|
||||
class ESPNexUpload
|
||||
{
|
||||
public: /* methods */
|
||||
// callback template definition
|
||||
typedef std::function<void(void)> THandlerFunction;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param uint32_t upload_baudrate - set upload baudrate.
|
||||
*/
|
||||
ESPNexUpload(uint32_t upload_baudrate, int line, int rx, int tx);
|
||||
|
||||
/**
|
||||
* destructor.
|
||||
*
|
||||
*/
|
||||
~ESPNexUpload() {}
|
||||
|
||||
/**
|
||||
* Connect to Nextion over serial
|
||||
*
|
||||
* @return true or false.
|
||||
*/
|
||||
bool connect();
|
||||
|
||||
/**
|
||||
* prepare upload. Set file size & Connect to Nextion over serial
|
||||
*
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool prepareUpload(uint32_t file_size);
|
||||
|
||||
/**
|
||||
* set Update Progress Callback. (What to do during update progress)
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void setUpdateProgressCallback(THandlerFunction value);
|
||||
|
||||
/**
|
||||
* start update tft file to nextion.
|
||||
*
|
||||
* @param const uint8_t *file_buf
|
||||
* @param size_t buf_size
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool upload(const uint8_t *file_buf, size_t buf_size);
|
||||
|
||||
/**
|
||||
* start update tft file to nextion.
|
||||
*
|
||||
* @param Stream &myFile
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool upload(Stream &myFile);
|
||||
|
||||
/**
|
||||
* Send reset command to Nextion over serial
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void softReset(void);
|
||||
|
||||
/**
|
||||
* Send reset, end serial, reset _sent_packets & update status message
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void end(void);
|
||||
|
||||
public: /* data */
|
||||
String statusMessage = "";
|
||||
|
||||
private: /* methods */
|
||||
/*
|
||||
* get communicate baudrate.
|
||||
*
|
||||
* @return communicate baudrate.
|
||||
*
|
||||
*/
|
||||
uint16_t _getBaudrate(void);
|
||||
|
||||
/*
|
||||
* search communicate baudrate.
|
||||
*
|
||||
* @param baudrate - communicate baudrate.
|
||||
*
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool _searchBaudrate(uint32_t baudrate);
|
||||
|
||||
/*
|
||||
* set download baudrate.
|
||||
*
|
||||
* @param baudrate - set download baudrate.
|
||||
*
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool _setPrepareForFirmwareUpdate(uint32_t upload_baudrate);
|
||||
|
||||
/*
|
||||
* set Nextion running mode.
|
||||
*
|
||||
* Undocumented feature of the Nextion protocol.
|
||||
* It's used by the 'upload to Nextion device' feature of the Nextion Editor V0.58
|
||||
*
|
||||
* The nextion display doesn't send any response
|
||||
*
|
||||
*/
|
||||
void _setRunningMode(void);
|
||||
|
||||
/*
|
||||
* Test UART nextion connection availability
|
||||
*
|
||||
* @param input - echo string,
|
||||
*
|
||||
* @return true when the 'echo string' that is send is equal to the received string
|
||||
*
|
||||
* This test is used by the 'upload to Nextion device' feature of the Nextion Editor V0.58
|
||||
*
|
||||
*/
|
||||
bool _echoTest(String input);
|
||||
|
||||
/*
|
||||
* This function get the sleep and dim value from the Nextion display.
|
||||
*
|
||||
* If sleep = 1 meaning: sleep is enabled
|
||||
* action : sleep will be disabled
|
||||
* If dim = 0, meaning: the display backlight is turned off
|
||||
* action : dim will be set to 100 (percent)
|
||||
*
|
||||
*/
|
||||
bool _handlingSleepAndDim(void);
|
||||
|
||||
/*
|
||||
* This function (debug) print the Nextion response to a human readable string
|
||||
*
|
||||
* @param esp_request - true: request message from esp to nextion
|
||||
* false: response message from nextion to esp
|
||||
*
|
||||
* @param input - string to print
|
||||
*
|
||||
*/
|
||||
void _printSerialData(bool esp_request, String input);
|
||||
|
||||
/*
|
||||
* This function print a prefix debug line
|
||||
*
|
||||
* @param line: optional debug/ info line
|
||||
*/
|
||||
void _printInfoLine(String line = "");
|
||||
|
||||
/*
|
||||
* Send command to Nextion.
|
||||
*
|
||||
* @param cmd - the string of command.
|
||||
* @param tail - end the string with tripple 0xFF byte
|
||||
* @param null_head - start the string with a single 0x00 byte
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void sendCommand(const char *cmd, bool tail = true, bool null_head = false);
|
||||
|
||||
/*
|
||||
* Receive string data.
|
||||
*
|
||||
* @param buffer - save string data.
|
||||
* @param timeout - set timeout time.
|
||||
* @param recv_flag - if recv_flag is true,will braak when receive 0x05.
|
||||
*
|
||||
* @return the length of string buffer.
|
||||
*
|
||||
*/
|
||||
uint16_t recvRetString(String &string, uint32_t timeout = 500, bool recv_flag = false);
|
||||
|
||||
/*
|
||||
*
|
||||
* This function calculates the transmission time, the transmission time
|
||||
* is based on the length of the message and the baudrate.
|
||||
*
|
||||
* @param message - only used to determine the length of the message
|
||||
*
|
||||
* @return time in us length of string buffer.
|
||||
*
|
||||
*/
|
||||
uint32_t calculateTransmissionTimeMs(String message);
|
||||
|
||||
void nexSerialBegin(uint32_t upload_baudrate, int line, int rx, int tx);
|
||||
|
||||
private: /* data */
|
||||
uint32_t _baudrate; /* nextion serail baudrate */
|
||||
uint32_t _undownloadByte; /* undownload byte of tft file */
|
||||
uint32_t _upload_baudrate; /* upload baudrate */
|
||||
uint16_t _sent_packets = 0; /* upload baudrate */
|
||||
uint8_t _rx;
|
||||
uint8_t _tx;
|
||||
uint8_t _line;
|
||||
THandlerFunction _updateProgressCallback;
|
||||
|
||||
#ifdef ESP8266
|
||||
SoftwareSerial* nexSerial;
|
||||
#else
|
||||
Stream* nexSerial;
|
||||
#endif
|
||||
};
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* #ifndef __ESPNEXUPLOAD_H__ */
|
||||
312
src/modules/display/Nextion/Nextion.cpp
Normal file
312
src/modules/display/Nextion/Nextion.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
|
||||
#define DEBUG_SERIAL_ENABLE
|
||||
#include "Global.h"
|
||||
#include "classes/IoTUart.h"
|
||||
#include "ESPNexUpload.h"
|
||||
bool updated = false;
|
||||
|
||||
class Nextion : public IoTUart
|
||||
{
|
||||
private:
|
||||
String _url;
|
||||
String _host;
|
||||
int _tx, _rx, _speed, _line;
|
||||
bool _UpTelegram;
|
||||
char _inc;
|
||||
String _inStr = ""; // буфер приема строк в режимах 0, 1, 2
|
||||
|
||||
// Выводим русские буквы на экран Nextion (преобразуем в кодировку ISO-8859-5)
|
||||
String convertRUS(String text)
|
||||
{
|
||||
const char *in = text.c_str();
|
||||
String out;
|
||||
if (in == NULL)
|
||||
return out;
|
||||
|
||||
uint32_t codepoint = 0;
|
||||
while (*in != 0)
|
||||
{
|
||||
uint8_t ch = (uint8_t)(*in);
|
||||
if (ch <= 0x7f)
|
||||
codepoint = ch;
|
||||
else if (ch <= 0xbf)
|
||||
codepoint = (codepoint << 6) | (ch & 0x3f);
|
||||
else if (ch <= 0xdf)
|
||||
codepoint = ch & 0x1f;
|
||||
else if (ch <= 0xef)
|
||||
codepoint = ch & 0x0f;
|
||||
else
|
||||
codepoint = ch & 0x07;
|
||||
++in;
|
||||
if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff))
|
||||
{
|
||||
if (codepoint <= 255)
|
||||
{
|
||||
out += (char)codepoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (codepoint > 0x400)
|
||||
out += (char)(codepoint - 0x360);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public:
|
||||
Nextion(String parameters) : IoTUart(parameters)
|
||||
{
|
||||
_url = jsonReadStr(parameters, "url");
|
||||
_url = "/" + _url;
|
||||
_host = jsonReadStr(parameters, "host");
|
||||
jsonRead(parameters, "rx", _rx);
|
||||
jsonRead(parameters, "tx", _tx);
|
||||
jsonRead(parameters, "speed", _speed);
|
||||
jsonRead(parameters, "line", _line);
|
||||
jsonRead(parameters, "uploadTelegram", _UpTelegram);
|
||||
}
|
||||
|
||||
IoTValue execute(String command, std::vector<IoTValue> ¶m)
|
||||
{
|
||||
|
||||
if (command == "Update")
|
||||
{
|
||||
updateServer();
|
||||
}
|
||||
else if (command == "printFFF")
|
||||
{
|
||||
if (param.size() == 2)
|
||||
//UART.printFFF("auto.val=1",0)
|
||||
{
|
||||
String strToUart = "";
|
||||
strToUart = param[0].valS;
|
||||
|
||||
if (param[1].valD)
|
||||
uartPrintFFF("\"" + strToUart + "\"");
|
||||
else
|
||||
uartPrintFFF(strToUart);
|
||||
}
|
||||
// отправка данных на Nextion - UART.printFFF("t1.txt=", ID_vidget + " °", 1);
|
||||
// или UART.printRusFFF("buttons.bt0.txt="," Гостинная",1);
|
||||
if (param.size() == 3)
|
||||
{
|
||||
String strToUart = "";
|
||||
strToUart = param[0].valS;
|
||||
|
||||
if (param[2].valD)
|
||||
uartPrintFFF(strToUart + "\"" + param[1].valS + "\"");
|
||||
else
|
||||
uartPrintFFF(strToUart + param[1].valS);
|
||||
}
|
||||
}
|
||||
// отправка кирилических символов на Nextion (русские буквы)
|
||||
else if (command == "printRusFFF")
|
||||
{
|
||||
if (param.size() == 2)
|
||||
{
|
||||
String strToUart = "";
|
||||
strToUart = param[0].valS;
|
||||
|
||||
if (param[1].valD)
|
||||
uartPrintFFF(convertRUS("\"" + strToUart + "\""));
|
||||
else
|
||||
uartPrintFFF(convertRUS(strToUart));
|
||||
}
|
||||
if (param.size() == 3)
|
||||
{
|
||||
String strToUart = "";
|
||||
strToUart = param[0].valS;
|
||||
|
||||
if (param[2].valD)
|
||||
uartPrintFFF(convertRUS(strToUart + "\"" + param[1].valS + "\""));
|
||||
else
|
||||
uartPrintFFF(convertRUS(strToUart + param[1].valS));
|
||||
}
|
||||
}// else { // не забываем, что переопределяем execute и нужно проверить что в базовом классе проверяется
|
||||
// return IoTUart::execute(command, param);
|
||||
// }
|
||||
return {};
|
||||
}
|
||||
|
||||
void onModuleOrder(String &key, String &value) {
|
||||
if (key == "uploadServer") {
|
||||
updateServer();
|
||||
}
|
||||
}
|
||||
|
||||
void uartPrintFFF(const String& msg) {
|
||||
if (_myUART) {
|
||||
SerialPrint("I", F("Nextion"), "uartPrintFFF -> "+msg+" +FFFFFF");
|
||||
_myUART->print(msg);
|
||||
_myUART->write(0xff);
|
||||
_myUART->write(0xff);
|
||||
_myUART->write(0xff);
|
||||
}
|
||||
}
|
||||
//---------------------NEXTION-UART---START------------------------
|
||||
void uartHandle() {
|
||||
if (!_myUART) return;
|
||||
if (_myUART->available()) {
|
||||
_inc = _myUART->read();
|
||||
if (_inc == 0xFF) {
|
||||
_inc = _myUART->read();
|
||||
_inc = _myUART->read();
|
||||
_inStr = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_inc == '\r') return;
|
||||
|
||||
if (_inc == '\n') {
|
||||
if (_inStr.indexOf("=") == -1) { // если входящее сообщение не по формату, то работаем как в режиме 0
|
||||
setValue(_inStr);
|
||||
return;
|
||||
}
|
||||
String id = selectToMarker(_inStr, "=");
|
||||
String valStr = selectToMarkerLast(_inStr, "=");
|
||||
valStr.replace("\"", "");
|
||||
id.replace(".val", "_val");
|
||||
id.replace(".txt", "_txt");
|
||||
generateOrder(id, valStr);
|
||||
_inStr = "";
|
||||
} else _inStr += _inc;
|
||||
}
|
||||
}
|
||||
|
||||
void onRegEvent(IoTItem* eventItem) {
|
||||
if (!_myUART || !eventItem) return;
|
||||
int indexOf_;
|
||||
String printStr = "";
|
||||
|
||||
printStr += eventItem->getID();
|
||||
indexOf_ = printStr.indexOf("_");
|
||||
if (indexOf_ == -1) return; // пропускаем событие, если нет используемого признака типа данных - _txt или _vol
|
||||
|
||||
if (printStr.indexOf("_txt") > 0) {
|
||||
printStr.replace("_txt", ".txt=\"");
|
||||
printStr += eventItem->getValue();
|
||||
printStr += "\"";
|
||||
} else if (printStr.indexOf("_val") > 0) {
|
||||
printStr += eventItem->getValue();
|
||||
printStr.replace(".", "");
|
||||
printStr.replace("_val", ".val=");
|
||||
} else {
|
||||
if (indexOf_ == printStr.length()-1) printStr.replace("_", "");
|
||||
else printStr.replace("_", ".");
|
||||
printStr += "=";
|
||||
printStr += eventItem->getValue();
|
||||
}
|
||||
|
||||
uartPrintFFF(convertRUS(printStr));
|
||||
}
|
||||
|
||||
//---------------------NEXTION-UART---END------------------------
|
||||
|
||||
//---------------------NEXTION-UPDATE---START------------------------
|
||||
void updateServer()
|
||||
{
|
||||
SerialPrint("I", F("NextionUpdate"), "Update .... ");
|
||||
|
||||
if (!updated)
|
||||
{
|
||||
SerialPrint("I", F("NextionUpdate"), "connecting to " + (String)_host);
|
||||
HTTPClient http;
|
||||
#if defined ESP8266
|
||||
if (!http.begin(_host, 80, _url))
|
||||
SerialPrint("I", F("NextionUpdate"), "connection failed ");
|
||||
#elif defined ESP32
|
||||
if (!http.begin(String("http://") + _host + _url))
|
||||
SerialPrint("I", F("NextionUpdate"), "connection failed ");
|
||||
#endif
|
||||
|
||||
SerialPrint("I", F("NextionUpdate"), "Requesting file: " + (String)_url);
|
||||
int code = http.GET();
|
||||
// Update the nextion display
|
||||
if (code == 200)
|
||||
flashNextion(http);
|
||||
else
|
||||
SerialPrint("I", F("NextionUpdate"), "HTTP error: " + (String)http.errorToString(code).c_str());
|
||||
|
||||
http.end();
|
||||
SerialPrint("I", F("NextionUpdate"), "Closing connection ");
|
||||
}
|
||||
}
|
||||
|
||||
void uploadNextionTlgrm(String &url)
|
||||
{
|
||||
if (!_UpTelegram)
|
||||
return;
|
||||
if (!updated)
|
||||
{
|
||||
SerialPrint("I", F("NextionUpdate"), "connecting to " + url);
|
||||
|
||||
HTTPClient http;
|
||||
|
||||
#ifdef ESP8266
|
||||
SerialPrint("I", F("NextionUpdate"), "Update impossible esp8266: Change boards to esp32 :)");
|
||||
return;
|
||||
#else
|
||||
if (!http.begin(url)) // пингуем файл
|
||||
SerialPrint("I", F("NextionUpdate"), "connection failed ");
|
||||
#endif
|
||||
SerialPrint("I", F("NextionUpdate"), "Requesting file: OK" );
|
||||
int code = http.GET();
|
||||
// Update the nextion display
|
||||
if (code == 200)
|
||||
flashNextion(http);
|
||||
else
|
||||
SerialPrint("I", F("NextionUpdate"), "HTTP error: " + (String)http.errorToString(code).c_str());
|
||||
|
||||
http.end();
|
||||
SerialPrint("I", F("NextionUpdate"), "Closing connection ");
|
||||
}
|
||||
}
|
||||
|
||||
void flashNextion(HTTPClient &http)
|
||||
{
|
||||
int contentLength = http.getSize();
|
||||
SerialPrint("I", F("NextionUpdate"), "File received. Update Nextion... ");
|
||||
bool result;
|
||||
ESPNexUpload nexUp(_speed, _line, _rx, _tx);
|
||||
nexUp.setUpdateProgressCallback([]()
|
||||
{ SerialPrint("I", F("NextionUpdate"), "... "); });
|
||||
|
||||
result = nexUp.prepareUpload(contentLength);
|
||||
if (!result)
|
||||
{
|
||||
SerialPrint("I", F("NextionUpdate"), "Error: " + (String)nexUp.statusMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
SerialPrint("I", F("NextionUpdate"), "Start upload. File size is: " + (String)contentLength);
|
||||
result = nexUp.upload(*http.getStreamPtr());
|
||||
if (result)
|
||||
{
|
||||
updated = true;
|
||||
SerialPrint("I", F("NextionUpdate"), "Succesfully updated Nextion! ");
|
||||
}
|
||||
else
|
||||
{
|
||||
SerialPrint("I", F("NextionUpdate"), "Error updating Nextion: " + (String)nexUp.statusMessage);
|
||||
}
|
||||
nexUp.end();
|
||||
}
|
||||
}
|
||||
//---------------------NEXTION-UPDATE---END------------------------
|
||||
|
||||
~Nextion(){};
|
||||
|
||||
};
|
||||
|
||||
void *getAPI_Nextion(String subtype, String param)
|
||||
{
|
||||
if (subtype == F("Nextion"))
|
||||
{
|
||||
return new Nextion(param);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
98
src/modules/display/Nextion/modinfo.json
Normal file
98
src/modules/display/Nextion/modinfo.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"menuSection": "screens",
|
||||
"configItem": [
|
||||
{
|
||||
"global": 0,
|
||||
"name": "Nextion",
|
||||
"type": "Reading",
|
||||
"subtype": "Nextion",
|
||||
"id": "nex",
|
||||
"widget": "",
|
||||
"page": "",
|
||||
"descr": "",
|
||||
"host": "192.168.1.10:5500",
|
||||
"url": "nextion.tft",
|
||||
"btn-uploadServer": "",
|
||||
"tx": 17,
|
||||
"rx": 16,
|
||||
"line": 2,
|
||||
"speed": 9600,
|
||||
"uploadTelegram": 1
|
||||
}
|
||||
],
|
||||
"about": {
|
||||
"authorName": "Bubnov Mikhail",
|
||||
"authorContact": "https://t.me/Mit4bmw",
|
||||
"authorGit": "https://github.com/Mit4el",
|
||||
"specialThanks": "",
|
||||
"moduleName": "Nextion",
|
||||
"moduleVersion": "2.0",
|
||||
"usedRam": {
|
||||
"esp32_4mb": 15,
|
||||
"esp8266_4mb": 15
|
||||
},
|
||||
"title": "Nextion",
|
||||
"moduleDesc": "загрузка прошивки в дисплей Nextion. Команда для запуска обновления дисплея: Nextion.Update(); ",
|
||||
"propInfo": {
|
||||
"tx": "TX пин",
|
||||
"rx": "RX пин",
|
||||
"speed": "Скорость UART",
|
||||
"line": "Актуально только для ESP32: номер линии hardUART. =2 rx=16 tx=17, для SoftwarwSerial в ESP32 line = -1",
|
||||
"host": "Сервер обновления. Можно использовать LiveServer из VisualCode, указывать ip адрес",
|
||||
"url": "файл прошивки экрана, указывать с расширением, например nextion.tft или iotm/test.tft",
|
||||
"uploadTelegram": "1 - разрешает прошивать экран через модуль Telegram_v2",
|
||||
"btn-uploadServer": "Кнопка загрузки прошивки с сервера LiveServer или другого по ip"
|
||||
},
|
||||
"funcInfo": [
|
||||
{
|
||||
"name": "Update",
|
||||
"descr": "Функция сценария для загрузки прошивки с сервера LiveServer или другого по ip",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"name": "printFFF",
|
||||
"descr": "Отправить в UART текстовую строку и hex метку 3 байта 0xFF0xFF0xFF. Напимер nex.printFFF(\"auto.val=1\",0)",
|
||||
"params": [
|
||||
"Строка текста",
|
||||
"1 - обернуть строку в кавычки, 0 - отправить без кавычек"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "printFFF",
|
||||
"descr": "Отправить в UART текстовую строку и hex метку 3 байта 0xFF0xFF0xFF. Напимер nex.printFFF(\"t1.txt=\", ID_vidget + \" °\", 1);",
|
||||
"params": [
|
||||
"Строка текста",
|
||||
"ID Виджета или любое значение",
|
||||
"1 - обернуть строку в кавычки, 0 - отправить без кавычек"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "printRusFFF",
|
||||
"descr": "Отправить в UART текстовую строку и hex метку 3 байта 0xFF0xFF0xFF. С предварительной конвертацией русских букв (преобразуем в кодировку ISO-8859-5)",
|
||||
"params": [
|
||||
"Строка текста",
|
||||
"1 - обернуть строку в кавычки, 0 - отправить без кавычек"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "printRusFFF",
|
||||
"descr": "Отправить в UART текстовую строку и hex метку 3 байта 0xFF0xFF0xFF. С предварительной конвертацией русских букв (преобразуем в кодировку ISO-8859-5)",
|
||||
"params": [
|
||||
"Строка текста",
|
||||
"ID Виджета или любое значение",
|
||||
"1 - обернуть строку в кавычки, 0 - отправить без кавычек"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"defActive": false,
|
||||
"usedLibs": {
|
||||
"esp32_4mb": [],
|
||||
"esp32_4mb3f": [],
|
||||
"esp8266_4mb": [],
|
||||
"esp8266_1mb": [],
|
||||
"esp8266_1mb_ota": [],
|
||||
"esp8285_1mb": [],
|
||||
"esp8285_1mb_ota": []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user