Updated comments

Updated comments

--- hardware/arduino/avr/libraries/Bridge/examples/TimeCheck/TimeCheck.ino
+++ hardware/arduino/avr/libraries/Bridge/examples/TimeCheck/TimeCheck.ino
@@ -7,6 +7,7 @@
  using an Arduino Yun.

  created  27 May 2013
+ modified 17 June 2013
  By Tom Igoe
  */

@@ -28,9 +29,7 @@
   // run an initial date process. Should return:
   // hh:mm:ss :
   if (!date.running())  {
-    date.begin("date");
-    date.addParameter("+%T");
-    date.run();
+    date.runShellCommand("date +%T");
   }
 }

@@ -49,9 +48,7 @@

     // restart the date process:
     if (!date.running())  {
-      date.begin("date");
-      date.addParameter("+%T");
-      date.run();
+      date.runShellCommand("date +%T");
     }
   }

@@ -77,3 +74,4 @@
   }

 }
+


Update sketch_aug08a.ino

Update sketch_aug08a.ino

--- plane/TRANSMITTER/sketch_aug08a/sketch_aug08a.ino
+++ plane/TRANSMITTER/sketch_aug08a/sketch_aug08a.ino
@@ -6,6 +6,7 @@
 *
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
 */
+int value = 0; // set values you need to zero
 #include <SPI.h>
 #include <nRF24L01.h>
 #include <RF24.h>
@@ -13,12 +14,15 @@
 RF24 radio(7, 8); // CNS, CE
 const byte addresses[][6] = {"00001", "00002"};
 boolean buttonState = 0;
+    #define MAX_SIGNAL 2100
+    #define MIN_SIGNAL 700
 void setup() {
   pinMode(12, OUTPUT);
   radio.begin();
   radio.openWritingPipe(addresses[1]); // 00001
   radio.openReadingPipe(1, addresses[0]); // 00002
   radio.setPALevel(RF24_PA_MIN);
+  Serial.begin(115200);
 }
 void loop() {
   delay(5);
@@ -29,14 +33,10 @@
       int potValue1 = analogRead(A1);
       int angleValue1 = map(potValue1, 0, 1023, 0, 180);
       radio.write(&angleValue1, sizeof(angleValue1));
-  delay(5);
-  radio.startListening();
-  while (!radio.available());
-  radio.read(&buttonState, sizeof(buttonState));
-  if (buttonState == HIGH) {
-    digitalWrite(led, HIGH);
-  }
-  else {
-    digitalWrite(led, LOW);
-  }
+          int potValue2 = analogRead(A2);
+          int angleValue2 = map(potValue2, 0, 1023, MIN_SIGNAL, MAX_SIGNAL);
+          radio.write(&angleValue2, sizeof(angleValue2));
+           if(Serial.available())
+           value = Serial.parseInt();    // Parse an Integer from Serial
+           Serial.println(angleValue2);
 }


Changed message data type

Changed message data type

--- Temperature/Temperature.ino
+++ Temperature/Temperature.ino
@@ -11,16 +11,18 @@

 #include <Wire.h>
 #include <ros.h>
-#include <std_msgs/Float32.h>
+#include <std_msgs/String.h>

 #define SENSOR_COUNT 1
 #define TYPE_ANALOG 0
+#define ANALOG_PIN 0

 #define MAX_SAMPLE_RATE 10
 #define MAX_SAMPLE_COUNT 10
 #define MAX_DELTA 0.5

 typedef struct temperature_sensor {
+  unsigned int id;
   float prev_temp;
   float curr_temp;
   unsigned int type;
@@ -31,15 +33,18 @@
 } TemperatureSensor;

 const TemperatureSensor default_sensor {
-  0.0f, 0.0f, 0, 0, 0, 0, 0
+  0, 0.0f, 0.0f, 0, 0, 0, 0, 0
 };

-// Temperature Sensor Array
+// Temperature Sensor variables
 TemperatureSensor sensors[SENSOR_COUNT];
+static const String json_prefix = "{\"id\":";
+static const String json_middle = ",\"temperature\":";
+static const String json_suffix = "}";

 // ROS variables
 static ros::NodeHandle  nh;
-static std_msgs::Float32 temp_msg;
+static std_msgs::String temp_msg;
 static ros::Publisher pub_temp("temperature", &temp_msg);

 static void increment_sample_rate(TemperatureSensor* sensor) {
@@ -77,7 +82,8 @@
 static void handle_temp(TemperatureSensor* sensor) {
   if(abs(sensor->prev_temp - sensor->curr_temp) > MAX_DELTA) {
     sensor->prev_temp = sensor->curr_temp;
-    temp_msg.data = sensor->curr_temp;
+    String message = json_prefix + sensor->id + json_middle + sensor->curr_temp + json_suffix;
+    temp_msg.data = message.c_str();
     pub_temp.publish(&temp_msg);
   }
 }
@@ -89,6 +95,13 @@
   sensor->curr_temp = celsius;
 }

+static void create_sensor(unsigned int id, unsigned int address, unsigned int type, TemperatureSensor* sensor) {
+  *sensor = default_sensor;
+  sensor->id = id;
+  sensor->address = address;
+  sensor->type = type;
+}
+
 void setup()
 {
   nh.initNode();
@@ -96,9 +109,8 @@

   unsigned int sensor_count = 0;
   // Create analog temperature sensor
-  TemperatureSensor analog_sensor = default_sensor;
-  analog_sensor.address = 0;
-  analog_sensor.type = TYPE_ANALOG;
+  TemperatureSensor analog_sensor;
+  create_sensor(sensor_count, ANALOG_PIN, TYPE_ANALOG, &analog_sensor);
   sensors[sensor_count++] = analog_sensor;
 }


have all winter snow options available for quick use

--- init.ino
+++ init.ino
@@ -102,8 +102,9 @@

 	// thread_handler.queue(new Animation_Holiday_Halloween_WinAllHalloweenSparkle());

-	// thread_handler.queue(new Animation_Seasonal_Winter_WindowSnow(&window1));
-	// thread_handler.queue(new Animation_Seasonal_Winter_WindowSnow(&window3));
+	// thread_handler.queue(new Animation_Seasonal_Indiv_Winter_WindowSnow(&window1));
+	// thread_handler.queue(new Animation_Seasonal_Indiv_Winter_WindowSnow(&window2));
+	// thread_handler.queue(new Animation_Seasonal_Indiv_Winter_WindowSnow(&window3));

 	// thread_handler.queue(new Animation_Simple_Indiv_CalmPurpleFade(&window1));
 	// thread_handler.queue(new Animation_Simple_Indiv_CalmPurpleFade(&window2));


Update HASwitchPlate.ino

Update HASwitchPlate.ino

This pull request to to add a beep tone on screen press. This will help people to know that the button press was successful.
I have also added a MQTT command to allow invalid code tried it will beep a pattern. (once I get Yet another alarm system to update his code to allow this.)

Thanks

Ben

--- Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
+++ Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
@@ -82,6 +82,7 @@
 const unsigned long telnetInputMax = 128;           // Size of user input buffer for user telnet session
 bool motionEnabled = false;                         // Motion sensor is enabled
 bool mdnsEnabled = true;                            // mDNS enabled
+bool beepEnabled = true;
 uint8_t motionPin = 0;                              // GPIO input pin for motion sensor if connected and enabled
 bool motionActive = false;                          // Motion is being detected
 const unsigned long motionLatchTimeout = 30000;     // Latch time for motion sensor
@@ -107,6 +108,7 @@
 String mqttStatusTopic;                             // MQTT topic for publishing device connectivity state
 String mqttSensorTopic;                             // MQTT topic for publishing device information in JSON format
 String mqttLightCommandTopic;                       // MQTT topic for incoming panel backlight on/off commands
+String mqttBeepCommandTopic;                         // MQTT topic for error beep
 String mqttLightStateTopic;                         // MQTT topic for outgoing panel backlight on/off state
 String mqttLightBrightCommandTopic;                 // MQTT topic for incoming panel backlight dimmer commands
 String mqttLightBrightStateTopic;                   // MQTT topic for outgoing panel backlight dimmer state
@@ -137,6 +139,17 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 void setup()
 { // System setup
+
+  if (beepEnabled)
+  {
+    pinMode(4, OUTPUT);
+    beep(100);
+    beep(50);
+    beep(100);
+  }
+
+
+
   pinMode(nextionResetPin, OUTPUT);
   digitalWrite(nextionResetPin, HIGH);
   Serial.begin(115200);  // Serial - LCD RX (after swap), debug TX
@@ -300,6 +313,18 @@
 // Functions

 ////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void beep(unsigned char delayms){
+  analogWrite(4, 254);      // Almost any value can be used except 0 and 255
+                           // experiment to get the best tone
+  delay(delayms);          // wait for a delayms ms
+  analogWrite(4, 0);       // 0 turns it off
+  delay(delayms);          // wait for a delayms ms
+}
+
+
+
+
 void mqttConnect()
 { // MQTT connection and subscriptions

@@ -517,6 +542,12 @@
   { // '[...]/device/command/factoryreset' == clear all saved settings)
     configClearSaved();
   }
+  else if (strTopic == (mqttCommandTopic + "/beep") || strTopic == (mqttGroupCommandTopic + "/beep"))
+  { // '[...]/device/command/factoryreset' == clear all saved settings)
+    beep(1000);
+    beep(100);
+    beep(100);
+  }
   else if (strTopic.startsWith(mqttCommandTopic) && (strPayload == ""))
   { // '[...]/device/command/p[1].b[4].txt' -m '' == nextionGetAttr("p[1].b[4].txt")
     String subTopic = strTopic.substring(mqttCommandTopic.length() + 1);
@@ -674,6 +705,12 @@
       mqttClient.publish(mqttButtonTopic, "ON");
       String mqttButtonJSONEvent = String(F("{\"event\":\"p[")) + String(nextionPage) + String(F("].b[")) + String(nextionButtonID) + String(F("]\", \"value\":\"ON\"}"));
       mqttClient.publish(mqttStateJSONTopic, mqttButtonJSONEvent);
+      if (beepEnabled)
+      {
+        pinMode(4, OUTPUT);
+        beep(100);
+      }
+
     }
     if (nextionButtonAction == 0x00)
     {
@@ -1463,6 +1500,17 @@
               mdnsEnabled = false;
             }
           }
+          if (!configJson["beepEnabled"].isNull())
+          {
+            if (configJson["beepEnabled"])
+            {
+              beepEnabled = true;
+            }
+            else
+            {
+              beepEnabled = false;
+            }
+          }
           String configJsonStr;
           serializeJson(configJson, configJsonStr);
           debugPrintln(String(F("SPIFFS: parsed json:")) + configJsonStr);
@@ -1509,6 +1557,8 @@
   jsonConfigValues["debugSerialEnabled"] = debugSerialEnabled;
   jsonConfigValues["debugTelnetEnabled"] = debugTelnetEnabled;
   jsonConfigValues["mdnsEnabled"] = mdnsEnabled;
+  jsonConfigValues["beepEnabled"] = beepEnabled;
+

   debugPrintln(String(F("SPIFFS: mqttServer = ")) + String(mqttServer));
   debugPrintln(String(F("SPIFFS: mqttPort = ")) + String(mqttPort));
@@ -1522,6 +1572,7 @@
   debugPrintln(String(F("SPIFFS: debugSerialEnabled = ")) + String(debugSerialEnabled));
   debugPrintln(String(F("SPIFFS: debugTelnetEnabled = ")) + String(debugTelnetEnabled));
   debugPrintln(String(F("SPIFFS: mdnsEnabled = ")) + String(mdnsEnabled));
+  debugPrintln(String(F("SPIFFS: beepEnabled = ")) + String(beepEnabled));

   File configFile = SPIFFS.open("/config.json", "w");
   if (!configFile)
@@ -1632,13 +1683,8 @@
   {
     httpMessage += String(F(" selected"));
   }
