[Cleanup] Uniform labels for GPIO pins

For all other plugins not setting the GPIO labels, all are now added.
Also reverted the decision about RX/TX, since these are the only ones to be crossed, the rest is always describing the data on the sensor side.
"GPIO <-- TX" is rather descriptive. The GPIO is on the ESP side, TX is on the sensor side.

So the function to format the label is called `formatGpioName_RX` and it will write "GPIO <- TX"
At least it is clear where it is going to be used, it is the RX channel on the ESP side. (for example SoftwareSerial describes the pins with function on ESP side)
This commit is contained in:
TD-er
2018-11-11 12:42:36 +01:00
parent 72637da44c
commit 26d7c95b6f
35 changed files with 202 additions and 32 deletions
+12 -2
View File
@@ -272,12 +272,22 @@ String formatGpioName_output_optional(const String& label) {
return formatGpioName(label, gpio_output, true);
}
// RX/TX are the only signals which are crossed, so they must be labelled like this:
// "GPIO <-- RX" and "GPIO <-- TX"
String formatGpioName_TX(bool optional) {
return formatGpioName("TX", gpio_output, optional);
return formatGpioName("RX", gpio_output, optional);
}
String formatGpioName_RX(bool optional) {
return formatGpioName("RX", gpio_input, optional);
return formatGpioName("TX", gpio_input, optional);
}
String formatGpioName_TX_HW(bool optional) {
return formatGpioName("RX (HW)", gpio_output, optional);
}
String formatGpioName_RX_HW(bool optional) {
return formatGpioName("TX (HW)", gpio_input, optional);
}
/*********************************************************************************************\
+1 -1
View File
@@ -2280,7 +2280,7 @@ void handle_devices() {
if (Device[DeviceIndex].Type >= DEVICE_TYPE_SINGLE)
addFormPinSelect(TempEvent.String1, F("taskdevicepin1"), Settings.TaskDevicePin1[taskIndex]);
if (Device[DeviceIndex].Type >= DEVICE_TYPE_DUAL)
addFormPinSelect( TempEvent.String2, F("taskdevicepin2"), Settings.TaskDevicePin2[taskIndex]);
addFormPinSelect(TempEvent.String2, F("taskdevicepin2"), Settings.TaskDevicePin2[taskIndex]);
if (Device[DeviceIndex].Type == DEVICE_TYPE_TRIPLE)
addFormPinSelect(TempEvent.String3, F("taskdevicepin3"), Settings.TaskDevicePin3[taskIndex]);
}
+13
View File
@@ -99,6 +99,19 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
// FIXME TD-er: This plugin is handling too much.
// - switch/dimmer input
// - PWM output
// - switch output (relays)
// - servo output
// - sending pulses
// - playing tunes
event->String1 = formatGpioName_bidirectional("");
break;
}
case PLUGIN_WEBFORM_LOAD:
{
String options[2];
+6
View File
@@ -63,6 +63,12 @@ boolean Plugin_003(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_input(F("Pulse"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNumericBox(F("Debounce Time (mSec)"), F("p003")
+10 -4
View File
@@ -51,6 +51,12 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_bidirectional(F("1-Wire"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
uint8_t savedAddress[8];
@@ -111,7 +117,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
ExtraTaskSettings.TaskDevicePluginConfigLong[x] = addr[x];
Plugin_004_DS_setResolution(addr, getFormItemInt(F("p004_res")));
Plugin_004_DS_startConvertion(addr);
Plugin_004_DS_startConversion(addr);
}
success = true;
break;
@@ -135,7 +141,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
if (Plugin_004_DallasPin != -1){
uint8_t addr[8];
Plugin_004_get_addr(addr, event->TaskIndex);
Plugin_004_DS_startConvertion(addr);
Plugin_004_DS_startConversion(addr);
delay(800); //give it time to do intial conversion
}
success = true;
@@ -163,7 +169,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
UserVar[event->BaseVarIndex] = NAN;
log += F("Error!");
}
Plugin_004_DS_startConvertion(addr);
Plugin_004_DS_startConversion(addr);
log += (" (");
for (byte x = 0; x < 8; x++)
@@ -218,7 +224,7 @@ byte Plugin_004_DS_scan(byte getDeviceROM, uint8_t* ROM)
* 11 bits resolution -> 375 ms
* 12 bits resolution -> 750 ms
\*********************************************************************************************/
void Plugin_004_DS_startConvertion(uint8_t ROM[8])
void Plugin_004_DS_startConversion(uint8_t ROM[8])
{
Plugin_004_DS_reset();
Plugin_004_DS_write(0x55); // Choose ROM
+6
View File
@@ -59,6 +59,12 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_bidirectional(F("Data"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
const String options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021") };
+7
View File
@@ -52,6 +52,13 @@ boolean Plugin_008(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_input(F("D0 (Green, 5V)"));
event->String2 = formatGpioName_input(F("D1 (White, 5V)"));
break;
}
case PLUGIN_INIT:
{
Plugin_008_init = true;
+6
View File
@@ -64,6 +64,12 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("Trigger"));
event->String2 = formatGpioName_input(F("Echo, 5V"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
+10 -4
View File
@@ -133,6 +133,12 @@ boolean Plugin_016(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_input(F("IR"));
break;
}
case PLUGIN_INIT:
{
int irPin = Settings.TaskDevicePin1[event->TaskIndex];
@@ -251,9 +257,9 @@ boolean Plugin_016(byte function, struct EventStruct *event, String& string)
// an IRSEND HTTP/MQTT command. It analyzes the timings, and searches for a common denominator which can be
// used to compress the values. If found, it then produces a string consisting of B32 Hex digit for each
// timing value, appended by the denominators for Pulse and Blank. This string can then be used in an
// IRSEND command. An important advantage of this string over the current IRSEND RAW B32 format implemented
// IRSEND command. An important advantage of this string over the current IRSEND RAW B32 format implemented
// by GusPS is that it allows easy inspections and modifications after the code is constructed.
//
//
// Author: Gilad Raz (jazzgil) 23sep2018
void displayRawToReadableB32Hex() {
@@ -265,7 +271,7 @@ void displayRawToReadableB32Hex() {
line += uint64ToString(results.rawbuf[i] * RAWTICK, 10) + ",";
addLog(LOG_LEVEL_DEBUG, line);
// Find a common denominator divisor for odd indexes (pulses) and then even indexes (blanks).
// Find a common denominator divisor for odd indexes (pulses) and then even indexes (blanks).
for (uint16_t p = 0; p < 2; p++) {
uint16_t cd = 0xFFFFU; // current divisor
// find the lowest value to start the divisor with.
@@ -273,7 +279,7 @@ void displayRawToReadableB32Hex() {
uint16_t val = results.rawbuf[i] * RAWTICK;
if (cd > val) cd = val;
}
uint16_t bstDiv = -1, bstAvg = 0xFFFFU;
float bstMul = 5000;
cd += get_tolerance(cd) + 1;
+1
View File
@@ -68,6 +68,7 @@ boolean Plugin_017(byte function, struct EventStruct *event, String& string)
case PLUGIN_WEBFORM_LOAD:
{
// FIXME TD-er: Why is this using pin3 and not pin1? And why isn't this using the normal pin selection functions?
addFormPinSelect(F("Reset Pin"), F("taskdevicepin3"), Settings.TaskDevicePin3[event->TaskIndex]);
success = true;
break;
+6
View File
@@ -45,6 +45,12 @@ boolean Plugin_018(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("LED"));
break;
}
case PLUGIN_INIT:
{
Plugin_018_init = true;
+6
View File
@@ -44,6 +44,12 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_bidirectional(F("Reset"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNumericBox(F("TCP Port"), F("p020_port"), ExtraTaskSettings.TaskDevicePluginConfigLong[0]);
+6
View File
@@ -43,6 +43,12 @@ boolean Plugin_021(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("Level low"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
// char tmpString[128];
+1
View File
@@ -104,6 +104,7 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
addFormTextBox(String(F("Line ")) + (varNr + 1), String(F("p023_template")) + (varNr + 1), deviceTemplate[varNr], 64);
}
// FIXME TD-er: Why is this using pin3 and not pin1? And why isn't this using the normal pin selection functions?
addFormPinSelect(F("Display button"), F("taskdevicepin3"), Settings.TaskDevicePin3[event->TaskIndex]);
addFormNumericBox(F("Display Timeout"), F("plugin_23_timer"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
+1 -1
View File
@@ -17,7 +17,7 @@ boolean Plugin_029(byte function, struct EventStruct *event, String& string)
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_029;
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
Device[deviceCount].Type = DEVICE_TYPE_SINGLE; // FIXME TD-er: Does this need a pin? Seems not to be used
Device[deviceCount].VType = SENSOR_TYPE_SWITCH;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
+7
View File
@@ -56,6 +56,13 @@ boolean Plugin_031(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_bidirectional(F("Data"));
event->String2 = formatGpioName_output(F("SCK"));
break;
}
case PLUGIN_INIT:
{
Plugin_031_init = true;
+14 -8
View File
@@ -7,7 +7,7 @@
#include <IRremoteESP8266.h>
#endif
#include <IRsend.h>
#include <IRutils.h>
#include <IRutils.h>
IRsend *Plugin_035_irSender;
@@ -45,6 +45,12 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_TX();
break;
}
case PLUGIN_INIT:
{
int irPin = Settings.TaskDevicePin1[event->TaskIndex];
@@ -92,7 +98,7 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
if (IrType.equalsIgnoreCase(F("RAW")) || IrType.equalsIgnoreCase(F("RAW2"))) {
String IrRaw;
uint16_t IrHz=0;
uint16_t IrHz=0;
unsigned int IrPLen=0;
unsigned int IrBLen=0;
@@ -117,7 +123,7 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
printWebString += IrBLen;
printWebString += F("<BR>");
uint16_t buf[200];
uint16_t buf[200];
uint16_t idx = 0;
if (IrType.equalsIgnoreCase(F("RAW"))) {
unsigned int c0 = 0; //count consecutives 0s
@@ -247,16 +253,16 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
memcpy(ircodestr, TmpStr1, sizeof(TmpStr1[0])*100);
}
//if (GetArgv(command, TmpStr1, 100, 4)) IrBits = str2int(TmpStr1); //not needed any more... leave it for reverce compatibility or remove it and break existing instalations?
//if (GetArgv(command, TmpStr1, 100, 5)) IrRepeat = str2int(TmpStr1); // Ir repeat is usfull in some circonstances, have to see how to add it and have it be revese compatible as well.
//if (GetArgv(command, TmpStr1, 100, 5)) IrRepeat = str2int(TmpStr1); // Ir repeat is usfull in some circonstances, have to see how to add it and have it be revese compatible as well.
//if (GetArgv(command, TmpStr1, 100, 6)) IrSecondCode = strtoul(TmpStr1, NULL, 16);
//Comented out need char[] for input Needs fixing
if (IrType.equalsIgnoreCase(F("NEC"))) Plugin_035_irSender->sendNEC(IrCode);
if (IrType.equalsIgnoreCase(F("SONY"))) Plugin_035_irSender->sendSony(IrCode);
if (IrType.equalsIgnoreCase(F("Sherwood"))) Plugin_035_irSender->sendSherwood(IrCode);
if (IrType.equalsIgnoreCase(F("SAMSUNG"))) Plugin_035_irSender->sendSAMSUNG(IrCode);
if (IrType.equalsIgnoreCase(F("LG"))) Plugin_035_irSender->sendLG(IrCode);
if (IrType.equalsIgnoreCase(F("SharpRaw"))) Plugin_035_irSender->sendSharpRaw(IrBits);
if (IrType.equalsIgnoreCase(F("LG"))) Plugin_035_irSender->sendLG(IrCode);
if (IrType.equalsIgnoreCase(F("SharpRaw"))) Plugin_035_irSender->sendSharpRaw(IrBits);
if (IrType.equalsIgnoreCase(F("JVC"))) Plugin_035_irSender->sendJVC(IrCode);
if (IrType.equalsIgnoreCase(F("Denon"))) Plugin_035_irSender->sendDenon(IrCode);
if (IrType.equalsIgnoreCase(F("SanyoLC7461"))) Plugin_035_irSender->sendSanyoLC7461(IrCode);
@@ -485,7 +491,7 @@ void parseStringAndSendAirCon(const uint16_t irType, const String str) {
break;
#endif
}
}
#if SEND_PRONTO
+1
View File
@@ -145,6 +145,7 @@ boolean Plugin_036(byte function, struct EventStruct *event, String& string)
addFormTextBox(String(F("Line ")) + (varNr + 1), String(F("p036_template")) + (varNr + 1), P036_deviceTemplate[varNr], P36_Nchars);
}
// FIXME TD-er: Why is this using pin3 and not pin1? And why isn't this using the normal pin selection functions?
addFormPinSelect(F("Display button"), F("taskdevicepin3"), Settings.TaskDevicePin3[event->TaskIndex]);
addFormNumericBox(F("Display Timeout"), F("p036_timer"), Settings.TaskDevicePluginConfig[event->TaskIndex][4]);
+2
View File
@@ -66,6 +66,8 @@ boolean Plugin_038(byte function, struct EventStruct *event, String& string)
int indices[] = { 1, 2 };
addFormNumericBox(F("Led Count"), F("p038_leds"), Settings.TaskDevicePluginConfig[event->TaskIndex][0],1,999);
// FIXME TD-er: Why isn't this using the normal pin selection functions?
addFormPinSelect(F("GPIO"), F("taskdevicepin1"), Settings.TaskDevicePin1[event->TaskIndex]);
addFormSelector(F("Strip Type"), F("p038_strip"), 2, options, indices, Settings.TaskDevicePluginConfig[event->TaskIndex][1] );
+6
View File
@@ -80,6 +80,12 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("CS"));
break;
}
case PLUGIN_INIT:
{
// Get CS Pin
+6
View File
@@ -49,6 +49,12 @@ boolean Plugin_041(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("Data"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNumericBox(F("Red"), F("p041_red"), Settings.TaskDevicePluginConfig[event->TaskIndex][0], 0, 255);
+6
View File
@@ -133,6 +133,12 @@ boolean Plugin_042(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("Data"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addHtml(F("<script src=\"jscolor.min.js\"></script>\n"));
+6
View File
@@ -41,6 +41,12 @@ boolean Plugin_043(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output(F("Clock Event"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
String options[3];
+1
View File
@@ -80,6 +80,7 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
addFormNumericBox(F("Stop bits"), F("p044_stop"), ExtraTaskSettings.TaskDevicePluginConfigLong[4]);
// FIXME TD-er: Why isn't this using the normal pin selection functions?
addFormPinSelect(F("Reset target after boot"), F("taskdevicepin1"), Settings.TaskDevicePin1[event->TaskIndex]);
addFormNumericBox(F("RX Receive Timeout (mSec)"), F("p044_rxwait"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
+7
View File
@@ -198,6 +198,13 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(false);
break;
}
case PLUGIN_WEBFORM_LOAD:
{
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
+7
View File
@@ -63,6 +63,13 @@ boolean Plugin_052(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(false);
break;
}
case PLUGIN_WRITE:
{
String cmd = parseString(string, 1);
+1 -1
View File
@@ -214,7 +214,7 @@ boolean Plugin_053(byte function, struct EventStruct *event, String& string)
{
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(false);
event->String3 = formatGpioName_output(F("Reset");
event->String3 = formatGpioName_output(F("Reset"));
break;
}
+1 -1
View File
@@ -135,9 +135,9 @@ boolean Plugin_055(byte function, struct EventStruct *event, String& string)
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] <= 0) //Plugin_055_millisPauseTime
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = 400;
// FIXME TD-er: Should we add support for 4 pin definitions?
addFormPinSelect(formatGpioName_output(F("Driver#8")), F("TDP4"), (int)(Settings.TaskDevicePin[3][event->TaskIndex]));
addFormSubHeader(F("Timing"));
addFormNumericBox(F("Chiming/Strike Time (ct)"), F("chimetime"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
+8 -6
View File
@@ -59,6 +59,14 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_056));
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(true); // optional
break;
}
case PLUGIN_WEBFORM_LOAD:
{
if (Plugin_056_hasTxPin(event)) {
@@ -83,12 +91,6 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
success = true;
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(true);
break;
}
case PLUGIN_INIT:
{
+7
View File
@@ -57,6 +57,13 @@ boolean Plugin_071(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(false);
break;
}
case PLUGIN_INIT:
{
Plugin_071_init = true;
+6
View File
@@ -92,6 +92,12 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
// Do not name the pins, since they are swapped between types.
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNote(F("TM1637: 1st=CLK-Pin, 2nd=DIO-Pin"));
+4 -4
View File
@@ -114,13 +114,13 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
rxPin = Settings.TaskDevicePin1[event->TaskIndex];
txPin = Settings.TaskDevicePin2[event->TaskIndex];
event->String1 = formatGpioName_input(F("SS RX");
event->String2 = formatGpioName_output(F("SS TX");
event->String1 = formatGpioName_RX(false);
event->String2 = formatGpioName_TX(false);
if(AdvHwSerial == true) {
if ((rxPin == 3 && txPin == 1) || (rxPin == 13 && txPin == 15)) {
event->String1 = formatGpioName_input(F("HW RX");
event->String2 = formatGpioName_output(F("HW TX");
event->String1 = formatGpioName_RX_HW(false);
event->String2 = formatGpioName_TX_HW(false);
}
}
break;
+8
View File
@@ -77,6 +77,14 @@ boolean Plugin_076(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_output("SEL");
event->String2 = formatGpioName_input("CF1");
event->String3 = formatGpioName_input("CF");
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNote(F("Sonoff POW: 1st(SEL)=GPIO-5, 2nd(CF1)=GPIO-13, 3rd(CF)=GPIO-14"));
+6
View File
@@ -84,6 +84,12 @@ boolean Plugin_077(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
// No pins selectable, all hard coded
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNumericBox(F("U Ref"), F("p077_URef"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
+6
View File
@@ -51,6 +51,12 @@ boolean Plugin_080(byte function, struct EventStruct * event, String& string)
break;
}
case PLUGIN_GET_DEVICEGPIONAMES:
{
event->String1 = formatGpioName_bidirectional(F("1-Wire"));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
uint8_t savedAddress[8];