new Nextion

This commit is contained in:
Mit4el
2023-11-17 23:00:52 +03:00
parent cffc6dbab5
commit 4f7eaff3b5
4 changed files with 1355 additions and 0 deletions

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

View 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 doesnt 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__ */

View 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> &param)
{
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;
}
}

View 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": []
}
}