-  httpMessage += String(F(">D1</option><option value='D2'"));
-  if (motionPin == D2)
-  {
-    httpMessage += String(F(" selected"));
-  }
-  httpMessage += String(F(">D2</option></select>"));
-
+  httpMessage += String(F(">D1</option></select>"));
+
   httpMessage += String(F("
Serial debug output enabled:<input id='debugSerialEnabled' name='debugSerialEnabled' type='checkbox'"));
   if (debugSerialEnabled)
   {
@@ -1654,7 +1700,17 @@
   {
     httpMessage += String(F(" checked='checked'"));
   }
+
+  httpMessage += String(F(">
Keypress beep enabled:<input id='beepEnabled' name='beepEnabled' type='checkbox'"));
+  if (beepEnabled)
+  {
+    httpMessage += String(F(" checked='checked'"));
+  }
+
+
+
   httpMessage += String(F(">

<button type='submit'>save settings</button></form>"));
+

   if (updateEspAvailable)
   {
@@ -1808,6 +1864,16 @@
   { // mdnsEnabled was enabled but should now be disabled
     shouldSaveConfig = true;
     mdnsEnabled = false;
+  }
+  if ((webServer.arg("beepEnabled") == String("on")) && !beepEnabled)
+  { // beepEnabled was disabled but should now be enabled
+    shouldSaveConfig = true;
+    beepEnabled = true;
+  }
+  else if ((webServer.arg("beepEnabled") == String("")) && beepEnabled)
+  { // beepEnabled was enabled but should now be disabled
+    shouldSaveConfig = true;
+    beepEnabled = false;
   }

   if (shouldSaveConfig)
@@ -2598,4 +2664,4 @@
       s[k++] = c;
   }
   s[k] = 0;
-}+}


Arduino sketch v0.2.1 bugfix and feature relase

--- Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
+++ Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
@@ -12,7 +12,7 @@
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 // and associated documentation files (the "Software"), to deal in the Software without restriction,
-// including without limitation the rights to use, copy, modify, merge, publish, distribute,
+// including without limitation the rights to use, copy, modify, merge, publish, distribute,
 // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
 //
@@ -26,19 +26,23 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 ////////////////////////////////////////////////////////////////////////////////////////////////////

-// Optional: Assign default values here.  These may be overwritten by saved values from config.json
-char mqttServer[40] = "";
+// OPTIONAL: Assign default values here.
+const char *wifiSSID = ""; // If WiFi details are set here, you will need to set all other values
+const char *wifiPass = ""; // below or via the web interface when the device starts
+////////////////////////////////////////////////////////////////////////////////////////////////////
+char mqttServer[64] = ""; // These may be overwritten by saved values from config.json
 char mqttPort[6] = "1883";
 char mqttUser[32] = "";
 char mqttPassword[32] = "";
 char haspNode[16] = "plate01";
-char otaPassword[32] = "OTA_Update_Password";
+char configUser[32] = "admin";
+char configPassword[32] = "hasp";
 ////////////////////////////////////////////////////////////////////////////////////////////////////

 // Serial debug output control, comment out to disable
 #define DEBUGSERIAL
 // Open a super-insecure (but read-only) telnet debug port
-#define DEBUGTELNET
+// #define DEBUGTELNET

 #include <FS.h>
 #include <ESP8266WiFi.h>
@@ -51,6 +55,7 @@
 #include <WiFiManager.h>
 #include <ArduinoJson.h>
 #include <MQTT.h>
+#include <EEPROM.h>

 #ifdef DEBUGTELNET
 WiFiServer telnetServer(23);
@@ -58,8 +63,9 @@
 #endif
 WiFiClient wifiClient;
 MQTTClient mqttClient(256);
-
-const char* haspVersion = "0.2.0";  // Current HASP software release version
+ESP8266WebServer webServer(80);
+
+const char *haspVersion = "0.2.1";  // Current HASP software release version
 byte nextionReturnBuffer[100];      // Byte array to pass around data coming from the panel
 uint8_t nextionReturnIndex = 0;     // Index for nextionReturnBuffer
 uint8_t nextionActivePage = 0;      // Track active LCD page
@@ -67,6 +73,7 @@
 char wifiConfigAP[19];              // AP config SSID, haspNode + 3 chars
 bool shouldSaveConfig = false;      // Flag to save json config to SPIFFS
 byte espMac[6];                     // Byte array to store our MAC address
+String mqttClientId;                // Auto-generated MQTT ClientID
 String mqttGetSubtopic;             // MQTT subtopic for incoming commands requesting .val
 String mqttStateTopic;              // MQTT topic for outgoing panel interactions
 String mqttCommandTopic;            // MQTT topic for incoming panel commands
@@ -75,18 +82,19 @@
 String mqttLightStateTopic;         // MQTT topic for outgoing panel backlight on/off state
 String mqttLightBrightCommandTopic; // MQTT topic for incoming panel backlight dimmer commands
 String mqttLightBrightStateTopic;   // MQTT topic for outgoing panel backlight dimmer state
+const char HASP_STYLE[] = "<style>button{background-color:slategray;}</style>";

 ////////////////////////////////////////////////////////////////////////////////////////////////////
 void setup()
 { // System setup
-
+  delay(1000);
   Serial.begin(115200);  // Serial - LCD RX (after swap), debug TX
   Serial1.begin(115200); // Serial1 - LCD TX, no RX
-  debugPrintln("\r\nHardware initialized, starting program load");
-
-  // If this ESP8266 has saved WiFi creds, you'll need to uncomment
-  // this command, flash to the device, let it run once, then
-  // comment it out again to clear out any previously saved config
+  debugPrintln(F("\r\nSYSTEM: Hardware initialized, starting program load"));
+
+  // If this ESP8266 has an older version of `config.json` saved to SPIFFS, you'll need to either
+  // wipe SPIFFS during flash or uncomment the following command, flash it, comment it out again,
+  // then flash again to clear out the local filesystem.
   // clearSavedConfig();

   initializeNextion(); // initialize display
@@ -94,13 +102,16 @@
   readSavedConfig(); // Check filesystem for a saved config.json
   setupWifi();       // Start up networking

-  if (otaPassword[0])
-  { // Start up OTA
-    setupOTA();
-  }
+  webServer.on("/", webHandleRoot);
+  webServer.on("/saveConfig", webHandleSaveConfig);
+  webServer.on("/resetConfig", webHandleResetConfig);
+  webServer.onNotFound(webHandleNotFound);
+  webServer.begin();
+  debugPrintln(String(F("HTTP: Server started @ http://")) + String(WiFi.localIP()));
+
+  setupOTA();

   // Create server and assign callbacks for MQTT
-  //mqttClient.begin(mqttServer, mqttPort, wifiClient);
   mqttClient.begin(mqttServer, atoi(mqttPort), wifiClient);
   mqttClient.onMessage(mqtt_callback);
   mqttConnect();
@@ -109,10 +120,10 @@
   // Setup telnet server for remote debug output
   telnetServer.begin();
   telnetServer.setNoDelay(true);
-  debugPrintln("telnetClient debug server enabled at telnet:" + WiFi.localIP().toString());
+  debugPrintln(String(F("TELNET: debug server enabled at telnet:")) + WiFi.localIP().toString());
 #endif

-  debugPrintln("Initialization complete, swapping debug serial output to D8\r\n");
+  debugPrintln(F("SYSTEM: Init complete, swapping debug serial output to D8\r\n"));
   Serial.swap();
 }

@@ -140,10 +151,10 @@
   // MQTT client loop
   mqttClient.loop();

-  if (otaPassword[0])
-  { // OTA loop
-    ArduinoOTA.handle();
-  }
+  ArduinoOTA.handle();
+
+  // webServer loop
+  webServer.handleClient();

 #ifdef DEBUGTELNET
   // telnetClient loop
@@ -170,7 +181,7 @@
   // '[...]/device/command/p[1].b[4].txt' -m '' = getNextionAttr("p[1].b[4].txt")
   // '[...]/device/command/p[1].b[4].txt' -m '"Lights On"' = setNextionAttr("p[1].b[4].txt", "\"Lights On\"")

-  debugPrintln("MQTT IN:  '" + strTopic + "' : '" + strPayload + "'");
+  debugPrintln(String(F("MQTT IN:  '")) + strTopic + "' : '" + strPayload + "'");

   if ((strTopic == mqttCommandTopic) && (strPayload == ""))
   { // '[...]/device/command' -m '' = undefined
@@ -236,7 +247,7 @@
   Serial1.print(hmi_value);
   Serial1.write(nextionSuffix, sizeof(nextionSuffix));
   Serial1.flush();
-  debugPrintln("HMI OUT:  '" + hmi_attribute + "=" + hmi_value + "'");
+  debugPrintln(String(F("HMI OUT:  '")) + hmi_attribute + "=" + hmi_value + "'");
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -248,7 +259,7 @@
   Serial1.print("get " + hmi_attribute);
   Serial1.write(nextionSuffix, sizeof(nextionSuffix));
   Serial1.flush();
-  debugPrintln("HMI OUT:  'get " + hmi_attribute + "'");
+  debugPrintln(String(F("HMI OUT:  'get ")) + hmi_attribute + "'");
   processNextionInput();
 }

@@ -259,7 +270,7 @@
   Serial1.print(nexcmd);
   Serial1.write(nextionSuffix, sizeof(nextionSuffix));
   Serial1.flush();
-  debugPrintln("HMI OUT:  " + nexcmd);
+  debugPrintln(String(F("HMI OUT:  ")) + nexcmd);
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -337,16 +348,16 @@

     if (nextionButtonAction == 0x01)
     {
-      debugPrintln("HMI IN:   [Button ON] 'p[" + nextionPage + "].b[" + nextionButtonID + "]'");
+      debugPrintln(String(F("HMI IN:   [Button ON] 'p[")) + nextionPage + "].b[" + nextionButtonID + "]'");
       String mqttButtonTopic = mqttStateTopic + "/p[" + nextionPage + "].b[" + nextionButtonID + "]";
-      debugPrintln("MQTT OUT: '" + mqttButtonTopic + "' : 'ON'");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttButtonTopic + "' : 'ON'");
       mqttClient.publish(mqttButtonTopic, "ON");
     }
     if (nextionButtonAction == 0x00)
     {
-      debugPrintln("HMI IN:   [Button OFF] 'p[" + nextionPage + "].b[" + nextionButtonID + "]'");
+      debugPrintln(String(F("HMI IN:   [Button OFF] 'p[")) + nextionPage + "].b[" + nextionButtonID + "]'");
       String mqttButtonTopic = mqttStateTopic + "/p[" + nextionPage + "].b[" + nextionButtonID + "]";
-      debugPrintln("MQTT OUT: '" + mqttButtonTopic + "' : 'OFF'");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttButtonTopic + "' : 'OFF'");
       mqttClient.publish(mqttButtonTopic, "OFF");
       // Now see if this object has a .val that might have been updated.
       // works for sliders, two-state buttons, etc, throws a 0x1A error for normal buttons
@@ -361,12 +372,12 @@
     // Example: 0x66 0x02 0xFF 0xFF 0xFF
     // Meaning: page 2
     String nextionPage = String(nextionReturnBuffer[1]);
-    debugPrintln("HMI IN:   [sendme Page] '" + nextionPage + "'");
+    debugPrintln(String(F("HMI IN:   [sendme Page] '")) + nextionPage + "'");
     if (nextionActivePage != nextionPage.toInt())
     {
       nextionActivePage = nextionPage.toInt();
       String mqttPageTopic = mqttStateTopic + "/page";
-      debugPrintln("MQTT OUT: '" + mqttPageTopic + "' : '" + nextionPage + "'");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttPageTopic + "' : '" + nextionPage + "'");
       mqttClient.publish(mqttPageTopic, nextionPage);
     }
   }
@@ -384,16 +395,16 @@
     byte nextionTouchAction = nextionReturnBuffer[5];
     if (nextionTouchAction == 0x01)
     {
-      debugPrintln("HMI IN:   [Touch ON] '" + xyCoord + "'");
+      debugPrintln(String(F("HMI IN:   [Touch ON] '")) + xyCoord + "'");
       String mqttTouchTopic = mqttStateTopic + "/touchOn";
-      debugPrintln("MQTT OUT: '" + mqttTouchTopic + "' : '" + xyCoord + "'");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttTouchTopic + "' : '" + xyCoord + "'");
       mqttClient.publish(mqttTouchTopic, xyCoord);
     }
     else if (nextionTouchAction == 0x00)
     {
-      debugPrintln("HMI IN:   [Touch OFF] '" + xyCoord + "'");
+      debugPrintln(String(F("HMI IN:   [Touch OFF] '")) + xyCoord + "'");
       String mqttTouchTopic = mqttStateTopic + "/touchOff";
-      debugPrintln("MQTT OUT: '" + mqttTouchTopic + "' : '" + xyCoord + "'");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttTouchTopic + "' : '" + xyCoord + "'");
       mqttClient.publish(mqttTouchTopic, xyCoord);
     }
   }
@@ -407,16 +418,16 @@
     { // convert the payload into a string
       getString += (char)nextionReturnBuffer[i];
     }
-    debugPrintln("HMI IN:   [String Return] '" + getString + "'");
+    debugPrintln(String(F("HMI IN:   [String Return] '")) + getString + "'");
     if (mqttGetSubtopic == "")
     { // If there's no outstanding request for a value, publish to mqttStateTopic
-      debugPrintln("MQTT OUT: '" + mqttStateTopic + "' : '" + getString + "]");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttStateTopic + "' : '" + getString + "]");
       mqttClient.publish(mqttStateTopic, getString);
     }
     else
     { // Otherwise, publish the to saved mqttGetSubtopic and then reset mqttGetSubtopic
       String mqttReturnTopic = mqttStateTopic + mqttGetSubtopic;
-      debugPrintln("MQTT OUT: '" + mqttReturnTopic + "' : '" + getString + "]");
+      debugPrintln(String(F("MQTT OUT: '")) + mqttReturnTopic + "' : '" + getString + "]");
       mqttClient.publish(mqttReturnTopic, getString);
       mqttGetSubtopic = "";
     }
@@ -431,7 +442,7 @@
     getInt = getInt * 256 + nextionReturnBuffer[2];
     getInt = getInt * 256 + nextionReturnBuffer[1];
     String getString = String(getInt);
