Nextion display plugin

Moderators: BertB, rtenklooster, Voyager, Stuntteam, Martinus

Message
Author
BertB
Normal user
Posts: 947
Joined: 25 Apr 2015, 14:39

Re: Nextion display plugin

#271 Post by BertB » 14 Jul 2018, 09:17

Sounds like a good idea to me.

ThomasB
Normal user
Posts: 57
Joined: 17 Jun 2018, 20:41
Location: USA

Re: Nextion display plugin

#272 Post by ThomasB » 14 Jul 2018, 18:14

@TD-er: I was hoping to hear that there was a built-in method to postpone plugin Write events. Since that was wishful thinking, your suggestion (thanks!) is where I will go.

I looked through the ESP Easy code and can't find an existing string Queue routine to use. I don't want to re-invent the wheel so I prefer using a library function. There are a couple published queue handlers available, but that means it would have to be installed. Like this one:
https://playground.arduino.cc/Code/QueueList

Is adding another library frowned upon or is it a normal thing for the ESP Easy developers to do? Any guidance on this is appreciated.

Also, enhancing the ESPeasySoftwareSerial module to add functions to switch between hardware (both swap and USB) and soft serial would be fantastic. I'd be happy to contribute to the effort (not as a project leader, but can do some grunt work like testing/validation).

@BertB: Any chance you can try out the new V3 Nextion code and perform some validation? BTW, I found an odd issue with TaskDeviceName that required me to make some code changes shortly after I published it. So copy the V3 plugin's code again to ensure you have the revised V3.

- Thomas

BertB
Normal user
Posts: 947
Joined: 25 Apr 2015, 14:39

Re: Nextion display plugin

#273 Post by BertB » 14 Jul 2018, 22:09

@ThomasB, I will do the testing.

BertB
Normal user
Posts: 947
Joined: 25 Apr 2015, 14:39

Re: Nextion display plugin

#274 Post by BertB » 14 Jul 2018, 23:06

@ThomasB
After I installed your latest version V3, I started with using D7 and D8 as Rx and Tx, with the Use Hardware Serial left unchecked.
Initially this works fine, but for some reason, I get unintended events. It is as if press a switch (1274) on the Nextion, but I don't.

It happens once every minute and this is the serial log.
600472 : LoadFromFile: config.dat index: 4096 datasize: 472
600475 : LoadFromFile: config.dat index: 5120 datasize: 768
600537 : LoadFromFile: config.dat index: 6144 datasize: 472
600543 : LoadFromFile: config.dat index: 4096 datasize: 472
600572 : LoadFromFile: config.dat index: 6144 datasize: 472
600575 : LoadFromFile: config.dat index: 4096 datasize: 472
600603 : LoadFromFile: config.dat index: 6144 datasize: 472
600606 : LoadFromFile: config.dat index: 4096 datasize: 472
600637 : LoadFromFile: config.dat index: 6144 datasize: 472
600639 : LoadFromFile: config.dat index: 4096 datasize: 472
600676 : EVENT: E16Nextion#idx=1274.00
600684 : ACT : SendToHTTP xxx.xxx.xxx.xxx,8080,/json.htm?type=command&param=switchlight&idx=387&switchcmd=Toggle
600700 : Command: sendtohttp
600732 : HTTP/1.1 200 OK

