@BertB: Sorry to hear about the problems. I've made some changes, plus added some log info to help debug the problems.
This version has a new checkbox for those users that want to resend idx and value data at the interval. Of course I know you don't want these values to be resent, so uncheck the Interval Options->Resend Values. When deselected/unchecked, the "Lines" statements will still act at each interval timeout, but the idx & value data will be skipped.
Code: Select all
//#######################################################################################################
//#######################################################################################################
//################################### Plugin 075: Nextion <info@sensorio.cz> ###########################
//################################### Created on the work of majklovec ###########################
//################################### Revisions by BertB and ThomasB ###########################
//################################### Last Revision: July-27-2018 (TB) ###########################
//#######################################################################################################
#ifdef USES_P075
#include <ESPeasySoftwareSerial.h>
// *****************************************************************************************************
// Defines start here
// *****************************************************************************************************
// Plug-In defines
#define PLUGIN_075
#define PLUGIN_ID_075 75
#define PLUGIN_NAME_075 "Display - Nextion [TESTING]"
#define PLUGIN_VALUENAME1_075 "idx"
#define PLUGIN_VALUENAME2_075 "value"
// Configuration Settings. Custom Configuration Memory must be less than 512 Bytes!
#define Nlines 10 // Custom Config, Number of user entered Command-Text Lines.
#define Lenlines 51 // Custom Config, Length of user entered Command-Text Lines.
// Nextion defines
#define RXBUFFSZ 80 // Local Serial RxD buffer.
#define TOUCH_BASE 500 // Base offset for 0X65 Touch Event Component ID.
// Serial defines
#define B9600 0
#define B38400 1
#define B57600 2
#define B115200 3
#define DEFAULT_BAUD B9600
// Global vars
ESPeasySoftwareSerial *SoftSerial = NULL;
char deviceTemplate[Nlines][Lenlines];
int rxPin = -1;
int txPin = -1;
// *****************************************************************************************************
// PlugIn starts here
// *****************************************************************************************************
boolean Plugin_075(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
static uint8_t BaudCode = 0; // Web GUI baud rate drop down. 9600 if 0, See array for other rates.
static boolean HwSerial = false; // Use Hardware Serial if true.
static boolean AdvHwSerial = false; // Web GUI checkbox enabled, Hardware Serial if true.
static boolean IncludeValues = false; // Web GUI checkbox enabled, Send Values at interval if true.
uint32_t AdvHwBaud = 9600UL;
switch (function) {
case PLUGIN_DEVICE_ADD: {
Device[++deviceCount].Number = PLUGIN_ID_075;
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
Device[deviceCount].VType = SENSOR_TYPE_DUAL;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = true;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = false;
Device[deviceCount].ValueCount = 2;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].TimerOptional = true; // Allow user to disable interval function.
Device[deviceCount].GlobalSyncOption = true;
break;
}
case PLUGIN_GET_DEVICENAME: {
string = F(PLUGIN_NAME_075);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES: {
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0],PSTR(PLUGIN_VALUENAME1_075));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1],PSTR(PLUGIN_VALUENAME2_075));
break;
}
case PLUGIN_GET_DEVICEGPIONAMES: {
AdvHwSerial = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
rxPin = Settings.TaskDevicePin1[event->TaskIndex];
txPin = Settings.TaskDevicePin2[event->TaskIndex];
event->String1 = F("GPIO SS RX ← ");
event->String2 = F("GPIO SS TX → ");
if(AdvHwSerial == true) {
if ((rxPin == 3 && txPin == 1) || (rxPin == 13 && txPin == 15)) {
event->String1 = F("GPIO HW RX ← ");
event->String2 = F("GPIO HW TX → ");
}
}
break;
}
case PLUGIN_WEBFORM_LOAD: {
rxPin = Settings.TaskDevicePin1[event->TaskIndex];
txPin = Settings.TaskDevicePin2[event->TaskIndex];
if (!((rxPin == 3 && txPin == 1) || (rxPin == 13 && txPin == 15))) { // Hardware Serial Compatible?
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = false; // Not HW serial compatible, Reset Check Box.
}
if (rxPin == 3 && txPin == 1) { // USB Port?
if(Settings.TaskDevicePluginConfig[event->TaskIndex][0]==false && // Hardware serial disabled.
Settings.TaskDeviceEnabled[event->TaskIndex] == true) { // Plugin is enabled.
Settings.TaskDevicePluginConfig[event->TaskIndex][0]=true; // USB port access uses HW serial, Force set Check Box.
}
}
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == false) { // Softserial mode.
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = B9600; // Reset to 9600 baud.
}
addFormSeparator(2);
addFormSubHeader(F("Enhanced Serial Communication"));
addFormCheckBox(F("Use Hardware Serial"), F("AdvHwSerial"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
String options[4];
options[0] = F("9600");
options[1] = F("38400");
options[2] = F("57600");
options[3] = F("115200");
addFormSelector(F("Baud Rate"), F("plugin_075_baud"), 4, options, NULL, choice);
addFormNote(F("Un-check box for Soft Serial communication (low performance mode, 9600 Baud)."));
addFormNote(F("Hardware Serial is available when the GPIO pins are RX=D7 and TX=D8."));
addFormNote(F("D8 (GPIO-15) requires a Buffer Circuit (PNP transistor) or ESP boot may fail."));
addFormNote(F("Do <b>NOT</b> enable the Serial Log file on Tools->Advanced->Serial Port."));
// ** DEVELOPER DEBUG MESSAGE AREA **
// addFormNote(ExtraTaskSettings.TaskDeviceName); // Debug value.
// int datax = (int)(Settings.TaskDeviceEnabled[event->TaskIndex]); // Debug value.
// String Data = "Debug. Plugin Enable State: ";
// Data += String(datax);
// addFormNote(Data);
addFormSubHeader(F("")); // Blank line, vertical space.
addFormHeader(F("Nextion Command-Text Strings (Optional)"));
char deviceTemplate[Nlines][Lenlines];
LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
for (byte varNr = 0; varNr < Nlines; varNr++) {
addFormTextBox(String(F("Line ")) + (varNr + 1), String(F("Plugin_075_template")) + (varNr + 1), deviceTemplate[varNr], Lenlines-1);
}
if( Settings.TaskDeviceTimer[event->TaskIndex]==0) {
if(IncludeValues) {
addFormNote(F("Interval Timer OFF, Nextion Lines (above) and Values (below) <b>NOT</b> scheduled for updates"));
}
else {
addFormNote(F("Interval Timer OFF, Nextion Lines (above) <b>NOT</b> scheduled for updates"));
}
}
addFormSeparator(2);
addFormSubHeader(F("Interval Options"));
addFormCheckBox(F("Resend <b>Values</b> (below) at Interval"), F("IncludeValues"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE: {
String argName;
char deviceTemplate[Nlines][Lenlines];
for (byte varNr = 0; varNr < Nlines; varNr++)
{
String arg = F("Plugin_075_template");
arg += varNr + 1;
String tmpString = WebServer.arg(arg);
strncpy(deviceTemplate[varNr], tmpString.c_str(), sizeof(deviceTemplate[varNr])-1);
deviceTemplate[varNr][Lenlines-1]=0;
}
if(ExtraTaskSettings.TaskDeviceName[0] == 0) { // User forgot to enter device name!
strcpy(ExtraTaskSettings.TaskDeviceName,"NEXTION"); // Give standard name.
}
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = isFormItemChecked(F("AdvHwSerial"));
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_075_baud"));
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = isFormItemChecked(F("IncludeValues"));
SaveCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
success = true;
break;
}
case PLUGIN_INIT: {
AdvHwSerial = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
BaudCode = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
IncludeValues = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
if(BaudCode > B115200) BaudCode = B9600;
const uint32_t BaudArray[4] = {9600UL, 38400UL, 57600UL, 115200UL};
AdvHwBaud = BaudArray[BaudCode];
if (Settings.TaskDevicePin1[event->TaskIndex] != -1) {
rxPin = Settings.TaskDevicePin1[event->TaskIndex];
}
if (Settings.TaskDevicePin2[event->TaskIndex] != -1) {
txPin = Settings.TaskDevicePin2[event->TaskIndex];
}
if (SoftSerial != NULL) {
delete SoftSerial;
SoftSerial = NULL;
}
String log = F("NEXTION075 : serial pin config RX:");
log += rxPin;
log += F(", TX:");
log += txPin;
if(Settings.TaskDeviceEnabled[event->TaskIndex]==true)
log += F(", Plugin Enabled"); // Plugin is enabled.
else log += F(", Plugin Disabled");
addLog(LOG_LEVEL_INFO, log);
if(Settings.TaskDeviceEnabled[event->TaskIndex] == true) { // Plugin is enabled.
// Hardware serial is RX on 13 and TX on 15 (swapped hw serial)
if (AdvHwSerial && rxPin == 13 && txPin == 15) {
log = F("NEXTION075 : Using swap hardware serial");
addLog(LOG_LEVEL_INFO, log);
HwSerial = true;
Settings.UseSerial = false; // Disable global Serial port.
Settings.SerialLogLevel = 0; // Disable logging on serial port.
Settings.BaudRate = AdvHwBaud; // Set BaudRate for Nextion.
Serial.flush();
Serial.begin(AdvHwBaud);
Serial.swap();
}
// Hardware serial is RX on 3 and TX on 1. USB serial for Nextion IDE (User MCU Input function).
else if(AdvHwSerial && rxPin == 3 && txPin == 1) {
log = F("NEXTION075 : Using USB hardware serial");
addLog(LOG_LEVEL_INFO, log);
HwSerial = true;
Settings.UseSerial = false; // Disable global Serial port.
Settings.SerialLogLevel = 0; // Disable logging on serial port.
Settings.BaudRate = AdvHwBaud; // Set BaudRate for Nextion.
Serial.flush();
Serial.begin(AdvHwBaud);
}
else {
log = F("NEXTION075 : Using software serial");
addLog(LOG_LEVEL_INFO, log);
HwSerial = false;
if (SoftSerial == NULL) {
SoftSerial = new ESPeasySoftwareSerial(rxPin, txPin);
}
SoftSerial->begin(9600);
SoftSerial->flush();
}
}
else {
}
success = true;
break;
}
case PLUGIN_READ: { // Get Plugin's optional command-text strings. Special RSSIBAR bargraph keyword is supported.
char deviceTemplate[Nlines][Lenlines];
int RssiIndex;
String newString;
String tmpString;
String UcTmpString;
LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
for (byte x = 0; x < Nlines; x++) {
tmpString = deviceTemplate[x];
if (tmpString.length()) {
UcTmpString = deviceTemplate[x];
UcTmpString.toUpperCase();
RssiIndex = UcTmpString.indexOf(F("RSSIBAR")); // RSSI bargraph Keyword found, wifi value in dBm.
if(RssiIndex >= 0) {
int barVal;
newString = tmpString.substring(0, RssiIndex);
int nbars = WiFi.RSSI();
if (nbars < -100 || nbars >= 0)
barVal=0;
else if (nbars >= -100 && nbars < -95)
barVal=5;
else if (nbars >= -95 && nbars < -90)
barVal=10;
else if (nbars >= -90 && nbars < -85)
barVal=20;
else if (nbars >= -85 && nbars < -80)
barVal=30;
else if (nbars >= -80 && nbars < -75)
barVal=45;
else if (nbars >= -75 && nbars < -70)
barVal=60;
else if (nbars >= -70 && nbars < -65)
barVal=70;
else if (nbars >= -65 && nbars < -55)
barVal=80;
else if (nbars >= -55 && nbars < -50)
barVal=90;
else if (nbars >= -50)
barVal=100;
newString += String(barVal,DEC);
}
else {
newString = parseTemplate(tmpString, 0);
}
sendCommand(newString.c_str(), HwSerial);
// success = true;
}
}
// At Interval timer, send idx & value data only if user enabled "values" interval mode.
if(IncludeValues) {
String log = F("NEXTION075: Interval Values enabled, resending idx=");
log += String(UserVar[event->BaseVarIndex]);
log += F(", value=");
log += String(UserVar[event->BaseVarIndex+1]);
addLog(LOG_LEVEL_INFO, log);
success = true;
}
else {
String log = F("NEXTION075: Interval Values disabled, idx & value values not resent");
addLog(LOG_LEVEL_INFO, log);
success = false;
}
break;
}
case PLUGIN_WRITE: {
String tmpString = string;
int argIndex = tmpString.indexOf(',');
if (argIndex) tmpString = tmpString.substring(0, argIndex);
// String log = F("Nextion Name : ");
// log += ExtraTaskSettings.TaskDeviceName;
// log += F(", str: ");
// log += string;
// addLog(LOG_LEVEL_INFO, log);
if (tmpString.equalsIgnoreCase(F("NEXTION"))) { // Use hard coded name, patch for TaskDeviceName bug.
// if (tmpString.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceName)) { // Buggy! Plugin's TaskDeviceName not working correctly.
argIndex = string.indexOf(',');
tmpString = string.substring(argIndex + 1);
sendCommand(tmpString.c_str(), HwSerial);
String log = F("NEXTION075 : WRITE, ");
log += F("Command is ");
log += (tmpString.c_str());
addLog(LOG_LEVEL_INFO, log);
success = true; // Set true only if plugin found a command to execute.
}
break;
}
case PLUGIN_EXIT: {
if (SoftSerial) {
delete SoftSerial;
SoftSerial=NULL;
}
if(HwSerial) {
HwSerial = false;
Settings.UseSerial = DEFAULT_USE_SERIAL;
Settings.BaudRate = DEFAULT_SERIAL_BAUD;
Serial.flush();
Serial.begin(DEFAULT_SERIAL_BAUD); // Restart Serial Logging with default baud.
}
break;
}
case PLUGIN_ONCE_A_SECOND: {
success = true;
break;
}
case PLUGIN_TEN_PER_SECOND: {
uint16_t i;
uint8_t c;
uint8_t charCount;
String log;
String Vidx;
String Nvalue;
String Svalue;
String Nswitch;
char __buffer[RXBUFFSZ+1];
if(HwSerial) {
charCount = Serial.available(); // Prime the Hardware Serial engine.
}
else {
if(SoftSerial == NULL) break; // Plugin issue, maybe it was deleted.
charCount = SoftSerial->available(); // Prime the Soft Serial engine.
}
while (charCount) { // This is the serial engine. It processes the serial Rx stream.
if(HwSerial) c = Serial.read();
else c = SoftSerial->read();
if (c == 0x65) {
if (charCount < 6) delay((5/(AdvHwBaud/9600))+1); // Let's wait for a few more chars to arrive.
if (HwSerial) charCount = Serial.available();
else charCount = SoftSerial->available();
if (charCount >= 6) {
__buffer[0] = c;
for (i = 1; i < 7; i++) {
if(HwSerial) __buffer[i] = Serial.read();
else __buffer[i] = SoftSerial->read();
}
__buffer[i] = 0x00;
if (0xFF == __buffer[4] && 0xFF == __buffer[5] && 0xFF == __buffer[6]) {
UserVar[event->BaseVarIndex] = (__buffer[1] * 256) + __buffer[2] + TOUCH_BASE;
UserVar[event->BaseVarIndex + 1] = __buffer[3];
sendData(event);
log = F("NEXTION075 : code: ");
log += __buffer[1];
log += ",";
log += __buffer[2];
log += ",";
log += __buffer[3];
addLog(LOG_LEVEL_INFO, log);
}
}
}
else {
if (c == '|') {
__buffer[0] = c;
if (charCount < 8) delay((9/(AdvHwBaud/9600))+1); // Let's wait for more chars to arrive.
else delay((3/(AdvHwBaud/9600))+1); // Short wait for tardy chars.
if (HwSerial) charCount = Serial.available();
else charCount = SoftSerial->available();
if(HwSerial) {
i = 1;
while (Serial.available() > 0 && i<RXBUFFSZ) { // Copy global serial buffer to local buffer.
__buffer[i] = Serial.read();
if (__buffer[i]==0x0a || __buffer[i]==0x0d) break;
i++;
}
}
else {
i = 1;
while (SoftSerial->available() > 0 && i<RXBUFFSZ) { // Copy global serial buffer to local buffer.
__buffer[i] = SoftSerial->read();
if (__buffer[i]==0x0a || __buffer[i]==0x0d) break;
i++;
}
}
__buffer[i] = 0x00;
String tmpString = __buffer;
log = F("NEXTION075 : code: ");
log += tmpString;
addLog(LOG_LEVEL_INFO, log);
int argIndex = tmpString.indexOf(F(",i"));
int argEnd = tmpString.indexOf(',', argIndex + 1);
if (argIndex) Vidx = tmpString.substring(argIndex + 2,argEnd);
boolean GotPipeCmd = false;
switch (__buffer[1]){
case 'u':
GotPipeCmd = true;
argIndex = argEnd;
argEnd = tmpString.indexOf(',',argIndex + 1);
if (argIndex) Nvalue = tmpString.substring(argIndex + 2,argEnd);
argIndex = argEnd;
argEnd = tmpString.indexOf(0x0a);
if (argIndex) Svalue = tmpString.substring(argIndex + 2,argEnd);
break;
case 's':
GotPipeCmd = true;
argIndex = argEnd;
argEnd = tmpString.indexOf(0x0a);
if (argIndex) Nvalue = tmpString.substring(argIndex + 2,argEnd);
if (Nvalue == F("On")) Svalue='1';
if (Nvalue == F("Off")) Svalue='0';
break;
}
if (GotPipeCmd) {
UserVar[event->BaseVarIndex] = Vidx.toFloat();
UserVar[event->BaseVarIndex+1] = Svalue.toFloat();
sendData(event);
log = F("NEXTION075 : Pipe Command Sent: ");
log += __buffer;
log += UserVar[event->BaseVarIndex];
}
else {
log = F("NEXTION075 : Unknown Pipe Command, skipped");
}
addLog(LOG_LEVEL_INFO, log);
}
}
if(HwSerial) charCount = Serial.available();
else charCount = SoftSerial->available();
}
success = true;
break;
}
}
return success;
}
void sendCommand(const char *cmd, boolean SerialMode)
{
if(SerialMode) { // Send command using Hardware UART serial.
Serial.print(cmd);
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
}
else { // Send command using bit-bang soft serial.
if(SoftSerial != NULL){
SoftSerial->print(cmd);
SoftSerial->write(0xff);
SoftSerial->write(0xff);
SoftSerial->write(0xff);
}
else {
String log = F("NEXTION075 : SoftSerial error, aborted sendCommand");
addLog(LOG_LEVEL_INFO, log);
}
}
return;
}
#endif // USES_P075
I did a quick validation and reviewed the syslog. I don't see any issues that will invite disco dance. Hopefully nothing new is broken and the changes fix the disco problem.