-    debugPrintln("HMI IN:   [Int Return] '" + getString + "'");
+    debugPrintln(String(F("HMI IN:   [Int Return] '")) + getString + "'");
     // If there's no outstanding request for a value, publish to mqttStateTopic
     if (mqttGetSubtopic == "")
     {
@@ -461,85 +472,102 @@
   sendNextionCmd("page 0");
   setNextionAttr("p[0].b[1].txt", "\"WiFi connecting\"");

-  // The extra parameters to be configured (can be either global or just in the setup)
-  // After connecting, parameter.getValue() will get you the configured value
-  // id/name placeholder/prompt default length
-  WiFiManagerParameter custom_mqttServer("server", "mqtt server", mqttServer, 40);
-  WiFiManagerParameter custom_mqttPort("port", "mqtt port", mqttPort, 6);
-  WiFiManagerParameter custom_mqttUser("user", "mqtt user", mqttUser, 32);
-  WiFiManagerParameter custom_mqttPassword("password", "mqtt password", mqttPassword, 32);
-  WiFiManagerParameter custom_haspNode("node", "HASP node", haspNode, 16);
-  WiFiManagerParameter custom_otaPassword("password", "OTA password", otaPassword, 32);
-
-  // WiFiManager local intialization. Once its business is done, there is no need to keep it around
-  WiFiManager wifiManager;
-
-  // set config save notify callback
-  wifiManager.setSaveConfigCallback(saveConfigCallback);
-
-  // Set client static ip
-  // wifiManager.setSTAStaticIPConfig(IPAddress(10, 0, 1, 99), IPAddress(10, 0, 1, 1), IPAddress(255, 255, 255, 0));
-
-  // Add all your parameters here
-  wifiManager.addParameter(&custom_mqttServer);
-  wifiManager.addParameter(&custom_mqttPort);
-  wifiManager.addParameter(&custom_mqttUser);
-  wifiManager.addParameter(&custom_mqttPassword);
-  wifiManager.addParameter(&custom_haspNode);
-  wifiManager.addParameter(&custom_otaPassword);
-
-  // Set minimum quality of signal so it ignores AP's under that quality. Defaults to 8%
-  //wifiManager.setMinimumSignalQuality();
-
-  // Timeout until configuration portal gets turned off
-  wifiManager.setTimeout(180);
-
-  wifiManager.setAPCallback(wifiConfigCallback);
-
   // Read our MAC address and save it to espMac
   WiFi.macAddress(espMac);
-
-  // Construct AP name as haspNode-byte[5] of mac
-  String strWifiConfigAP = String(haspNode) + "-" + String(espMac[5], HEX);
-  strWifiConfigAP.toCharArray(wifiConfigAP, (strWifiConfigAP.length() + 1));
-  // Construct a WiFi SSID password using bytes [3] and [4] of our MAC
-  String strConfigPass = "hasp" + String(espMac[3], HEX) + String(espMac[4], HEX);
-  strConfigPass.toCharArray(wifiConfigPass, 9);
-
-  // Fetches SSID and pass from EEPROM and tries to connect
-  // If it does not connect it starts an access point with the specified name
-  // and goes into a blocking loop awaiting configuration.
-  if (!wifiManager.autoConnect(wifiConfigAP, wifiConfigPass))
-  { // Reset and try again
-    debugPrintln("WIFI: Failed to connect and hit timeout");
-    delay(3000);
-    ESP.reset();
-    delay(5000);
-  }
-
-  // If you get here you have connected to the WiFi
-  debugPrintln("WIFI: Connected succesfully and assigned IP: " + WiFi.localIP().toString());
+  // Assign our hostname before connecting to WiFi
+  WiFi.hostname(String(haspNode));
+
+  debugPrintln("configPassword: [" + String(configPassword) + "]");
+
+  if (String(wifiSSID) == "")
+  { // If the sketch has no defined a static wifiSSID to connect to,
+    // use WiFiManager to collect required information from the user.
+
+    // id/name, placeholder/prompt, default value, length, extra tags
+    WiFiManagerParameter custom_mqttServer("mqttServer", "MQTT Server (required)", mqttServer, 63, " maxlength=39 required");
+    WiFiManagerParameter custom_mqttPort("mqttPort", "MQTT Port (required)", mqttPort, 5, " maxlength=5 type='number' required");
+    WiFiManagerParameter custom_mqttUser("mqttUser", "MQTT User (optional)", mqttUser, 31, " maxlength=31");
+    WiFiManagerParameter custom_mqttPassword("mqttPassword", "MQTT Password (optional)", mqttPassword, 31, " maxlength=31 type='password'");
+    WiFiManagerParameter custom_haspNode("haspNode", "HASP Node (required)", haspNode, 15, " maxlength=15 required");
+    WiFiManagerParameter custom_configUser("configUser", "Config User (optional)", configUser, 15, " maxlength=31'");
+    WiFiManagerParameter custom_configPassword("configPassword", "Config Password (optional)", configPassword, 31, " maxlength=31 type='password'");
+
+    // WiFiManager local intialization. Once its business is done, there is no need to keep it around
+    WiFiManager wifiManager;
+
+    // set config save notify callback
+    wifiManager.setSaveConfigCallback(saveConfigCallback);
+
+    wifiManager.setCustomHeadElement(HASP_STYLE);
+
+    // Add all your parameters here
+    wifiManager.addParameter(&custom_mqttServer);
+    wifiManager.addParameter(&custom_mqttPort);
+    wifiManager.addParameter(&custom_mqttUser);
+    wifiManager.addParameter(&custom_mqttPassword);
+    wifiManager.addParameter(&custom_haspNode);
+    wifiManager.addParameter(&custom_configUser);
+    wifiManager.addParameter(&custom_configPassword);
+
+    // Timeout until configuration portal gets turned off
+    wifiManager.setTimeout(180);
+
+    wifiManager.setAPCallback(wifiConfigCallback);
+
+    // Construct AP name as haspNode-byte[5] of mac
+    String strWifiConfigAP = String(haspNode) + "-" + String(espMac[5], HEX);
+    strWifiConfigAP.toCharArray(wifiConfigAP, (strWifiConfigAP.length() + 1));
+    // Construct a WiFi SSID password using bytes [3] and [4] of our MAC
+    String strConfigPass = "hasp" + String(espMac[3], HEX) + String(espMac[4], HEX);
+    strConfigPass.toCharArray(wifiConfigPass, 9);
+
+    // Fetches SSID and pass from EEPROM and tries to connect
+    // If it does not connect it starts an access point with the specified name
+    // and goes into a blocking loop awaiting configuration.
+    if (!wifiManager.autoConnect(wifiConfigAP, wifiConfigPass))
+    { // Reset and try again
+      debugPrintln(F("WIFI: Failed to connect and hit timeout"));
+      delay(2000);
+      ESP.reset();
+      delay(5000);
+    }
+
+    // Read updated parameters
+    strcpy(mqttServer, custom_mqttServer.getValue());
+    strcpy(mqttPort, custom_mqttPort.getValue());
+    strcpy(mqttUser, custom_mqttUser.getValue());
+    strcpy(mqttPassword, custom_mqttPassword.getValue());
+    strcpy(haspNode, custom_haspNode.getValue());
+    strcpy(configUser, custom_configUser.getValue());
+    strcpy(configPassword, custom_configPassword.getValue());
+
+    if (shouldSaveConfig)
+    { // Save the custom parameters to FS
+      saveUpdatedConfig();
+    }
+  }
+  else
+  { // wifiSSID has been defined in the sketch, so attempt to connect to it forever
+    debugPrintln(String(F("Connecting to WiFi network: ")) + String(wifiSSID));
+    WiFi.hostname(haspNode);
+    WiFi.mode(WIFI_STA);
+    WiFi.begin(wifiSSID, wifiPass);
+
+    while (WiFi.status() != WL_CONNECTED)
+    {
+      delay(500);
+    }
+  }
+  // If you get here you have connected to WiFi
+  debugPrintln(String(F("WIFI: Connected succesfully and assigned IP: ")) + WiFi.localIP().toString());
   String nextionPageRestore = "page " + String(nextionActivePage);
   sendNextionCmd(nextionPageRestore);
-
-  // Read updated parameters
-  strcpy(mqttServer, custom_mqttServer.getValue());
-  strcpy(mqttPort, custom_mqttPort.getValue());
-  strcpy(mqttUser, custom_mqttUser.getValue());
-  strcpy(mqttPassword, custom_mqttPassword.getValue());
-  strcpy(haspNode, custom_haspNode.getValue());
-  strcpy(otaPassword, custom_otaPassword.getValue());
-
-  if (shouldSaveConfig)
-  { // Save the custom parameters to FS
-    saveUpdatedConfig();
-  }
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
 void wifiConfigCallback(WiFiManager *myWiFiManager)
 { // Notify the user that we're entering config mode
-  debugPrintln("WIFI: Failed to connect to assigned AP, entering config mode");
+  debugPrintln(F("WIFI: Failed to connect to assigned AP, entering config mode"));
   sendNextionCmd("page 0");
   setNextionAttr("p[0].b[1].txt", "\"Configure HASP\\r\\rAP:" + String(wifiConfigAP) + "\\rPass:" + String(wifiConfigPass) + "\"");
 }
@@ -564,10 +592,10 @@
   while (!mqttClient.connected())
   {
     // Generate an MQTT client ID as haspNode + our MAC address
-    String mqttClientId = String(haspNode) + "-" + String(espMac[0], HEX) + String(espMac[1], HEX) + String(espMac[2], HEX) + String(espMac[3], HEX) + String(espMac[4], HEX) + String(espMac[5], HEX);
+    mqttClientId = String(haspNode) + "-" + String(espMac[0], HEX) + String(espMac[1], HEX) + String(espMac[2], HEX) + String(espMac[3], HEX) + String(espMac[4], HEX) + String(espMac[5], HEX);
     sendNextionCmd("page 0");
     setNextionAttr("p[0].b[1].txt", "\"WiFi connected\\r" + WiFi.localIP().toString() + "\\rMQTT Connecting\"");
-    debugPrintln("Attempting MQTT connection to broker " + String(mqttServer) + " as clientID " + mqttClientId);
+    debugPrintln(String(F("MQTT: Attempting connection to broker ")) + String(mqttServer) + " as clientID " + mqttClientId);

     // Set keepAlive, cleanSession, timeout
     mqttClient.setOptions(5, true, 5000);
@@ -580,39 +608,37 @@
       // Subscribe to our incoming topics
       if (mqttClient.subscribe(mqttCommandSubscription))
       {
-        debugPrintln("MQTT: subscribed to " + mqttCommandSubscription);
+        debugPrintln(String(F("MQTT: subscribed to ")) + mqttCommandSubscription);
       }
       if (mqttClient.subscribe(mqttLightSubscription))
       {
-        debugPrintln("MQTT: subscribed to " + mqttLightSubscription);
+        debugPrintln(String(F("MQTT: subscribed to ")) + mqttLightSubscription);
       }
       if (mqttClient.subscribe(mqttLightBrightSubscription))
       {
-        debugPrintln("MQTT: subscribed to " + mqttLightSubscription);
-      }
-
-      debugPrintln("MQTT: binary_sensor state: [" + mqttBinarySensorStateTopic + "] : [ON]");
+        debugPrintln(String(F("MQTT: subscribed to ")) + mqttLightSubscription);
+      }
+
+      debugPrintln(String(F("MQTT: binary_sensor state: [")) + mqttBinarySensorStateTopic + "] : [ON]");
       mqttClient.publish(mqttBinarySensorStateTopic, "ON", true, 1);

       // Update panel with MQTT status
       setNextionAttr("p[0].b[1].txt", "\"WiFi connected\\r" + WiFi.localIP().toString() + "\\rMQTT Connected\\r" + String(mqttServer) + "\"");
-      debugPrintln("MQTT: connected");
+      debugPrintln(F("MQTT: connected"));
       String nextionPageRestore = "page " + String(nextionActivePage);
       sendNextionCmd(nextionPageRestore);
     }
     else
     { // Wait 15 seconds before retrying
-      debugPrintln("MQTT connection failed, rc=" + String(mqttClient.returnCode()) + ".  Trying again in 15 seconds.");
+      debugPrintln(String(F("MQTT connection failed, rc=")) + String(mqttClient.returnCode()) + String(F(".  Trying again in 15 seconds.")));
       delay(1000);
       unsigned long mqttReconnectTimeout = 15000;  // timeout for MQTT reconnect
       unsigned long mqttReconnectTimer = millis(); // record current time for our timeout
       while ((millis() - mqttReconnectTimer) < mqttReconnectTimeout)
-      { // Handle OTA while we're waiting for MQTT to reconnect
+      { // Handle HTTP and OTA while we're waiting for MQTT to reconnect
         yield();
-        if (otaPassword[0])
-        {
-          ArduinoOTA.handle();
-        }
+        webServer.handleClient();
+        ArduinoOTA.handle();
       }
     }
   }
@@ -623,35 +649,35 @@
 { // (mostly) boilerplate OTA setup from library examples

   ArduinoOTA.setHostname(haspNode);
-  ArduinoOTA.setPassword(otaPassword);
+  ArduinoOTA.setPassword(configPassword);

   ArduinoOTA.onStart([]() {
-    debugPrintln("ESP OTA:  update start");
+    debugPrintln(F("ESP OTA: update start"));
     sendNextionCmd("page 0");
     setNextionAttr("p[0].b[1].txt", "\"ESP OTA Update\"");
   });
   ArduinoOTA.onEnd([]() {
-    debugPrintln("ESP OTA:  update complete");
+    debugPrintln(F("ESP OTA: update complete"));
     setNextionAttr("p[0].b[1].txt", "\"ESP OTA Update\\rComplete!\"");
   });
   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
     setNextionAttr("p[0].b[1].txt", "\"ESP OTA Update\\rProgress: " + String(progress / (total / 100)) + "%\"");
   });
   ArduinoOTA.onError([](ota_error_t error) {
-    debugPrintln("ESP OTA:  ERROR code " + String(error));
+    debugPrintln(String(F("ESP OTA: ERROR code ")) + String(error));
     if (error == OTA_AUTH_ERROR)
-      debugPrintln("ESP OTA:  ERROR - Auth Failed");
+      debugPrintln(F("ESP OTA: ERROR - Auth Failed"));
     else if (error == OTA_BEGIN_ERROR)
-      debugPrintln("ESP OTA:  ERROR - Begin Failed");
+      debugPrintln(F("ESP OTA: ERROR - Begin Failed"));
     else if (error == OTA_CONNECT_ERROR)
-      debugPrintln("ESP OTA:  ERROR - Connect Failed");
+      debugPrintln(F("ESP OTA: ERROR - Connect Failed"));
     else if (error == OTA_RECEIVE_ERROR)
-      debugPrintln("ESP OTA:  ERROR - Receive Failed");
+      debugPrintln(F("ESP OTA: ERROR - Receive Failed"));
     else if (error == OTA_END_ERROR)
-      debugPrintln("ESP OTA:  ERROR - End Failed");
+      debugPrintln(F("ESP OTA: ERROR - End Failed"));
   });
   ArduinoOTA.begin();