600770 : EVENT: E16Nextion#idx=1274.00 Processing time:94 milliSeconds
600771 : EVENT: E16Nextion#value=0.00
600795 : EVENT: E16Nextion#value=0.00 Processing time:25 milliSeconds
600796 : LoadFromFile: config.dat index: 28672 datasize: 724
600814 : Domoticz: Sensortype: 5 idx: 1 values: 1274;0
600815 : MQTT : {"idx":1,"RSSI":3,"nvalue":0,"svalue":"1274;0"}
600818 : LoadFromFile: config.dat index: 29696 datasize: 724
600837 : HTTP : connecting to xxx.xxx.xxx.xxx:8080
600851 : Domoticz: Sensortype: 5 idx: 310 values: 1274;0
600881 : HTTP : Success
600888 : HTTP : closing connection
600985 : NEXTION075 : WRITE, Command is page3.b5.bco=48631
601472 : LoadFromFile: config.dat index: 6144 datasize: 472
603475 : EVENT: Clock#Time=Sat,23:02
603500 : EVENT: Clock#Time=Sat,23:02 Processing time:25 milliSeconds
603571 : LoopStats: shortestLoop: 46 longestLoop: 1137307 avgLoopDuration: 128.59 systemTimerDuration: 21.62 systemTimerCalls: 32 loopCounterMax: 652173 loopCounterLast: 230924 countFindPluginId: 0
603580 : PluginStats P_37_Generic - MQTT Import READ Count: 1 Avg/min/max 2541.00/2541/2541 usec
603589 : PluginStats P_37_Generic - MQTT Import ONCE_A_SECOND Count: 31 Avg/min/max 2177.32/2127/2541 usec
603599 : PluginStats P_37_Generic - MQTT Import TEN_PER_SECOND Count: 297 Avg/min/max 2225.59/2083/3868 usec
603609 : PluginStats P_37_Generic - MQTT Import WRITE Count: 2 Avg/min/max 2311.50/2094/2529 usec
603619 : PluginStats P_37_Generic - MQTT Import EVENT_OUT Count: 1 Avg/min/max 2813.00/2813/2813 usec
603629 : PluginStats P_37_Generic - MQTT Import SERIAL_IN Count: 1 Avg/min/max 2068.00/2068/2068 usec
603639 : PluginStats P_37_Generic - MQTT Import FIFTY_PER_SECOND Count: 1476 Avg/min/max 2147.14/2055/2684 usec
603647 : PluginStats P_71_Display - Nextion [TESTING_V3] READ Count: 1 Avg/min/max 200096.00/200096/200096 usec
603658 : PluginStats P_71_Display - Nextion [TESTING_V3] ONCE_A_SECOND Count: 31 Avg/min/max 34.45/26/47 usec
603668 : PluginStats P_71_Display - Nextion [TESTING_V3] TEN_PER_SECOND Count: 297 Avg/min/max 133.53/122/159 usec
603679 : PluginStats P_71_Display - Nextion [TESTING_V3] WRITE Count: 3 Avg/min/max 7632.00/134/22608 usec
603689 : PluginStats P_71_Display - Nextion [TESTING_V3] EVENT_OUT Count: 1 Avg/min/max 58.00/58/58 usec
603700 : PluginStats P_71_Display - Nextion [TESTING_V3] SERIAL_IN Count: 1 Avg/min/max 47.00/47/47 usec
603710 : PluginStats P_71_Display - Nextion [TESTING_V3] FIFTY_PER_SECOND Count: 1476 Avg/min/max 38.09/27/48 usec
603720 : Load File stats: Count: 13 Avg/min/max 4399.46/1332/19547 usec
603726 : Plugin call 50 p/s stats: Count: 1476 Avg/min/max 3122.74/2974/3819 usec
603734 : Plugin call 10 p/s stats: Count: 297 Avg/min/max 3275.19/3090/4900 usec
603741 : Plugin call 10 p/s U stats: Count: 297 Avg/min/max 3235.36/2997/3832 usec
603748 : Plugin call 1 p/s stats: Count: 31 Avg/min/max 18967.03/4096/425777 usec
603756 : checkSensors() stats: Count: 31 Avg/min/max 14398.42/547/422162 usec
603763 : sendData() stats: Count: 1 Avg/min/max 217326.00/217326/217326 usec
603771 : Compute formula stats: Count: 1 Avg/min/max 19.00/19/19 usec
603777 : WD : Uptime 10 ConnectFailures 0 FreeMem 14200

ThomasB
Normal user
Posts: 57
Joined: 17 Jun 2018, 20:41
Location: USA

Re: Nextion display plugin

#275 Post by ThomasB » 14 Jul 2018, 23:54

That's very interesting. Is it reliably happening every minute, or does the time vary?

On the bottom of the Nextion plugin web access page, directly above the Values names, is a Interval time scroll box. What is the value [sec] entered there?

- Thomas

BertB
Normal user
Posts: 947
Joined: 25 Apr 2015, 14:39

Re: Nextion display plugin

#276 Post by BertB » 15 Jul 2018, 00:06

@ThomasB
It is 60 seconds, give or take a few.
The delay also is 60 sec.

ThomasB
Normal user
Posts: 57
Joined: 17 Jun 2018, 20:41
Location: USA

Re: Nextion display plugin

#277 Post by ThomasB » 15 Jul 2018, 00:31

Ok, then you are seeing expected behavior. The last received idx and value are stored. Then at each elapsed timer interval the idx and value are resent.

I assume that this is how other plugins' Interval function works. If not then I'll need to know what the expected behavior is so this plugin follows the ESPeasy standards.

The workaround? You can create a rule that sets the idx and value to 0 after your MQTT is sent. Then ignore 0 on future interval updates. In my home automation installation (Openhab) I have local rules that only trigger when the data changes. So repeated values are ignored.

- Thomas

BertB
Normal user
Posts: 947
Joined: 25 Apr 2015, 14:39

Re: Nextion display plugin

#278 Post by BertB » 15 Jul 2018, 00:45

Two comments on that.
1 I cannot remember thuis happening with the original version.

2 In this case the event only triggers a rule. Idx will be id of the switch. Value is always 0.

I will test this in more detail tomorrow.

ThomasB
Normal user
Posts: 57
Joined: 17 Jun 2018, 20:41
Location: USA

Re: Nextion display plugin

#279 Post by ThomasB » 15 Jul 2018, 00:54

No code changes were made that would affect this behavior, so you'll find that the original does it too. But if this is wrong then we can fix it.
In this case the event only triggers a rule. Idx will be id of the switch. Value is always 0.
As an alternative you can set both to -1 (or any other number) after your MQTT. Just choose a number that does not normally occur so that you can ignore it.

Edit #1: My Nextion sends custom idx codes that range from 10 to 30. I don't sent Nextion Touch events, but have a rule for them in case I decide to do that in the future. So here's a ESPeasy rule example that sends a MQTT to my home controller, then masks the sent data (set to -1) so it can be ignored by the rule when the timer intervals occur:

Code: Select all