-  debugPrintln("ESP OTA:  Over the Air firmware update ready");
+  debugPrintln(F("ESP OTA: Over the Air firmware update ready"));
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -670,45 +696,45 @@
   int total = 0;
   int pCent = 0;

-  debugPrintln("LCD OTA: Attempting firmware download from:" + otaURL);
+  debugPrintln(String(F("LCD OTA: Attempting firmware download from:")) + otaURL);
   HTTPClient http;
   http.begin(otaURL);
   int httpCode = http.GET();
   if (httpCode > 0)
   { // HTTP header has been send and Server response header has been handled
-    debugPrintln("LCD OTA: HTTP GET return code:" + String(httpCode));
+    debugPrintln(String(F("LCD OTA: HTTP GET return code:")) + String(httpCode));
     if (httpCode == HTTP_CODE_OK)
     { // file found at server
       // get length of document (is -1 when Server sends no Content-Length header)
       int len = http.getSize();
       FileSize = len;
       int Parts = (len / 4096) + 1;
-      debugPrintln("LCD OTA: File found at Server. Size " + String(len) + " bytes in " + String(Parts) + " 4k chunks.");
+      debugPrintln(String(F("LCD OTA: File found at Server. Size ")) + String(len) + String(F(" bytes in ")) + String(Parts) + String(F(" 4k chunks.")));
       // create buffer for read
       uint8_t buff[128] = {};
       // get tcp stream
       WiFiClient *stream = http.getStreamPtr();

-      debugPrintln("LCD OTA: Issuing NULL command");
+      debugPrintln(F("LCD OTA: Issuing NULL command"));
       Serial1.write(nextionSuffix, sizeof(nextionSuffix));
       handleNextionInput();

       String nexcmd = "whmi-wri " + String(FileSize) + ",115200,0";
-      debugPrintln("LCD OTA: Sending LCD upload command: " + nexcmd);
+      debugPrintln(String(F("LCD OTA: Sending LCD upload command: ")) + nexcmd);
       Serial1.print(nexcmd);
       Serial1.write(nextionSuffix, sizeof(nextionSuffix));
       Serial1.flush();

       if (otaReturnSuccess())
       {
-        debugPrintln("LCD OTA: LCD upload command accepted");
+        debugPrintln(F("LCD OTA: LCD upload command accepted"));
       }
       else
       {
-        debugPrintln("LCD OTA: LCD upload command FAILED.");
+        debugPrintln(F("LCD OTA: LCD upload command FAILED."));
         return;
       }
-      debugPrintln("LCD OTA: Starting update");
+      debugPrintln(F("LCD OTA: Starting update"));
       while (http.connected() && (len > 0 || len == -1))
       { // Write incoming data to panel as it arrives
         // get available data size
@@ -730,11 +756,11 @@
             count = 0;
             if (otaReturnSuccess())
             {
-              debugPrintln("LCD OTA: Part " + String(partNum) + " OK, " + String(pCent) + "% complete");
+              debugPrintln(String(F("LCD OTA: Part ")) + String(partNum) + String(F(" OK, ")) + String(pCent) + String(F("% complete")));
             }
             else
             {
-              debugPrintln("LCD OTA: Part " + String(partNum) + " FAILED, " + String(pCent) + "% complete");
+              debugPrintln(String(F("LCD OTA: Part ")) + String(partNum) + String(F(" FAILED, ")) + String(pCent) + String(F("% complete")));
             }
           }
           if (len > 0)
@@ -747,19 +773,20 @@
       total += count;
       if ((total == FileSize) && otaReturnSuccess())
       {
-        debugPrintln("LCD OTA: success, wrote " + String(total) + " of " + String(FileSize) + " bytes.");
+        debugPrintln(String(F("LCD OTA: success, wrote ")) + String(total) + " of " + String(FileSize) + " bytes.");
         delay(2000);
         ESP.reset();
+        delay(5000);
       }
       else
       {
-        debugPrintln("LCD OTA: failure");
+        debugPrintln(F("LCD OTA: failure"));
       }
     }
   }
   else
   {
-    debugPrintln("LCD OTA: HTTP GET failed, error code " + http.errorToString(httpCode));
+    debugPrintln(String(F("LCD OTA: HTTP GET failed, error code ")) + http.errorToString(httpCode));
   }
   http.end();
 }
@@ -827,80 +854,82 @@
 { // Read saved config.json from SPIFFS

   // Read configuration from FS json
-  debugPrintln("SPIFFS: mounting FS...");
+  debugPrintln(F("SPIFFS: mounting FS..."));

   if (SPIFFS.begin())
   {
-    debugPrintln("SPIFFS: mounted file system");
+    debugPrintln(F("SPIFFS: mounted file system"));
     if (SPIFFS.exists("/config.json"))
     {
       // File exists, reading and loading
-      debugPrintln("SPIFFS: reading config file");
+      debugPrintln(F("SPIFFS: reading config file"));
       File configFile = SPIFFS.open("/config.json", "r");
       if (configFile)
       {
-        debugPrintln("SPIFFS: opened config file");
+        debugPrintln(F("SPIFFS: opened config file"));
         size_t size = configFile.size();
         // Allocate a buffer to store contents of the file.
         std::unique_ptr<char[]> buf(new char[size]);

         configFile.readBytes(buf.get(), size);
-        DynamicJsonBuffer jsonBuffer;
+        DynamicJsonBuffer jsonBuffer(256);
         JsonObject &json = jsonBuffer.parseObject(buf.get());
         //json.printTo(Serial);
         if (json.success())
         {
-          debugPrintln("SPIFFS: parsed json");
           strcpy(mqttServer, json["mqttServer"]);
           strcpy(mqttPort, json["mqttPort"]);
           strcpy(mqttUser, json["mqttUser"]);
           strcpy(mqttPassword, json["mqttPassword"]);
           strcpy(haspNode, json["haspNode"]);
-          strcpy(otaPassword, json["otaPassword"]);
+          strcpy(configUser, json["configUser"]);
+          strcpy(configPassword, json["configPassword"]);
+          String jsonStr;
+          json.printTo(jsonStr);
+          debugPrintln(String(F("SPIFFS: parsed json:")) + jsonStr);
         }
         else
         {
-          debugPrintln("SPIFFS: [ERROR] Failed to load json config");
+          debugPrintln(F("SPIFFS: [ERROR] Failed to load json config"));
         }
       }
     }
   }
   else
   {
-    debugPrintln("SPIFFS: [ERROR] Failed to mount FS");
+    debugPrintln(F("SPIFFS: [ERROR] Failed to mount FS"));
   }
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
 void saveConfigCallback()
 { // Callback notifying us of the need to save config
-  debugPrintln("SPIFFS: Configuration changed, flagging for save");
+  debugPrintln(F("SPIFFS: Configuration changed, flagging for save"));
   shouldSaveConfig = true;
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
 void saveUpdatedConfig()
 { // Save the custom parameters to config.json
-  debugPrintln("SPIFFS: Saving config");
-  DynamicJsonBuffer jsonBuffer;
+  debugPrintln(F("SPIFFS: Saving config"));
+  DynamicJsonBuffer jsonBuffer(256);
   JsonObject &json = jsonBuffer.createObject();
   json["mqttServer"] = mqttServer;
   json["mqttPort"] = mqttPort;
   json["mqttUser"] = mqttUser;
   json["mqttPassword"] = mqttPassword;
   json["haspNode"] = haspNode;
-  json["otaPassword"] = otaPassword;
+  json["configUser"] = configUser;
+  json["configPassword"] = configPassword;

   File configFile = SPIFFS.open("/config.json", "w");
   if (!configFile)
   {
-    debugPrintln("SPIFFS: Failed to open config file for writing");
-  }
-
-  // json.printTo(Serial);
+    debugPrintln(F("SPIFFS: Failed to open config file for writing"));
+  }
   json.printTo(configFile);
   configFile.close();
-  //end save
+  shouldSaveConfig = false;
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -908,14 +937,213 @@
 { // Clear out all local storage
   sendNextionCmd("page 0");
   setNextionAttr("p[0].b[1].txt", "\"Resetting\\rsystem...\"");
-  debugPrintln("RESET: Formatting SPIFFS");
+  debugPrintln(F("RESET: Formatting SPIFFS"));
   SPIFFS.format();
-  debugPrintln("RESET: Clearing WiFiManager settings...");
+  debugPrintln(F("RESET: Clearing WiFiManager settings..."));
   WiFiManager wifiManager;
   wifiManager.resetSettings();
+  EEPROM.begin(512);
+  debugPrintln(F("Clearing EEPROM..."));
+  for (int i = 0; i < EEPROM.length(); i++)
+  {
+    EEPROM.write(i, 0);
+  }
   setNextionAttr("p[0].b[1].txt", "\"Rebooting\\rsystem...\"");
-  debugPrintln("RESET: Rebooting device");
+  debugPrintln(F("RESET: Rebooting device"));
+  delay(2000);
   ESP.reset();
+  delay(5000);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void webHandleNotFound()
+{ // webSevrer 404
+  String httpMessage = "File Not Found\n\n";
+  httpMessage += "URI: ";
+  httpMessage += webServer.uri();
+  httpMessage += "\nMethod: ";
+  httpMessage += (webServer.method() == HTTP_GET) ? "GET" : "POST";
+  httpMessage += "\nArguments: ";
+  httpMessage += webServer.args();
+  httpMessage += "\n";
+  for (uint8_t i = 0; i < webServer.args(); i++)
+  {
+    httpMessage += " " + webServer.argName(i) + ": " + webServer.arg(i) + "\n";
+  }
+  webServer.send(404, "text/plain", httpMessage);
+  debugPrintln(httpMessage);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void webHandleRoot()
+{ // webServer root
+  if (String(configPassword) != "")
+  { //Request HTTP auth if configPassword is set
+    if (!webServer.authenticate(configUser, configPassword))
+    {
+      return webServer.requestAuthentication();
+    }
+  }
+
+  String httpMessage = FPSTR(HTTP_HEAD);
+  httpMessage.replace("{v}", String(haspNode));
+  httpMessage += FPSTR(HTTP_SCRIPT);
+  httpMessage += FPSTR(HTTP_STYLE);
+  httpMessage += String(HASP_STYLE);
+  httpMessage += FPSTR(HTTP_HEAD_END);
+  httpMessage += String(F("<h1>"));
+  httpMessage += String(haspNode);
+  httpMessage += String(F("</h1>"));
+
+  httpMessage += String(F("<form method='get' action='saveConfig'>"));
+  httpMessage += String(F("<br/><b>MQTT Server</b> <i><small>(required)</small></i><input id='mqttServer' required name='mqttServer' maxlength=63 placeholder='mqttServer' value='")) + String(mqttServer) + "'>";
+  httpMessage += String(F("<br/><b>MQTT Port</b> <i><small>(required)</small></i><input id='mqttPort' required name='mqttPort' type='number' maxlength=5 placeholder='mqttPort' value='")) + String(mqttPort) + "'>";
+  httpMessage += String(F("<br/><b>MQTT User</b> <i><small>(optional)</small></i><input id='mqttUser' name='mqttUser' maxlength=31 placeholder='mqttUser' value='")) + String(mqttUser) + "'>";
+  httpMessage += String(F("<br/><b>MQTT Password</b> <i><small>(optional)</small></i><input id='mqttPassword' name='mqttPassword' type='password' maxlength=31 placeholder='mqttPassword'>"));
+  httpMessage += String(F("<br/><br/><b>HASP Node Name</b> <i><small>(required)</small></i><input id='haspNode' required name='haspNode' maxlength=15 placeholder='haspNode' value='")) + String(haspNode) + "'>";
+  httpMessage += String(F("<br/><br/><b>HASP Admin Username</b> <i><small>(optional)</small></i><input id='configUser' name='configUser' maxlength=31 placeholder='configUser' value='")) + String(configUser) + "'>";
+  httpMessage += String(F("<br/><b>HASP Admin Password</b> <i><small>(optional)</small></i><input id='configPassword' name='configPassword' type='password' maxlength=31>"));
+  httpMessage += String(F("<br/><br/><button type='submit'>save settings</button></form>"));
+
+  httpMessage += String(F("<br/><hr><br/><form method='get' action='resetConfig'>"));
+  httpMessage += String(F("<button type='submit'>factory reset settings</button></form>"));
+
+  httpMessage += String(F("<br/><hr><br/><b>MQTT Status: </b>"));
+  if (mqttClient.connected())
+  { // Check MQTT connection
+    httpMessage += String(F("Connected"));
+  }
+  else
+  {
+    httpMessage += String(F("<font color='red'><b>Disconnected</b></font>, return code: ")) + String(mqttClient.returnCode());
+  }
+  httpMessage += String(F("<br/><b>MQTT ClientID: </b>")) + String(mqttClientId);
+  httpMessage += String(F("<br/><b>HASP Version: </b>")) + String(haspVersion);
+  httpMessage += String(F("<br/><b>LCD Active Page: </b>")) + String(nextionActivePage);
+  httpMessage += String(F("<br/><b>CPU Frequency: </b>")) + String(ESP.getCpuFreqMHz()) + String(F("MHz"));
+  httpMessage += String(F("<br/><b>Sketch Size: </b>")) + String(ESP.getSketchSize()) + String(F(" bytes"));
+  httpMessage += String(F("<br/><b>Free Sketch Space: </b>")) + String(ESP.getFreeSketchSpace()) + String(F(" bytes"));
+  httpMessage += String(F("<br/><b>Heap Free: </b>")) + String(ESP.getFreeHeap());
+  httpMessage += FPSTR(HTTP_END);
+  webServer.send(200, "text/html", httpMessage);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void webHandleSaveConfig()
+{ // webServer /saveConfig
+  if (String(configPassword) != "")
+  { //Request HTTP auth if configPassword is set
+    if (!webServer.authenticate(configUser, configPassword))
+    {
+      return webServer.requestAuthentication();
+    }
+  }
+  String httpMessage = FPSTR(HTTP_HEAD);
+  httpMessage.replace("{v}", String(haspNode));
+  httpMessage += FPSTR(HTTP_SCRIPT);
+  httpMessage += FPSTR(HTTP_STYLE);
+  httpMessage += String(HASP_STYLE);
+
+  // Check required values
+  if (webServer.arg("mqttServer") != "" && webServer.arg("mqttServer") != String(mqttServer))
+  { // Handle mqttServer
+    shouldSaveConfig = true;
+    webServer.arg("mqttServer").toCharArray(mqttServer, 64);
+  }
+  if (webServer.arg("mqttPort") != "" && webServer.arg("mqttPort") != String(mqttPort))
+  { // Handle mqttPort
+    shouldSaveConfig = true;
+    webServer.arg("mqttPort").toCharArray(mqttPort, 6);
+  }
+  if (webServer.arg("haspNode") != "" && webServer.arg("haspNode") != String(haspNode))
+  { // Handle haspNode
+    shouldSaveConfig = true;
+    webServer.arg("haspNode").toCharArray(haspNode, 16);
+  }
+  // Check optional values
+  if (webServer.arg("mqttUser") != String(mqttUser))
+  { // Handle mqttUser
+    shouldSaveConfig = true;
+    webServer.arg("mqttUser").toCharArray(mqttUser, 32);
+  }
+  if (webServer.arg("mqttPassword") != String(mqttPassword))
+  { // Handle mqttPassword
+    shouldSaveConfig = true;
+    webServer.arg("mqttPassword").toCharArray(mqttPassword, 32);
+  }
+  if (webServer.arg("configUser") != String(configUser))
+  { // Handle configUser
+    shouldSaveConfig = true;
+    webServer.arg("configUser").toCharArray(configUser, 32);
+  }
+  if (webServer.arg("configPassword") != String(configPassword))
+  { // Handle configPassword
+    shouldSaveConfig = true;
+    webServer.arg("configPassword").toCharArray(configPassword, 32);
+  }
+
+  if (shouldSaveConfig)
+  { // Config updated, notify user and trigger write to SPIFFS
+    httpMessage += String(F("<meta http-equiv='refresh' content='15;url=/' />"));
+    httpMessage += FPSTR(HTTP_HEAD_END);
+    httpMessage += String(F("<h1>")) + String(haspNode) + String(F("</h1>"));
+    httpMessage += String(F("<br/>Saving updated configuration values and restarting device"));
+    httpMessage += FPSTR(HTTP_END);
+    webServer.send(200, "text/html", httpMessage);
+    saveUpdatedConfig();
+    debugPrintln(F("RESET: Rebooting device"));
+    delay(2000);
+    ESP.reset();
+    delay(5000);
+  }
+  else
+  { // No change found, notify user and link back to config page
+    httpMessage += String(F("<meta http-equiv='refresh' content='3;url=/' />"));
+    httpMessage += FPSTR(HTTP_HEAD_END);
+    httpMessage += String(F("<h1>")) + String(haspNode) + String(F("</h1>"));
+    httpMessage += String(F("<br/>No changes found, returning to <a href='/'>home page</a>"));
+    httpMessage += FPSTR(HTTP_END);
+    webServer.send(200, "text/html", httpMessage);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void webHandleResetConfig()
+{ // webServer /resetConfig
+  if (String(configPassword) != "")
+  { //Request HTTP auth if configPassword is set
+    if (!webServer.authenticate(configUser, configPassword))
+    {
+      return webServer.requestAuthentication();
+    }
+  }
+  String httpMessage = FPSTR(HTTP_HEAD);
+  httpMessage.replace("{v}", String(haspNode));
+  httpMessage += FPSTR(HTTP_SCRIPT);
+  httpMessage += FPSTR(HTTP_STYLE);
+  httpMessage += String(HASP_STYLE);
+  httpMessage += FPSTR(HTTP_HEAD_END);
+
+  if (webServer.arg("confirm") == "yes")
+  { // User has confirmed, so reset everything
+    httpMessage += String(F("<h1>"));
+    httpMessage += String(haspNode);
+    httpMessage += String(F("</h1><b>Resetting all saved settings and restarting device into WiFi AP mode</b>"));
+    httpMessage += FPSTR(HTTP_END);
+    webServer.send(200, "text/html", httpMessage);
+    delay(1000);
+    clearSavedConfig();
+  }
+  else
+  {
+    httpMessage += String(F("<h1>Warning</h1><b>This process will reset all settings to the default values and restart the device.  You may need to connect to the WiFi AP displayed on the panel to re-configure the device before accessing it again."));
+    httpMessage += String(F("<br/><hr><br/><form method='get' action='resetConfig'>"));
+    httpMessage += String(F("<br/><br/><button type='submit' name='confirm' value='yes'>reset all settings</button></form>"));
+    httpMessage += String(F("<br/><hr><br/><form method='get' action='/'>"));
+    httpMessage += String(F("<button type='submit'>return home</button></form>"));
+    httpMessage += FPSTR(HTTP_END);
+    webServer.send(200, "text/html", httpMessage);
+  }
 }

 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -957,4 +1185,4 @@
     telnetClient.write(buffer, len);
   }
 #endif
-}
+}


Use C99 initializers all around

Use C99 initializers all around

--- moros/moros.ino
+++ moros/moros.ino
@@ -33,12 +33,12 @@

 button buttons[2] = {
   {
-    interrupt_number: 0,
-    handler: handle_button_press_1
+    .interrupt_number = 0,
+    .handler = handle_button_press_1
   },
   {
-    interrupt_number: 1,
-    handler: handle_button_press_2
+    .interrupt_number = 1,
+    .handler = handle_button_press_2
   }
 };

@@ -50,14 +50,14 @@

 screen screens[2] = {
   {
-    cs_pin: 4,
-    dc_pin: 5,
-    rst_pin: 6
+    .cs_pin = 4,
+    .dc_pin = 5,
+    .rst_pin = 6
   },
   {
-    cs_pin: 7,
-    dc_pin: 8,
-    rst_pin: 9
+    .cs_pin = 7,
+    .dc_pin = 8,
+    .rst_pin = 9
   }
 };

@@ -73,22 +73,22 @@

 player players[2] = {
   {
-    INITIAL_TIME_MS,
-    0,
-    TFT(screens[0].cs_pin, screens[0].dc_pin, screens[0].rst_pin),
-    "",
-    0,
-    buttons[0].interrupt_number,
-    buttons[0].handler
+    .time_remaining_ms = INITIAL_TIME_MS,
+    .last_update_ms = 0,
+    .tft = TFT(screens[0].cs_pin, screens[0].dc_pin, screens[0].rst_pin),
+    .display_time = {},
+    .display_width_chars = 0,
+    .interrupt_number = buttons[0].interrupt_number,
+    .handle_button_press = buttons[0].handler
   },
   {
-    INITIAL_TIME_MS,
-    0,
-    TFT(screens[1].cs_pin, screens[1].dc_pin, screens[1].rst_pin),
-    "",
-    0,
-    buttons[1].interrupt_number,
-    buttons[1].handler
+    .time_remaining_ms = INITIAL_TIME_MS,
+    .last_update_ms = 0,
+    .tft = TFT(screens[1].cs_pin, screens[1].dc_pin, screens[1].rst_pin),
+    .display_time = {},
+    .display_width_chars = 0,
+    .interrupt_number = buttons[1].interrupt_number,
+    .handle_button_press = buttons[1].handler
   }
 };


Remove logs - prepare for ESP8266 WiFi

Remove logs - prepare for ESP8266 WiFi

--- meteo_lcd/meteo_lcd.ino
+++ meteo_lcd/meteo_lcd.ino
@@ -1,11 +1,6 @@
-// Uncomment define DEBUG line to build with debug logs (on serial)
-// This line MUST be before log.h include to make any effect
-//#define DEBUG
-
 #include <DHT.h>  // Temp and humidity
 #include <Wire.h> // Pressure
 #include <Adafruit_BMP085.h> // Pressure
-#include <log.h> // Serial log support
 #include <LiquidCrystal_I2C.h> // LCD display
 #include <DS3231.h>

@@ -473,7 +468,6 @@
     static byte last_second;
     if (last_second == rtc.getSecond()) {
         // No update needed
-        LOGLN("RTC No update needed");
         return false;
     }
     last_second = rtc.getSecond();
@@ -526,7 +520,6 @@
     time_format[19] = ret % 10 + ('0');

 end:
-    LOGLN(time_format);
     lcd.setCursor(0, row);
     lcd.print(time_format);

@@ -679,50 +672,33 @@
     // ##### Temperature inside #####
     // Check value
     if (isnan(temp_in)) {
-        LOGLN("temp_in is NaN");
         temp_in = err_val; //ERR
-    }
-    else {
-        LOG("Temp in: "); LOGLN(temp_in);
     }

     // ##### Temperature outside #####
     // Check value
     if (isnan(temp_out)) {
-        LOGLN("temp_out is NaN");
         temp_out = err_val; //ERR
-    }
-    else {
-        LOG("Temp out: "); LOGLN(temp_out);
     }

     // ##### Humidity inside #####
     // Check value
     if(isnan(humid_in)) {
-        LOGLN("humid_in is NaN");
         humid_in = err_val; //ERR
-    }
-    else {
-        LOG("Humid in: "); LOGLN(humid_in);
     }

     // ##### Humidity outside #####
     // Check value
     if(isnan(humid_out)) {
-        LOGLN("humid_out is NaN");
         humid_out = err_val; //ERR
-    }
-    else {
-        LOG("Humid out: "); LOGLN(humid_out);
     }

     // ##### Pressure #####
     // Nothing to do here
-    LOG("Pressure: "); LOGLN(pressure);
 }

@@ -786,10 +762,6 @@

 void setup ()
 {
-    LogInit(9600);
-
-    LOGLN("Setup begin");
-
     // LEDs
     pinMode(DEBUG_LED, OUTPUT);
     digitalWrite(DEBUG_LED, LOW);
@@ -819,8 +791,10 @@
     lcd.print("Witamy!");
     lcd.setCursor(1, 1);
     lcd.print("Stacja pogodowa");
-    lcd.setCursor(7, 2);
-    lcd.print("wersja D_0.3");
+    lcd.setCursor(5, 2);
+    lcd.print("wersja D_0.4.0");
+    lcd.setCursor(12, 3);
+    lcd.print("Wi-Fi")

     // Sleep for setup dht sensors - just in case. This also gives you time to read te welcome screen.
     delay(4000);
@@ -831,7 +805,6 @@

     // Pressure sensor
     if (!bmp.begin(3)) { // init pressure sensor with high precission param - 3
-        LOGLN("Cannot initalize BMP (pressure) sensor");
         digitalWrite(DEBUG_LED, HIGH); // if error turn debug LED on
     }

@@ -840,7 +813,6 @@

     // Full time update
     print_time_string(3 /* 4th row */, true);
-    LOGLN("Setup end");
 }

 ////////////////////////////////////////////////////////////////////////////////
@@ -848,8 +820,6 @@

 void loop ()
 {
-    LOGLN("Loop");
-
     if (enter_time_setup())
         time_setup(3 /* 4th row */);

@@ -867,7 +837,5 @@
         fill_data(temp_in, temp_out, humid_in, humid_out, pressure);
         digitalWrite(DEBUG_LED, LOW);
     }
-
-
-}
-
+}
+


不要なシリアル出力を削除

不要なシリアル出力を削除

--- 2_example/example13c_ntp/example13c_ntp.ino
+++ 2_example/example13c_ntp/example13c_ntp.ino
@@ -56,10 +56,6 @@

     Serial.print("Voltage  = ");
     Serial.println(v,3);                    // 電圧値を表示
-    time = highWord<<16 | lowWord;          // 時刻(1900年1月からの秒数)を代入
-    time -= 2208988800UL;                   // 1970年と1900年の差分を減算
-    time2txt(s,time);                       // 時刻をテキスト文字に変換
-    Serial.println(s);                      // テキスト文字を表示
     sendNTPpacket(NTP_SERVER);              // NTP取得パケットをサーバへ送信する
     while(udp.parsePacket()<44){
         delay(100);                         // 受信待ち


Agregada linea para lectura de energia

Agregada linea para lectura de energia

--- Arduino/SensordeEnergia/SensordeEnergia.ino
+++ Arduino/SensordeEnergia/SensordeEnergia.ino
@@ -1,10 +1,5 @@
 /**
-  * Description: This code has been only tested in Intel Galileo Gen 1 and gets the readings of the next sensors:
-        * TSL2561 - Light sensor
-        * MPL115A - Temperature and pressure sensor
-        * MAX4466 - Noise sensor
-        * HTU21DF - Humidity sensor
-        * Grove multichanel gas sensor
+  * Description: This code has been only tested in Intel Galileo Gen 1 and gets the readings of the next sensors:
         * SCT-013-000 - Electric current sensor
     Then it calls the python scripts to send the data to the server via MQTT. All readings are writen to a file
     located in the SD card, located by default in '/media/mmcblk0p1/'. The SD functions were taken from:
@@ -473,16 +468,19 @@
       if (DEBUG == 1) Serial.println("state:readSensors");
       if( (readingFlag & POTENCIA) == POTENCIA)
       {
-        if(DEBUG == 1)
-        {
-          Serial.println("ENERGY SENSORS");
+
+          if(DEBUG == 1) Serial.println("ENERGY SENSORS");
           for(int i = 0; i < ENERGY_COUNT; i++)
           {
-            Serial.print(i+1);
-            Serial.print(" Sensor: ");
-            Serial.println(m.power[i]);
+            getCurrent(energySensors[i],i);
+            if(DEBUG == 1)
+            {
+              Serial.print(i+1);
+              Serial.print(" Sensor: ");
+              Serial.println(m.power[i]);
+            }
           }
-        }
+
       }
       state = checkRanges;
       break;


Spelling 😡

Spelling 😡

--- ZstabilizationTest1/ZstabilizationTest1.ino
+++ ZstabilizationTest1/ZstabilizationTest1.ino
@@ -41,17 +41,17 @@

   /*
   buttonState = digitalRead(##buttonPin##);
-  // if putton pressed, ACTIVATE Z Stabalization
+  // if putton pressed, ACTIVATE Z Stabilization
   if(buttonState == HIGH && !lockedZ){
     depthSavedState = sensor.depth();
     lockedZ = true;
   }
-  // if putton pressed, DEACTIVATE Z Stabalization
+  // if putton pressed, DEACTIVATE Z Stailization
   if(buttonState == HIGH && lockedZ){
     depthSavedState = sensor.depth();
     lockedZ = false;
   }
-    // if Z STABLAIZATION = ACTIVE
+    // if Z STABILIZATION = ACTIVE
     while(lockedZ){
     // if ROV is above saved state
       if(sensor.depth() > depthSavedState){


Signal history detection is working!?!?!?!?

--- module/module.ino
+++ module/module.ino
@@ -278,8 +278,9 @@
 			numInvalid += 1;
 		}
 	}
-	Serial.print(numValid); Serial.print(numInvalid);
-	Serial.print(" "); Serial.print(" ");
+	//Serial.print(numValid); Serial.print(numInvalid);
+	//Serial.print(" "); Serial.print(" ");
+  delay(1);

 	if (numValid == sampleSize) {
 		return flag.detectedJobStart;


Added debug check

Added debug check

--- module/module.ino
+++ module/module.ino
@@ -198,7 +198,7 @@
 			Serial.print("PeriodX: "); Serial.print(periodX);
 			Serial.print(" PeriodY: "); Serial.print(periodY);
 			Serial.print(" "); Serial.print(signals[0]); Serial.print(signals[1]); Serial.print(signals[2]);
-			Serial.print(" "); Serial.print(checkHistory(signals));
+			Serial.print(" "); Serial.print(numValid); Serial.print(numInvalid); Serial.print(" "); Serial.print(checkHistory(signals));
 			Serial.print(" Start Time: "); Serial.print(startTime);
 			Serial.print(" Pulse Count: "); Serial.println(pulseCount);
 		}


json,. mqtt

json,. mqtt

--- yun.ino
+++ yun.ino
@@ -1,69 +1,109 @@
-#include <DHT.h>
-#include <Ultrasonic.h>
-#include <Bridge.h>
-#include <BridgeServer.h>
-#include <BridgeClient.h>
+#include <ArduinoJson.h>

-#define DHT_PIN 4
-#define DHT_TYPE DHT11
-#define BUZZER_PIN 8
-#define LED_BLUE_PIN 3
-#define ULTRASONIC_RANGER_PIN 2
+#include <MQTTClient.h>
+#include <MQTT.h>
+#include <system.h>

-DHT dht(DHT_PIN, DHT_TYPE);
-Ultrasonic ultrasonic(ULTRASONIC_RANGER_PIN);
-BridgeServer server;
+#include "Ultrasonic.h"
+#include "DHT.h"
+
+#define DHTTYPE DHT11
+
+MQTTClient client;
+int ultrasonicPin = 2;
+int DHTPin = 4;
+int buzzerPin = 8;
+int ledPin = 3;
+
+DHT dht(DHTPin, DHTTYPE);
+Ultrasonic ultrasonic(ultrasonicPin);
+
+void connect()
+{
+  Serial.print("\nConnecting to MQTT...");
+  while (!client.connect("arduino", "try", "try"))
+  {
+    Serial.print(".");
+    delay(1000);
+  }
+
+  Serial.println("\nconnected!");
+
+  client.subscribe("/hello");
+  // client.unsubscribe("/hello");
+}
+
+void messageReceived(String &topic, String &payload)
+{
+  Serial.println("incoming: " + topic + " - " + payload);
+}

 void setup()
 {
-  // Sensors setup
+  // MQTT
+  client.begin("broker.shiftr.io", net);
+  client.onMessage(messageReceived);
+  connect();
+
+  Serial.begin(9600);
   dht.begin();
-  pinMode(BUZZER_PIN, OUTPUT);
-  pinMode(LED_BLUE_PIN, OUTPUT);
-
-  // External and openwrt communications setup
-  Bridge.begin();
-  server.begin();
+  pinMode(buzzerPin, OUTPUT);
+  pinMode(ledPin, OUTPUT);
 }

 void loop()
 {
-  BridgeClient client = server.accept();
-
-  if (client) {
-    process(client);
-    client.stop();
+  // MQTT
+  client.loop();
+  if (!client.connected())
+  {
+    connect();
   }

+  long ultrasonicCentimeters;
+
+  ultrasonicCentimeters = ultrasonic.MeasureInCentimeters(); // two measurements should keep an interval
+  Serial.println(ultrasonicCentimeters);
+  if (ultrasonicCentimeters > 50)
+  {
+    toggleDigital(buzzerPin, 250);
+  }
+  else
+  {
+    toggleDigital(ledPin, 1000);
+  }
+
+  // Reading temperature or humidity takes about 250 milliseconds!
+  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
+  float h = dht.readHumidity();
+  float t = dht.readTemperature();
+
+  // check if returns are valid, if they are NaN (not a number) then something went wrong!
+  if (isnan(t) || isnan(h))
+  {
+    Serial.println("Failed to read from DHT");
+  }
+  else
+  {
+    printDHT(h, t);
+  }
+
+  Serial.println("\n");
   delay(1000);
 }

-void process(BridgeClient client) {
-  String command = client.readStringUntil('/');
-
-  if(command == "digital") {
-    toggleDigital(13, 1000);
-  }
-  if(command == "buzzer") {
-    toggleDigital(BUZZER_PIN, 1000);
-  }
-  if(command == "ultrasonic_ranger") {
-    long ultrasonicCentimeters = ultrasonic.MeasureInCentimeters();
-    client.write(ultrasonicCentimeters);
-  }
-  if(command == "humidity") {
-    float h = dht.readHumidity();
-    client.write(h);
-  }
-  if(command == "temperature") {
-    float t = dht.readTemperature();
-    client.write(t);
-  }
-}
-
-void toggleDigital(int pin, int delayTime) {
+void toggleDigital(int pin, int delayTime)
+{
   digitalWrite(pin, HIGH);
   delay(delayTime);
   digitalWrite(pin, LOW);
 }

+void printDHT(float h, int t)
+{
+  Serial.print("Humidity: ");
+  Serial.print(h);
+  Serial.print("\t Temperature: ");
+  Serial.print(t);
+  Serial.println(" *C");
+}


update basic.ino

update basic.ino

--- examples/Basic/Basic.ino
+++ examples/Basic/Basic.ino
@@ -3,10 +3,12 @@
 void setup() {
     // put your setup code here, to run once:
     Serial.begin(115200);
+
+    // WiFi.mode(WiFi_STA); // it is a good practice to make sure your code sets wifi mode how you want it.

     //WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
     WiFiManager wm;
-
+
     //reset settings - wipe credentials for testing
     //wm.resetSettings();


Fix test MIDI sketch with proper setup and docs.

--- sketches/test_midi/test_midi.ino
+++ sketches/test_midi/test_midi.ino
@@ -4,17 +4,9 @@
  Turns on a LED when at least one key is pressed.

  The circuit:
- * LED built in to pin 13, connected to ground
- * Key matrix: C, C#, and D from two keyboards
-   * C into digital pin 8
-   * C# into digital pin 9
-   * D into digital pin 10
-   * Internal pull-up resistors activated for all inputs
- * Keyboard 0 - pin 69 (analog 15)
- * Keyboard 1 - pin 68 (analog 14)
- * Six diodes allowing facing away from the inputs (allowing
-   current to be sunk, and hence inputs pulled down,
-   but open circuit otherwise)
+ * OrganDuino PCB shield, populated with diodes
+ * First two octaves (24 keys) soldered in
+ * Rank 0 jumper bridged on reverse side

  created 2016 by @JDWarner
 */
@@ -118,12 +110,12 @@

   // drive pins per rank
   for(int d=0; d<numRanks; d++){
-      pinMode(d, OUTPUT);
-      digitalWrite(d, HIGH);
+      pinMode(rankPins[d], OUTPUT);
+      digitalWrite(rankPins[d], HIGH);
   }
   // initialize the organ keys' pins as inputs
   for(int k=0; k<numKeys; k++){
-      pinMode(k, INPUT_PULLUP);
+      pinMode(keyPins[k], INPUT_PULLUP);
   }
 }


Updated bridge sensor sketch to use more reliable power functions. Needs testing on actual hardware still.

--- Arduino/libraries/UA_Sensors/examples/BridgeSensorGSM/BridgeSensorGSM.ino
+++ Arduino/libraries/UA_Sensors/examples/BridgeSensorGSM/BridgeSensorGSM.ino
@@ -4,7 +4,7 @@
   Sketch used by UA Sensors platform.

   Created 14 6 2014
-  Modified 14 6 2014
+  Modified 23 6 2014
 */

 #include <LowPower.h>
@@ -53,8 +53,6 @@
 #define UNSENT_FILENAME            "unsent.txt"
 #define ERROR_FILENAME             "error.txt"
 #define PHONE_NUMBER               "+12223334444"
-#define GSM_TIMEOUT                250
-#define SMS_TIMEOUT                100
 #define ERROR_GSM                  "GSM Failed"
 #define ERROR_SMS                  "SMS Failed"

@@ -246,14 +244,12 @@
     Serial.begin(19200);
     delay(100);

-    sim900.togglePower();
-

     // 20. Send text message if GSM Ready
-    if (sim900.isReady(GSM_TIMEOUT) == true)
+    if (sim900.ensureReady() == true)
     {
       sim900.sendTextMsg(textMessage, PHONE_NUMBER);
-      if (sim900.isTextMsgDelivered(SMS_TIMEOUT) == false)
+      if (sim900.isTextMsgDelivered() == false)
       {
         // Log SMS failure
         digitalWrite(MOSFET_SD_PIN, HIGH);
@@ -281,7 +277,6 @@
       delay(1000);
     }

-
     // Reset number of cached readings
     numCachedReadings = 0;

@@ -289,8 +284,13 @@
     // 20. Turn off GSM.
     // -----------------

-    // Turn on GSM power pin.
-    sim900.togglePower();
+    // Turn off GSM power pin.
+    if (sim900.ensureOffline() == false)
+    {
+      // TODO(richard-to): What would be best way to handle this issue?
+      //                   Battery will die quickly if power cannot be turned off.
+      //                   Send SOS SMS?
+    }

     // Turn off GSM MOSFET.
     digitalWrite(MOSFET_GSM_PIN, LOW);


suppression des 2 morceaux non identifiés (pour raccourcir la durée de la démo)


Debug IR codes

Debug IR codes

--- MagbotBudget/MagbotBudget.ino
+++ MagbotBudget/MagbotBudget.ino
@@ -15,7 +15,7 @@
  6  - Motor B pwm
  5  - Motor A pwm
  4  - Ping echo
- 3  - (blocked by shield)
+ 3  - not used
  2  - Sound
  1  - not connected (Serial write)
  0  - not connected (Serial read)
@@ -247,7 +247,7 @@
   batteryLevel();
   whiskersCalibrate();

-  timer.setTimeout(500, actionTrundle);
+  //timer.setTimeout(500, actionTrundle);

 }
@@ -1058,6 +1058,8 @@
   /* Save this code incase we get a repeat code next time */
   LastCode = code;

+  Serial.println(code);
+
   /* Find the button name for the received code */
   switch (code)
   {
@@ -1163,7 +1165,7 @@
     break;
   }

-  //Serial.println(CodeName);
+  Serial.println(CodeName);
 }

 /********************************************************************************


explained DISABLE_LOOPING switch in description section

--- Arduino_codeline/fairytale25/fairytale25.ino
+++ Arduino_codeline/fairytale25/fairytale25.ino
@@ -99,6 +99,9 @@
    After playback of all files is finished, the program will resume it's main loop, delay
    operation for roughly 15 seconds (to give the user the chance to remove the just used Tag
    from the reader) and then wait until it detects the next tag.
+   In case the figure is not removed from the reader, the album will be played again. To
+   prevent this from happening, there is a compile time switch below DISABLE_LOOPING. Enable
+   this switch and the box will only start the newxt album if it is != just played played album.

    While advancing through the files in the directory, the program will update the TrackDB-File
    with  the number of the currently played track. Doing so allows for interrupted playbacks -
@@ -205,29 +208,31 @@
    Some features (as e.g. Remote Control, Buttons or operation LED etc.) can be turned off
    or on via #define switches in the code below.

-      #define IRREMOTE     enables the IR Remote Control option
+      IRREMOTE          enables the IR Remote Control option

-      #define BUTTONS      enables the 4 control buttons
+      BUTTONS           enables the 4 control buttons

-      #define VOLUMEPOT    enables the volume potentiometer
+      VOLUMEPOT         enables the volume potentiometer

-      #define LOWBAT       enables the low battery warning with light and voice
-
-      #define OPRLIGHT     enables the operations light on the front of the box
+      LOWBAT            enables the low battery warning with light and voice
+
+      OPRLIGHT          enables the operations light on the front of the box

-      #define OPRLIGHTTIME enables time based operations light - turns off the light after 30 Minutes
-
-      #define NFCNDEF      enables the use of NDEF messages to get the directory for a tag
+      OPRLIGHTTIME      enables time based operations light - turns off the light after 30 Minutes
+
+      NFCNDEF           enables the use of NDEF messages to get the directory for a tag

-      #define NFCTRACKDB   enables the use of the TrackDB to get the directiry for a tag
-
-      #define ALBUMNFC     enables a special file albumnfc.tdb in which all album <-> nfc
-                           connections are stored - additional to the TrackDb files
-
-      #define RESUMELAST   enables the option to resume last played album upon startup.
-                           This is achieved via a file in the TrackDB and works without
-                           a tag but uses the pause/resume button instead
-
+      NFCTRACKDB        enables the use of the TrackDB to get the directiry for a tag
+
+      ALBUMNFC          enables a special file albumnfc.tdb in which all album <-> nfc
+                        connections are stored - additional to the TrackDb files
+
+      RESUMELAST        enables the option to resume last played album upon startup.
+                        This is achieved via a file in the TrackDB and works without
+                        a tag but uses the pause/resume button instead
+
+      DISABLE_LOOPING   disables looping an album in case the figure is still on the
+                        reader when playback is finished
 */

 //


oha_gateway_rf_v0_1: - Added debug logging of RF message to serial port

--- oha_gateway_rf_v0_1/oha_gateway_rf_v0_1.ino
+++ oha_gateway_rf_v0_1/oha_gateway_rf_v0_1.ino
@@ -9,7 +9,7 @@
    * Analog 5 to Arduino 5 via level shifter
    * RF Status LED attached to digital pin 9

-   Created 06-JAN-2015 by Jon Brule
+   Created 13-JAN-2015 by Jon Brule
 ----------------------------------------------------------------------------- */
 #include <RFM69.h>
 #include <SPI.h>
@@ -54,45 +54,45 @@
 // setup the arduino board
 //
 void setup() {
-    Serial.begin(BAUD_RATE);
-    #if DEBUG
-        Serial.print("\n[OHA RF Gateway - ");
-        Serial.print(VERSION);
-        Serial.println("]");
-    #endif
+  Serial.begin(BAUD_RATE);
+  #if SERIAL
+    Serial.print("\n[OHA RF Gateway - ");
+    Serial.print(VERSION);
+    Serial.println("]");
+  #endif

-    setup_rf();
-    setup_i2c();
+  setup_rf();
+  setup_i2c();
 }

 //------------------------------------------------------------------------------
 // Initializes the RF radio.
 //
 static void setup_rf() {
-    #if DEBUG
-        Serial.print("Setup radio...");
-    #endif
-    radio.initialize(FREQUENCY, NODEID, NETWORKID);
-    radio.setHighPower();
-    delay(1000);
-    #if DEBUG
-        Serial.println("OK");
-    #endif
+  #if SERIAL
+    Serial.print("Setup radio...");
+  #endif
+  radio.initialize(FREQUENCY, NODEID, NETWORKID);
+  radio.setHighPower();
+  delay(1000);
+  #if DEBUG
+    Serial.println("OK");
+  #endif
 }

 //------------------------------------------------------------------------------
 // Initializes the I2C bus.
 //
 static void setup_i2c() {
-    #if DEBUG
-        Serial.print("Setup I2C...");
-    #endif
-    Wire.begin (I2C_ADDR);
-    Wire.onReceive(receiveFromWire);
-    delay(1000);
-    #if DEBUG
-        Serial.println("OK");
-    #endif
+  #if SERIAL
+    Serial.print("Setup I2C...");
+  #endif
+  Wire.begin (I2C_ADDR);
+  Wire.onReceive(receiveFromWire);
+  delay(1000);
+  #if DEBUG
+    Serial.println("OK");
+  #endif
 }

@@ -105,17 +105,17 @@
 //
 void loop() {

-    // process inbound RF message
-    if (receiveFromRF()) {
-      sendToI2C();
-      haveDataRF = false;
-    }
+  // process inbound RF message
+  if (receiveFromRF()) {
+    sendToI2C();
+    haveDataRF = false;
+  }

-    // process inbound I2C message
-    if (haveDataI2C) {
-      sendToRF();
-      haveDataI2C = false;
-    }
+  // process inbound I2C message
+  if (haveDataI2C) {
+    sendToRF();
+    haveDataI2C = false;
+  }

 }

@@ -123,51 +123,71 @@
 // Receives a message from the RF mesh
 //
 boolean receiveFromRF() {
-    if (radio.receiveDone()) {
-        if (radio.DATALEN != sizeof(Message)) {
-            Serial.print("Invalid payload received, not matching Message struct!");
-        } else {
-            memcpy(&msgRF, (byte*) radio.DATA, sizeof msgRF);
-            msgRF.msg.rssi = radio.RSSI;
-            haveDataRF = true;
+  if (radio.receiveDone()) {
+    if (radio.DATALEN != sizeof(Message)) {
+      Serial.print("Invalid payload received, not matching Message struct!");
+    } else {
+      memcpy(&msgRF, (byte*) radio.DATA, sizeof msgRF);
+      msgRF.msg.rssi = radio.RSSI;
+      haveDataRF = true;
+      #if DEBUG
+        Serial.print("RF<direction=");
+        Serial.print(msgRF.msg.direction, DEC);
+        Serial.print(",type=");
+        Serial.print(msgRF.msg.type, DEC);
+        Serial.print(",source=");
+        Serial.print(msgRF.msg.source, DEC);
+        Serial.print(",destination=");
+        Serial.print(msgRF.msg.destination, DEC);
+        Serial.print(",rssi=");
+        Serial.print(msgRF.msg.rssi, DEC);
+        Serial.print(",rssi=data(");
+        for (int i = 0; i < MSG_DATA_LENGTH; i++) {
+          if (i > 0) Serial.print(",");
+          Serial.print(msgRF.msg.data[i], DEC);
         }
-        if (radio.ACK_REQUESTED) {
-            radio.sendACK();
-        }
+        Serial.print(")>");
+      #endif
     }
-    return haveDataRF;
+    if (radio.ACK_REQUESTED) {
+      radio.sendACK();
+    }
+  }
+  return haveDataRF;
 }

 //------------------------------------------------------------------------------
 // Receives a message from the I2C bus (a.k.a Wire).
 //
 void receiveFromWire(int howMany) {
-    if (howMany < sizeof msgI2C) {
-        return;
-    }
+  if (howMany < sizeof msgI2C) {
+    return;
+  }

-    // read into structure
-    byte * p = (byte *) &msgI2C;
-    for (byte i = 0; i < sizeof msgI2C; i++) {
-        *p++ = Wire.read();
-    }
-    haveDataI2C = true;
+  // read into structure
+  byte * p = (byte *) &msgI2C;
+  for (byte i = 0; i < sizeof msgI2C; i++) {
+    *p++ = Wire.read();
+  }
+  haveDataI2C = true;
 }

 //------------------------------------------------------------------------------
 // Publishes an I2C message to the RF mesh.
 //
 void sendToRF() {
-    radio.send(msgI2C.msg.destination, msgI2C.raw, MSG_LENGTH);
+  radio.send(msgI2C.msg.destination, msgI2C.raw, MSG_LENGTH);
 }

 //------------------------------------------------------------------------------
 // Publishes an RF message to the I2C bus.
 //
 void sendToI2C() {
-    Serial.println("xmit to i2c");
-    Wire.beginTransmission(I2C_TARGET);
-    Wire.write((byte *) &msgRF, sizeof msgRF);
-    Wire.endTransmission();
+  #if DEBUG
+    Serial.println(" - xmit to i2c");
+  #endif
+  Wire.beginTransmission(I2C_TARGET);
+  Wire.write((byte *) &msgRF, sizeof msgRF);
+  Wire.endTransmission();
 }


BabelFish: Full BASIC program transfer to PC/laptop

This change allows sending the complete BASIC program to your
computer, no matter how large it is.

When saving a program from TinyBASIC or MSBASIC, it gets transmitted
to BabelFish as ASCII text lines. Now it depends on BabelFish's
serial session state what it will do with it:

When BabelFish is in idle mode (indicated by the "Cmd?" prompt),
the program is still saved into the microcontroller's EEPROM area,
exactly as before. If the program doesn't fit, the Gigatron receives
a Ctrl-C as before. The only change is that in this mode there's
no forwarding to PC/laptop any more. You need to be in Terminal
mode for that now.

In Terminal mode (enter with the 'T' command), now the complete
program is echoed to the host. Previously when typine SAVE in this
mode typing SAVE, all was silently ignored...) Note that the program
still isn't saved to the EEPROM in this mode. But you can capture
it from your terminal window and put it in a file on your computer.
Even if it wouldn't have fit in the EEPROM.

--- Utils/BabelFish/BabelFish.ino
+++ Utils/BabelFish/BabelFish.ino
@@ -401,52 +401,26 @@
 void loop()
 {
   // Check Gigatron's vPulse for incoming data
-  static byte inByte, inBit, hasChars;
-
-  critical();
-  byte newValue = waitVSync();
-  nonCritical();
-
-  switch (newValue) {
-    case 9:                            // Received one bit
-      inByte |= inBit;
-      // !!! FALL THROUGH !!!
-    case 7:                            // Received zero bit
-      inBit <<= 1;
-
-      if (saveIndex >= EEPROM_length)  // EEPROM overflow
-        if (hasChars)                  // Only break if this isn't an empty line
-          sendController(3, 10);       // Send long Ctrl-C back to stop LIST
-
-      if (inBit != 0)                  // Still a partial byte
-        break;
-
-      EEPROM.write(saveIndex++, inByte);// Store every full byte
-
-      #if hasSerial
-        if (inByte == 10)
-          Serial.print('\r');
-        Serial.print((char)inByte);    // Forward to host
-        noInterrupts();
-      #endif
-
-      if (inByte == 10) {              // End of line?
-        EEPROM.write(saveIndex, 255);  // EOF terminator, in case this becomes the last line
-        if (!hasChars)                 // An empty line clears the old program
-          saveIndex = fileStart;
-        hasChars = false;
-      } else if (inByte != 13)         // Don't count CR towards line length
-        hasChars = true;
-
-      inByte = 0;                      // Prepare for next byte
-      inBit = 1;
-      break;
-
-    default:
-      inByte = 0;                      // Reset incoming data state
-      inBit = 1;
+  // Save it into the EEPROM area if data received
+  int inByte = vSyncByte();
+  static byte hasChars;                 // Keeps track of partial lines
+  if (inByte < 0) {
+    if (inByte == -1)                   // Idle
+      hasChars = false;                 // Be robust against partial lines
+  } else {                              // Full byte received
+    if (saveIndex < EEPROM_length)      // Store byte in EEPROM if possible
+      EEPROM.write(saveIndex++, inByte);
+    else if (hasChars)                  // Full, but only break if line is non-empty
+      sendController(3, 10);            // Send long Ctrl-C back to stop sender
+    if (inByte >= 32)
+      hasChars = true;                  // Mark printable characters as non-empty
+    else if (inByte == '\n') {
+      if (!hasChars)                    // Empty lines delete the old program
+        saveIndex = fileStart;
+      if (saveIndex < EEPROM_length)    // EOF terminator
+        EEPROM.write(saveIndex, 255);
       hasChars = false;
-      break;
+    }
   }

   // Game controller pass through (Courtesy norgate)
@@ -728,7 +702,7 @@
   delay(50); // Allow Gigatron software to process line
 }

-// Send list of decimal numbers as bytes
+// Send list of decimal numbers as byte stream
 void doBytes(char *line)
 {
   do {
@@ -756,10 +730,10 @@
     Serial.println(":Entering terminal mode");
     Serial.println(":Exit with Ctrl-D");
     char next = 0, last;
-    byte out;
     bool ansi = false;
     for (;;) {
       if (Serial.available()) {
+        byte out;
         last = next;
         next = Serial.read();
         sendEcho(next, last);
@@ -781,6 +755,16 @@

         sendController(out, 2);
         ansi = false;
+      } else {
+
+        // If we receive data in terminal mode, forward it all
+        // to the the host (instead of storing it into EEPROM)
+        int inByte = vSyncByte(); // Check for data carried with /vSync
+        if (inByte >= 0) {
+          if (inByte == 10)
+            Serial.print('\r');
+          Serial.print((char)inByte);
+        }
       }
     }
   #endif
@@ -1131,6 +1115,34 @@
   checksum += value;
 }

+// Check Gigatron's vPulse for incoming data
+// Return each completed byte value, -1 for idle, < -1 for busy
+int vSyncByte()
+{
+  static byte inByte, inBit;
+
+  critical();
+  byte count = waitVSync();
+  nonCritical();
+
+  inByte &= ~inBit;                     // Clear current bit
+  switch (count) {
+    case 9:                             // Received a one bit
+      inByte |= inBit;
+      // !!! FALL THROUGH !!!
+    case 7:                             // Received a zero bit
+      inBit <<= 1;
+      if (!inBit) {
+        inBit = 1;                      // Prepare for next byte
+        return inByte;                  // Return full byte
+      }
+      break;
+    default:
+      inBit = 1;                        // Reset incoming data state
+  }
+  return -inBit;
+}
+
 // Count number of hSync pulses during vPulse
 // This is a way for the Gigatron to send information out
 byte waitVSync()
@@ -1161,6 +1173,7 @@
   return count;
 }

+// For polling the game controller
 void sendPulse(byte pin)
 {
   digitalWrite(pin, HIGH);
@@ -1188,11 +1201,11 @@
     if (j++ == 0 && nextByte == 255)    // EOF. Note that in MSBASIC, 255 means Pi.
       break;                            // So we only check this after a newline.
     sendController(nextByte, 2);        // A single frame is sometimes too fast
-    if (nextByte == 13)                 // "A carriage return takes more time"
+    if (nextByte == '\r')               // "A carriage return takes more time"
       lineDelay = 300 + j * 50;         // Reality: Micro-Soft BASIC is s-l-o-w
     delay((j % 26) ? 20                 // Allow Gigatron software to draw the char
                    : 300);              // And give more time at line wrap
-    if (nextByte == 10) {               // End of line
+    if (nextByte == '\n') {             // End of line
       delay(lineDelay);                 // Allow some extra time for line processing
       j = 0;                            // Start of new line
     }


Long jump mode implemented!

Long jump mode implemented!

--- pug.ino
+++ pug.ino
@@ -31,6 +31,7 @@
 // Goodies mode
 #define TOUPIE false
 #define TOUPIE_2 false
+#define JUMP false

 IntervalTimer ultraTimer;
 IntervalTimer motorTimer;
@@ -189,6 +190,16 @@
 boolean hasCalibrate = false;
 void loop() {
   if (DEBUG) return;
+
+  if(JUMP){
+    while (!digitalRead(JUMPER_PIN));
+    while (digitalRead(JUMPER_PIN));
+    setLeftSpeed( 100 );
+    setRightSpeed(100);
+    delay(5000);
+    stopMotors();
+    return;
+  }

   if (TOUPIE) {
     while (!digitalRead(JUMPER_PIN));
@@ -197,6 +208,7 @@
     setRightSpeed( -100 );
     delay(5000);
     stopMotors();
+    return;
   }

   if(TOUPIE_2) {
@@ -211,6 +223,7 @@
     setRightSpeed(100);
     delay(1000);
     stopMotors();
+    return;
   }

   if (!hasCalibrate) {


increased delay to 10s

increased delay to 10s


MQTT_MAX_PACKET_SIZE Comment

MQTT_MAX_PACKET_SIZE Comment

--- bruh_mqtt_multisensor_github/bruh_mqtt_multisensor_github.ino
+++ bruh_mqtt_multisensor_github/bruh_mqtt_multisensor_github.ino
@@ -19,6 +19,8 @@
       - Adafruit unified sensor
       - PubSubClient
       - ArduinoJSON
+
+  UPDATE 23 MAY 2017 - The MQTT_MAX_PACKET_SIZE parameter may not be setting appropriately do to a bug in the PubSub library. If the MQTT messages are not being transmitted as expected please you may need to change the MQTT_MAX_PACKET_SIZE parameter in "PubSubClient.h" directly.

 */


Removed dead code.

Removed dead code.

Save some bytes, less literals.

--- webservertask.ino
+++ webservertask.ino
@@ -17,15 +17,18 @@
   static const char * PASSWD_KEY_NVS           = "wwwpassword";  //the (changed) admin password is saved in NVS under this key
   static const char * HEADER_LASTMODIFIED      = "Last-Modified";
   static const char * HEADER_HTML              = "text/html";
+  static const char * INVALID_OPTION           = "Invalid option";
+  static const char * NO_SENSORNUMBER          = "No sensornumber";
+  static const char * INVALID_SENSORNUMBER     = "Invalid sensornumber";

   static AsyncWebServer server(80);

   while ( !systemStart.tv_sec )
     delay(100);

-  static char date[30];
-
-  strftime( date, sizeof( date ), "%a, %d %b %Y %X GMT", gmtime( &systemStart.tv_sec ) );
+  static char modifiedDate[30];
+
+  strftime( modifiedDate, sizeof( modifiedDate ), "%a, %d %b %Y %X GMT", gmtime( &systemStart.tv_sec ) );

   server.on( "/robots.txt", HTTP_GET, []( AsyncWebServerRequest * request ) {
     request->send( 200, HEADER_HTML, "User-agent: *\nDisallow: /\n" );
@@ -39,49 +42,49 @@
   });

   server.on( "/", HTTP_GET, [] ( AsyncWebServerRequest * request ) {
-    if ( htmlUnmodified( request, date ) ) return request->send(304);
+    if ( htmlUnmodified( request, modifiedDate ) ) return request->send(304);
     AsyncWebServerResponse *response = request->beginResponse_P( 200, HEADER_HTML, index_htm, index_htm_len );
-    response->addHeader( HEADER_LASTMODIFIED, date );
+    response->addHeader( HEADER_LASTMODIFIED, modifiedDate );
     request->send( response );
   });

   //  /channels or 'channels.htm'
   server.on( "/channels", HTTP_GET, [] ( AsyncWebServerRequest * request ) {
-    if ( htmlUnmodified( request, date ) ) return request->send(304);
+    if ( htmlUnmodified( request, modifiedDate ) ) return request->send(304);
     AsyncWebServerResponse *response = request->beginResponse_P( 200, HEADER_HTML, channels_htm, channels_htm_len );
-    response->addHeader( HEADER_LASTMODIFIED, date );
+    response->addHeader( HEADER_LASTMODIFIED, modifiedDate );
     request->send( response );
   });

   //  /editor or 'editor.htm'
   server.on( "/editor", HTTP_GET, [] ( AsyncWebServerRequest * request ) {
-    if ( htmlUnmodified( request, date ) ) return request->send(304);
+    if ( htmlUnmodified( request, modifiedDate ) ) return request->send(304);
     AsyncWebServerResponse *response = request->beginResponse_P( 200, HEADER_HTML, editor_htm, editor_htm_len );
-    response->addHeader( HEADER_LASTMODIFIED, date );
+    response->addHeader( HEADER_LASTMODIFIED, modifiedDate );
     request->send( response );
   });

   //  /logs or 'logs.htm'
   server.on( "/logs", HTTP_GET, [] ( AsyncWebServerRequest * request ) {
-    if ( htmlUnmodified( request, date ) ) return request->send(304);
+    if ( htmlUnmodified( request, modifiedDate ) ) return request->send(304);
     AsyncWebServerResponse *response = request->beginResponse_P( 200, HEADER_HTML, logs_htm, logs_htm_len );
-    response->addHeader( HEADER_LASTMODIFIED, date );
+    response->addHeader( HEADER_LASTMODIFIED, modifiedDate );
     request->send( response );
   });

   //  /setup or 'setup.htm'
   server.on( "/setup", HTTP_GET, [] ( AsyncWebServerRequest * request ) {
-    if ( htmlUnmodified( request, date ) ) return request->send(304);
+    if ( htmlUnmodified( request, modifiedDate ) ) return request->send(304);
     AsyncWebServerResponse *response = request->beginResponse_P( 200, HEADER_HTML, setup_htm, setup_htm_len );
-    response->addHeader( HEADER_LASTMODIFIED, date );
+    response->addHeader( HEADER_LASTMODIFIED, modifiedDate );
     request->send( response );
   });

   //  /filemanager or 'fileman.htm'
   server.on( "/filemanager", HTTP_GET, [] ( AsyncWebServerRequest * request ) {
-    if ( htmlUnmodified( request, date ) ) return request->send(304);
+    if ( htmlUnmodified( request, modifiedDate ) ) return request->send(304);
     AsyncWebServerResponse *response = request->beginResponse_P( 200, HEADER_HTML, fileman_htm, fileman_htm_len );
-    response->addHeader( HEADER_LASTMODIFIED, date );
+    response->addHeader( HEADER_LASTMODIFIED, modifiedDate );
     request->send( response );
   });

@@ -207,9 +210,9 @@

     else if ( request->hasArg( "sensor" ) ) {
       if ( !logger.sensorCount() ) return request->send( 501, HEADER_HTML, NOT_PRESENT_ERROR_501 );
-      if ( !request->hasArg( "number" ) ) return request->send( 400, HEADER_HTML, "No sensornumber" );
+      if ( !request->hasArg( "number" ) ) return request->send( 400, HEADER_HTML, NO_SENSORNUMBER );
       uint8_t num = request->arg( "number" ).toInt();
-      if ( num >= logger.sensorCount() ) return request->send( 400, HEADER_HTML, "Invalid sensornumber" );
+      if ( num >= logger.sensorCount() ) return request->send( 400, HEADER_HTML, INVALID_SENSORNUMBER );
       sensorName_t name;
       sensorId_t id;
       AsyncResponseStream *response = request->beginResponseStream( HEADER_HTML );
@@ -240,9 +243,9 @@

     else if ( request->hasArg( "sensorname" ) ) {
       if ( !logger.sensorCount() ) return request->send( 501, HEADER_HTML, NOT_PRESENT_ERROR_501 );
-      if ( !request->hasArg( "number" ) ) return request->send( 400, HEADER_HTML, "No sensornumber" );
+      if ( !request->hasArg( "number" ) ) return request->send( 400, HEADER_HTML, NO_SENSORNUMBER );
       uint8_t num = request->arg( "number" ).toInt();
-      if ( num >= logger.sensorCount() ) return request->send( 400, HEADER_HTML, "Invalid sensornumber" );
+      if ( num >= logger.sensorCount() ) return request->send( 400, HEADER_HTML, INVALID_SENSORNUMBER );
       sensorName_t name;
       return request->send( 200, HEADER_HTML, logger.getSensorName( num, name ) );
     }
@@ -295,7 +298,7 @@
     }

     else {
-      return request->send( 400, HEADER_HTML, "Invalid option" );
+      return request->send( 400, HEADER_HTML, INVALID_OPTION );
     }
   });

@@ -358,24 +361,13 @@
     }

     else {
-      return request->send( 400, HEADER_HTML, "Invalid option" );
+      return request->send( 400, HEADER_HTML, INVALID_OPTION );
     }
   });

   server.on( "/api/setdevice", HTTP_POST, []( AsyncWebServerRequest * request ) {
     if ( !request->authenticate( WWW_USERNAME, preferences.getString( PASSWD_KEY_NVS, WWW_DEFAULT_PASSWD ).c_str() ) ) {
       return request->requestAuthentication();
-    }
-
-    if ( request->hasArg( "clearnvs" ) ) {
-      preferences.clear();
-      return request->send( 200, HEADER_HTML, "NVS cleared" );
-    }
-
-    if ( request->hasArg( "clearwifi" ) ) {
-      request->send( 200, HEADER_HTML, "WiFi data erased" );
-      WiFi.disconnect(true);
-      return;
     }

     else if ( request->hasArg( "hostname" ) ) {
@@ -495,7 +487,7 @@
         logger.stopTempLogging();
         return request->send( 200, HEADER_HTML, "OFF" );
       }
-      else return request->send( 400, HEADER_HTML, "Invalid option." );
+      else return request->send( 400, HEADER_HTML, INVALID_OPTION );
     }

     else if ( request->hasArg( "sensorerrorlogging" ) ) {
@@ -509,16 +501,16 @@
         logger.stopErrorLogging();
         return request->send( 200, HEADER_HTML, "OFF" );
       }
-      else return request->send( 400, HEADER_HTML, "Invalid option." );
+      else return request->send( 400, HEADER_HTML, INVALID_OPTION );
     }

     else if ( request->hasArg( "sensorname" ) ) {
       if ( request->arg( "sensorname" ).length() > sizeof( sensorName_t ) )
         return request->send( 400, HEADER_HTML, "Sensorname too long" );

-      if ( !request->hasArg( "number" ) ) return request->send( 400, HEADER_HTML, "No sensornumber" );
+      if ( !request->hasArg( "number" ) ) return request->send( 400, HEADER_HTML, NO_SENSORNUMBER );
       uint8_t num = request->arg( "number" ).toInt();
-      if ( num > logger.sensorCount() ) return request->send( 400, HEADER_HTML, "Invalid sensornumber" );
+      if ( num > logger.sensorCount() ) return request->send( 400, HEADER_HTML, INVALID_SENSORNUMBER );
       sensorId_t id;
       logger.getSensorId( num, id );
       if ( !logger.setSensorName( id, request->arg( "sensorname" ).c_str() ) )
@@ -586,7 +578,7 @@

     else
     {
-      return request->send( 400, HEADER_HTML, "Invalid option" );
+      return request->send( 400, HEADER_HTML, INVALID_OPTION );
     }
   });