on NEXTION#idx do
  if [NEXTION#idx]>=10 and [NEXTION#idx]<=30
      Publish /%sysname%/NEXTION/idx,[NEXTION#idx]
  endif
  if [NEXTION#idx]>=500  // Touch Events
      Publish /%sysname%/NEXTION/idx,[NEXTION#idx]
      Publish /%sysname%/NEXTION/value,[NEXTION#value]
     NEXTION#value = -1
  endif
  NEXTION#idx = -1
endon


Edit #2
: I expect others will share your feelings about the repeating idx and value. So I have a solution; We can allow the user to disable the interval timer (set Interval to 0 secs). But let's talk about this some more after your validation is further along. All the needed changes can be folded into the next beta revision.

Thanks for doing the testing!

- Thomas

BertB
Normal user
Posts: 947
Joined: 25 Apr 2015, 14:39

Re: Nextion display plugin

#280 Post by BertB » 15 Jul 2018, 12:50

ThomasB wrote:
15 Jul 2018, 00:54
No code changes were made that would affect this behavior, so you'll find that the original does it too. But if this is wrong then we can fix it.
I dare to disagree :-). I carried out some investigation and found out that your latest (7-13-2018) code has the flaw, whereas my latest modification (07082018) has not.
Just to be sure, below both versions. Off course, there is a lot of difference between them.

07082018 version:

Code: Select all

//#######################################################################################################
//################################### Plugin 075: Nextion <info@sensorio.cz>  ###########################
//################################### Created on the work of  majklovec       ###########################
//#######################################################################################################
#ifdef USES_P075

#define PLUGIN_075
#define PLUGIN_ID_075 75
//#define PLUGIN_NAME_075 "Display - Nextion [TESTING]"
#define PLUGIN_NAME_075 "Display - Nextion   [BERTB REV3]"
#define PLUGIN_VALUENAME1_075 "code"
#define PLUGIN_VALUENAME2_075 "value"
#define Nlines 12        // The number of different lines which can be displayed - each line is 64 chars max

boolean Plugin_075_init = false;

boolean Plugin_075(byte function, struct EventStruct *event, String &string) {
  boolean success = false;

  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].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));
      success = true;
      break;
    }

    case PLUGIN_GET_DEVICEGPIONAMES: {
      int rxPin = Settings.TaskDevicePin1[event->TaskIndex];
      int txPin = Settings.TaskDevicePin2[event->TaskIndex];
      
      if ((rxPin == 3 && txPin == 1) || (rxPin == 13 && txPin == 15)) {
        event->String1 = F("GPIO HW RX &larr;");
        event->String2 = F("GPIO HW TX &rarr;");
      }
      else {  // Soft Serial.
        event->String1 = F("GPIO SS RX &larr;");
        event->String2 = F("GPIO SS TX &rarr;");
      }
      break;
    }

    case PLUGIN_INIT: {

/*      LoadTaskSettings(event->TaskIndex);

      if (Settings.TaskDevicePin1[event->TaskIndex] != -1)
        {
          Plugin_075_RXpin = Settings.TaskDevicePin1[event->TaskIndex];
        }

      if (Settings.TaskDevicePin2[event->TaskIndex] != -1)
        {
          Plugin_075_TXpin = Settings.TaskDevicePin2[event->TaskIndex];
        }

      if (!nextion) {
        nextion = new ESPeasySoftwareSerial(Plugin_075_RXpin , Plugin_075_TXpin);
      }
*/
      Serial.begin(9600);
      Serial.flush();
      Serial.swap();

      Plugin_075_init = true;
      success = true;
      break;
    }

       
    case PLUGIN_TEN_PER_SECOND: {
      if(Plugin_075_init) {
        char __buffer[80];

        uint16_t i;
        uint8_t c;
        String Vidx;
        String Nvalue;
        String Svalue;
        String Nswitch;

        while (Serial.available() > 0) {
          delay(10);
          c = Serial.read();

          if (0x65 == c) {
            if (Serial.available() >= 6) {
              __buffer[0] = c;
              for (i = 1; i < 7; i++) {
                __buffer[i] = Serial.read();
              }

              __buffer[i] = 0x00;

              if (0xFF == __buffer[4] && 0xFF == __buffer[5] && 0xFF == __buffer[6]) {
                UserVar[event->BaseVarIndex] = __buffer[1] * 256 + __buffer[2];
                UserVar[event->BaseVarIndex + 1] = __buffer[3];
                String log = F("Nextion : code: ");
                log += __buffer[1];
                log += ",";
                log += __buffer[2];
                log += ",";
                log += __buffer[3];

                addLog(LOG_LEVEL_INFO, log);
                sendData(event);
                
                success = true;
              }
              else success = false;
              
              return success;
            }
          }
          else if (c == '|') {
              i = 1;
              __buffer[0] = c;
              c=0;
              while (Serial.available() > 0) {
                __buffer[i] = Serial.read();
                if (__buffer[i]==0x0d) break;
                i++;
              }
              __buffer[i] = 0x00;

              String tmpString = __buffer;

              int argIndex = tmpString.indexOf(F(",i"));
              int argEnd = tmpString.indexOf(',', argIndex + 1);
              if (argIndex)
                Vidx = tmpString.substring(argIndex + 2,argEnd);

              switch (__buffer[1]){

                case 'u':

                  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':

                  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;

                default:
                  success = false;
                  return success;
                  break;
                }

                UserVar[event->BaseVarIndex] = Vidx.toFloat();
                UserVar[event->BaseVarIndex+1] = Svalue.toFloat();

                String log = F("Nextion : send command: ");
                log += __buffer;
                log += UserVar[event->BaseVarIndex];
                addLog(LOG_LEVEL_INFO, log);
                sendData(event);

                ExecuteCommand(VALUE_SOURCE_SYSTEM, __buffer);

                success = true;
              }
              else success = false;
            }
          }
          break;
      }

    case PLUGIN_ONCE_A_SECOND: {
        success = true;
        break;
      }


    case PLUGIN_WEBFORM_SAVE: {

        String argName;

        char deviceTemplate[Nlines][64];
        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][63]=0;

//          strncpy(deviceTemplate[varNr], WebServer.arg(argName).c_str(), sizeof(deviceTemplate[varNr]));
        }

        SaveCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));

      success = true;
      break;
    }

    case PLUGIN_WEBFORM_LOAD: {
      char deviceTemplate[Nlines][64];
      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], 64);
      }

      success = true;
      break;
    }


/*    case PLUGIN_EXIT:
      {
          if (nextion)
          {
            delete nextion;
            nextion=NULL;
          }
          break;
      }
*/
    case PLUGIN_READ: {
        char deviceTemplate[Nlines][64];
        LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
        String newString;

        for (byte x = 0; x < Nlines; x++) {
          String tmpString = deviceTemplate[x];
          if (tmpString.length())
          {
            int rssiIndex = tmpString.indexOf(F("rssi"));
            if(rssiIndex >= 0)
            {
              int barVal;
              newString = tmpString.substring(0, rssiIndex);
              int nbars = WiFi.RSSI();
              if (nbars < -100)
                 barVal=0;
              else if (nbars >= -100 and nbars < -90)
                 barVal=20;
              else if (nbars >= -90 and nbars < -80)
                 barVal=40;
              else if (nbars >= -80 and nbars < -70)
                 barVal=60;
              else if (nbars >= -70 and nbars < -60)
                 barVal=80;
              else if (nbars >= -60)
                 barVal=100;

              newString += String(barVal,DEC);
            }
            else
            {
              newString = parseTemplate(tmpString, 0);
            }

            sendCommand(newString.c_str());
          }
        }

        success = false;
        break;
      }


    case PLUGIN_WRITE: {
      String tmpString = string;
      int argIndex = tmpString.indexOf(',');
      if (argIndex)
        tmpString = tmpString.substring(0, argIndex);
      if (tmpString.equalsIgnoreCase(F("NEXTION"))) {
        argIndex = string.indexOf(',');
        tmpString = string.substring(argIndex + 1);

        sendCommand(tmpString.c_str());

//        Serial.println(tmpString);
        success = true;
      }
      break;
    }
  }
  return success;
}


void sendCommand(const char *cmd) {
  Serial.print(cmd);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

#endif // USES_P075
07132018 version:

Code: Select all

//#######################################################################################################
//#######################################################################################################
//################################### Plugin 075: Nextion <info@sensorio.cz>  ###########################
//###################################   Created on the work of  majklovec     ###########################
//###################################    Revisions by BertB and ThomasB       ########################### 
//###################################    Last Revision: July-13-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_V3]"
#define PLUGIN_VALUENAME1_075 "idx"
#define PLUGIN_VALUENAME2_075 "value"
#define Nlines 12        // Qty of "optional" user entered Command-Text strings, 64 chars max per line.

// Nextion defines
#define RXBUFFSZ  80     // Local Serial RxD buffer.  
#define TOUCH_BASE 500   // Base offset for 0X65 Touch Event.

// Serial defines
#define B9600    0
#define B38400   1
#define B57600   2
#define B115200  3
#define DEFAULT_BAUD B9600

// Global vars
ESPeasySoftwareSerial *SoftSerial = NULL;
int rxPin = -1;
int txPin = -1;


// *****************************************************************************************************
// PlugIn starts here
// *****************************************************************************************************

boolean Plugin_075(byte function, struct EventStruct *event, String& string) 
{
  boolean success = false;
  static boolean HwSerial = false;
  static boolean AdvHwSerial = false;  
  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].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 &larr; ");
      event->String2 = F("GPIO SS TX &rarr; ");

      if(AdvHwSerial == true) {
        if ((rxPin == 3 && txPin == 1) || (rxPin == 13 && txPin == 15)) {
            event->String1 = F("GPIO HW RX &larr; ");
            event->String2 = F("GPIO HW TX &rarr; ");
        }
      }
      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][64];
      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], 64);
      }

      success = true;
      break;
    }


    case PLUGIN_WEBFORM_SAVE: {

        String argName;

        char deviceTemplate[Nlines][64];
        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][63]=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"));
        SaveCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));

        success = true;
        break;
    }


    case PLUGIN_INIT: {

      AdvHwSerial = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
      uint8_t BaudCode = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
      
      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][64];
        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;
        break;
    }


    case PLUGIN_WRITE: {
        String tmpString = string;
        int argIndex = tmpString.indexOf(',');
        if (argIndex) tmpString = tmpString.substring(0, argIndex);

//      String log = F("TaskDeviceName : ");
//      log += ExtraTaskSettings.TaskDeviceName;
//      addLog(LOG_LEVEL_INFO, log);

        if (tmpString.equalsIgnoreCase(F("NEXTION"))) {
//      if (tmpString.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceName)) { // Use Plugin Name as command ID name.
            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 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];
              log = F("NEXTION075 : code: ");
              log += __buffer[1];
              log += ",";
              log += __buffer[2];
              log += ",";
              log += __buffer[3];
              addLog(LOG_LEVEL_INFO, log);

              sendData(event);
            }
          }
        } 
        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 SerialHW) 
{
    if(SerialHW) {
        Serial.print(cmd);
        Serial.write(0xff);
        Serial.write(0xff);
        Serial.write(0xff);
    }
    else {
        SoftSerial->print(cmd);
        SoftSerial->write(0xff);
        SoftSerial->write(0xff);
        SoftSerial->write(0xff);
    }
}

#endif // USES_P075
Thanks for doing the testing!
No problem. It is my baby too :-)

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests