jp112

SonoffHMLOX_Obi-Mod

Apr 30th, 2018
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.43 KB | None | 0 0
  1. /*
  2.   Generic ESP8285 Module
  3.   Flash Mode: DOUT
  4.   Flash Frequency: 40 MHz
  5.   CPU Frequency: 80 MHz
  6.   Flash Size: 1M (64k SPIFFS)
  7.   esp8266/arduino core 2.4.x - working 16.02.5328a8b
  8. */
  9. #include <Arduino.h>
  10. #include <ArduinoJson.h>
  11. #include <ArduinoOTA.h>
  12. #include <ESP8266HTTPClient.h>
  13. #include <ESP8266HTTPUpdateServer.h>
  14. #include <ESP8266mDNS.h>
  15. #include <ESP8266WebServer.h>
  16. #include <ESP8266WiFi.h>
  17. #include <FS.h>
  18. #include <HLW8012.h>
  19. #include <WiFiUdp.h>
  20. #include "WM.h"
  21. #include "css_global.h"
  22. #include "js_global.h"
  23. #include "js_pow.h"
  24. #include "js_fwupd.h"
  25.  
  26. const String FIRMWARE_VERSION = "1.0.23";
  27. //#define                       UDPDEBUG
  28. #define                       SERIALDEBUG
  29.  
  30. #define RelayPin              12 // 12
  31. #define RelayOnPin            12
  32. #define RelayOffPin            5
  33. #define UseSoftRelayState     true
  34.  
  35. #define SwitchPin             14 // 0
  36. #define SwitchGPIOPin14        0 // 14
  37. #define LEDPinSwitch           4 // 13
  38.  
  39. #define LEDPinPow             15
  40. #define SEL_PIN                5
  41. #define CF1_PIN               13
  42. #define CF_PIN                14
  43. #define MillisKeyBounce      100  //Millisekunden zwischen 2xtasten
  44. #define ConfigPortalTimeout  180  //Timeout (Sekunden) des AccessPoint-Modus
  45. #define HTTPTimeOut         1500  //Timeout (Millisekunden) für http requests
  46. #define IPSIZE                16
  47. #define VARIABLESIZE         255
  48. #define UDPPORT             6676
  49. #define KEYPRESSLONGMILLIS  1500 //Millisekunden für langen Tastendruck bei Sonoff Touch als Sender
  50.  
  51. const char GITHUB_REPO_URL[] PROGMEM = "https://api.github.com/repos/jp112sdl/SonoffHMLOX/releases/latest";
  52.  
  53. #ifdef UDPDEBUG
  54. const char * SYSLOGIP = "192.168.1.251";
  55. #define SYSLOGPORT          514
  56. #endif
  57.  
  58. enum BackendTypes_e {
  59.   BackendType_HomeMatic,
  60.   BackendType_Loxone
  61. };
  62.  
  63. enum SonoffModel_e {
  64.   SonoffModel_Switch,
  65.   SonoffModel_Pow,
  66.   SonoffModel_TouchAsSender
  67. };
  68.  
  69. enum RelayStates_e {
  70.   RELAYSTATE_OFF,
  71.   RELAYSTATE_ON
  72. };
  73.  
  74. enum TransmitStates_e {
  75.   NO_TRANSMITSTATE,
  76.   TRANSMITSTATE
  77. };
  78.  
  79. enum GPIO14Modes_e {
  80.   GPIO14Mode_OFF,
  81.   GPIO14Mode_KEY,
  82.   GPIO14Mode_SWITCH_ABSOLUT,
  83.   GPIO14Mode_SWITCH_TOGGLE
  84. };
  85.  
  86. struct globalconfig_t {
  87.   char ccuIP[IPSIZE]   = "";
  88.   char DeviceName[VARIABLESIZE] = "";
  89.   bool restoreOldRelayState = false;
  90.   bool lastRelayState = false;
  91.   int  MeasureInterval = 10;
  92.   byte BackendType = BackendType_HomeMatic;
  93.   byte SonoffModel = SonoffModel_Switch;
  94.   byte GPIO14Mode = GPIO14Mode_OFF;
  95.   bool GPIO14asSender = false;
  96.   String Hostname = "Sonoff";
  97.   bool LEDDisabled = false;
  98. } GlobalConfig;
  99.  
  100. struct hmconfig_t {
  101.   String ChannelName = "";
  102.   String ChannelNameSender = "";
  103.   char PowerVariableName[VARIABLESIZE] = "";
  104.   char EnergyCounterVariableName[VARIABLESIZE] = "";
  105. } HomeMaticConfig;
  106.  
  107. struct loxoneconfig_t {
  108.   char Username[VARIABLESIZE] = "";
  109.   char Password[VARIABLESIZE] = "";
  110.   char UDPPort[10] = "";
  111. } LoxoneConfig;
  112.  
  113. struct sonoffnetconfig_t {
  114.   char ip[IPSIZE]      = "0.0.0.0";
  115.   char netmask[IPSIZE] = "0.0.0.0";
  116.   char gw[IPSIZE]      = "0.0.0.0";
  117. } SonoffNetConfig;
  118.  
  119. enum _SyslogSeverity {
  120.   _slEmergency,
  121.   _slAlert,
  122.   _slCritical,
  123.   _slError,
  124.   _slWarning,
  125.   _slNotice,
  126.   _slInformational,
  127.   _slDebug
  128. };
  129.  
  130. const String bootConfigModeFilename = "bootcfg.mod";
  131. const String lastRelayStateFilename = "laststat.txt";
  132. const String configJsonFile         = "config.json";
  133. bool RelayState = LOW;
  134. bool KeyPress = false;
  135. bool WiFiConnected = false;
  136. bool LastSwitchGPIOPin14State = HIGH;
  137. bool CurrentSwitchGPIO14State = HIGH;
  138. byte LEDPin = 13;
  139. byte On = 1;
  140. byte Off = 0;
  141. unsigned long LastMillisKeyPress = 0;
  142. unsigned long TimerStartMillis = 0;
  143. unsigned long LastHlwMeasureMillis = 0;
  144. unsigned long LastHlwCollectMillis = 0;
  145. unsigned long KeyPressDownMillis = 0;
  146. unsigned long TimerSeconds = 0;
  147. unsigned long LastWiFiReconnectMillis = 0;
  148. bool OTAStart = false;
  149. bool UDPReady = false;
  150. bool startWifiManager = false;
  151. bool wm_shouldSaveConfig        = false;
  152. bool PRESS_LONGsent = false;
  153. bool softRelayState = Off;
  154. #define wifiManagerDebugOutput   true
  155.  
  156. ESP8266WebServer WebServer(80);
  157. ESP8266HTTPUpdateServer httpUpdater;
  158.  
  159. struct udp_t {
  160.   WiFiUDP UDP;
  161.   char incomingPacket[255];
  162. } UDPClient;
  163.  
  164. //HLW8012
  165. #define CURRENT_MODE                    HIGH
  166. #define CURRENT_RESISTOR                0.001
  167. #define VOLTAGE_RESISTOR_UPSTREAM       ( 5 * 470000 ) // Real: 2280k
  168. #define VOLTAGE_RESISTOR_DOWNSTREAM     ( 1000 ) // Real 1.009k
  169. #define defaultCurrentMultiplier        13670.9
  170. #define defaultVoltageMultiplier        441250.69
  171. #define defaultPowerMultiplier          12168954.98
  172. #define HLWMAXCOLLECTCOUNT              20 //Anzahl Werte für Mittelwertbildung
  173. #define HLWDISCARDNUM                   6  //Wieviele Werte sollen verworfen werden
  174. #define HLWCOLLECTINTERVAL              500 //ms
  175.  
  176. struct hlwvalues_ {
  177.   float ActivePower[HLWMAXCOLLECTCOUNT];
  178.   float ApparentPower[HLWMAXCOLLECTCOUNT];
  179.   float Voltage[HLWMAXCOLLECTCOUNT];
  180.   float Current[HLWMAXCOLLECTCOUNT];
  181.   int HlwCollectCounter = 0;
  182. } hlwvalues;
  183.  
  184. struct hlw8012value_t {
  185.   float voltage        = 0;
  186.   float current        = 0;
  187.   float powerw         = 0;
  188.   float powerva        = 0;
  189.   float energy_counter = 0;
  190. } hlw8012value;
  191.  
  192. struct hlw8012calibrationdata_t {
  193.   float CurrentMultiplier = defaultCurrentMultiplier;
  194.   float VoltageMultiplier = defaultVoltageMultiplier;
  195.   float PowerMultiplier  = defaultPowerMultiplier;
  196. } HLW8012Calibration;
  197.  
  198. HLW8012 hlw8012;
  199.  
  200. void ICACHE_RAM_ATTR hlw8012_cf1_interrupt() {
  201.   hlw8012.cf1_interrupt();
  202. }
  203. void ICACHE_RAM_ATTR hlw8012_cf_interrupt() {
  204.   hlw8012.cf_interrupt();
  205. }
  206.  
  207. void setup() {
  208.   Serial.begin(115200);
  209.   Serial.println("\nSonoff " + WiFi.macAddress() + " startet... (FW: " + FIRMWARE_VERSION + ")");
  210.   pinMode(LEDPinSwitch, OUTPUT);
  211.   pinMode(LEDPinPow,    OUTPUT);
  212.   pinMode(RelayPin,     OUTPUT);
  213.   pinMode(RelayOnPin,   OUTPUT);
  214.   pinMode(RelayOffPin,  OUTPUT);
  215.   pinMode(SwitchPin,    INPUT_PULLUP);
  216.  
  217.   Serial.println(F("Config-Modus durch bootConfigMode aktivieren? "));
  218.   if (SPIFFS.begin()) {
  219.     Serial.println(F("-> bootConfigModeFilename mounted file system"));
  220.     if (SPIFFS.exists("/" + bootConfigModeFilename)) {
  221.       startWifiManager = true;
  222.       Serial.println("-> " + bootConfigModeFilename + " existiert, starte Config-Modus");
  223.       SPIFFS.remove("/" + bootConfigModeFilename);
  224.       SPIFFS.end();
  225.     } else {
  226.       Serial.println("-> " + bootConfigModeFilename + " existiert NICHT");
  227.     }
  228.   } else {
  229.     Serial.println(F("-> Nein, SPIFFS mount fail!"));
  230.   }
  231.  
  232.   if (!startWifiManager) {
  233.     Serial.println(F("Config-Modus mit Taster aktivieren?"));
  234.     for (int i = 0; i < 20; i++) {
  235.       if (digitalRead(SwitchPin) == LOW) {
  236.         startWifiManager = true;
  237.         break;
  238.       }
  239.       digitalWrite(LEDPinSwitch, HIGH);
  240.       digitalWrite(LEDPinPow, LOW);
  241.       delay(100);
  242.       digitalWrite(LEDPinSwitch, LOW);
  243.       digitalWrite(LEDPinPow, HIGH);
  244.       delay(100);
  245.     }
  246.     Serial.println("Config-Modus " + String(((startWifiManager) ? "" : "nicht ")) + "aktiviert.");
  247.   }
  248.  
  249.   if (!loadSystemConfig()) startWifiManager = true;
  250.   //Ab hier ist die Config geladen und alle Variablen sind mit deren Werten belegt!
  251.  
  252.   if (doWifiConnect()) {
  253.     Serial.println(F("\nWLAN erfolgreich verbunden!"));
  254.     printWifiStatus();
  255.   } else ESP.restart();
  256.  
  257. #ifndef SERIALDEBUG
  258.   Serial.println("\nSerieller Debug nicht konfiguriert. Deshalb ist hier jetzt ENDE.\n");
  259.   delay(20); //to flush serial buffer
  260.   Serial.end();
  261. #endif
  262.  
  263.   switch (GlobalConfig.SonoffModel) {
  264.     case SonoffModel_Switch:
  265.       DEBUG("\nSonoff Modell = Switch / S20");
  266.       LEDPin = LEDPinSwitch;
  267.       On = HIGH;
  268.       Off = LOW;
  269.       pinMode(SwitchGPIOPin14, INPUT_PULLUP);
  270.       break;
  271.     case SonoffModel_Pow:
  272.       DEBUG("\nSonoff Modell = POW");
  273.       LEDPin = LEDPinPow;
  274.       On = HIGH;
  275.       Off = LOW;
  276.       hlw_init();
  277.       GlobalConfig.GPIO14Mode = GPIO14Mode_OFF;
  278.       break;
  279.     case SonoffModel_TouchAsSender:
  280.       DEBUG("\nSonoff Modell = Touch as Sender");
  281.       LEDPin = LEDPinSwitch;
  282.       On = LOW;
  283.       Off = HIGH;
  284.       GlobalConfig.GPIO14Mode = GPIO14Mode_OFF;
  285.       break;
  286.   }
  287.  
  288.   pinMode(LEDPin, OUTPUT);
  289.  
  290.   initWebServerHandler();
  291.  
  292.   httpUpdater.setup(&WebServer);
  293.   WebServer.begin();
  294.  
  295.   if (!MDNS.begin(GlobalConfig.Hostname.c_str())) {
  296.     DEBUG("Error setting up MDNS responder!");
  297.   }
  298.  
  299.   startOTAhandling();
  300.  
  301.   DEBUG("Starte UDP-Handler an Port " + String(UDPPORT) + "...");
  302.   UDPClient.UDP.begin(UDPPORT);
  303.   UDPReady = true;
  304.  
  305.   if (GlobalConfig.SonoffModel == SonoffModel_Pow)
  306.     switchLED(On);
  307.  
  308.   if (GlobalConfig.BackendType == BackendType_HomeMatic) {
  309.     reloadCUxDAddress(NO_TRANSMITSTATE);
  310.     byte tryCount = 0;
  311.     byte tryCountMax = 5;
  312.     while (HomeMaticConfig.ChannelName == "CUxD.") {
  313.       tryCount++;
  314.       DEBUG("Failed getting CUxD Device from HomeMaticConfig.ChannelName. Retry " + String(tryCount) + " / " + String(tryCountMax));
  315.       delay(1000);
  316.       reloadCUxDAddress(NO_TRANSMITSTATE);
  317.       if (tryCount == tryCountMax) break;
  318.     }
  319.   }
  320.  
  321.   GlobalConfig.lastRelayState = getLastRelayState();
  322.   if ((GlobalConfig.restoreOldRelayState) && GlobalConfig.lastRelayState == true) {
  323.     switchRelay(RELAYSTATE_ON, TRANSMITSTATE);
  324.   } else {
  325.     switchRelay(RELAYSTATE_OFF, TRANSMITSTATE);
  326.   }
  327.  
  328.   DEBUG(String(GlobalConfig.DeviceName) + " - Boot abgeschlossen, SSID = " + WiFi.SSID() + ", IP = " + String(IpAddress2String(WiFi.localIP())) + ", RSSI = " + WiFi.RSSI() + ", MAC = " + WiFi.macAddress(), "Setup", _slInformational);
  329. }
  330.  
  331. void loop() {
  332.   //Überlauf der millis() abfangen
  333.   if (LastMillisKeyPress > millis())
  334.     LastMillisKeyPress = millis();
  335.   if (TimerStartMillis > millis())
  336.     TimerStartMillis = millis();
  337.   if (LastHlwMeasureMillis > millis())
  338.     LastHlwMeasureMillis = millis();
  339.   if (LastHlwCollectMillis > millis())
  340.     LastHlwCollectMillis = millis();
  341.   if (LastWiFiReconnectMillis > millis())
  342.     LastWiFiReconnectMillis = millis();
  343.  
  344.   //Reconnect WiFi wenn nicht verbunden (alle 30 Sekunden)
  345.   if (WiFi.status() != WL_CONNECTED) {
  346.     WiFiConnected = false;
  347.     if (millis() - LastWiFiReconnectMillis > 30000) {
  348.       LastWiFiReconnectMillis = millis();
  349.       DEBUG("WiFi Connection lost! Reconnecting...");
  350.       WiFi.reconnect();
  351.     }
  352.   } else {
  353.     if (!WiFiConnected) {
  354.       DEBUG("WiFi reconnected!");
  355.       WiFiConnected = true;
  356.     }
  357.   }
  358.  
  359.   //auf OTA Anforderung reagieren
  360.   ArduinoOTA.handle();
  361.  
  362.   if (!OTAStart) {
  363.     //eingehende UDP Kommandos abarbeiten
  364.     String udpMessage = handleUDP();
  365.     if (udpMessage == "bootConfigMode")
  366.       setBootConfigMode;
  367.     if (udpMessage == "reboot")
  368.       ESP.restart();
  369.     if (udpMessage == "1" || udpMessage == "on")
  370.       switchRelay(RELAYSTATE_ON, NO_TRANSMITSTATE);
  371.     if (udpMessage == "0" || udpMessage == "off")
  372.       switchRelay(RELAYSTATE_OFF, NO_TRANSMITSTATE);
  373.     if (udpMessage == "2" || udpMessage == "toggle")
  374.       toggleRelay(false);
  375.     if (udpMessage.indexOf("1?t=") != -1) {
  376.       TimerSeconds = (udpMessage.substring(4, udpMessage.length())).toInt();
  377.       if (TimerSeconds > 0) {
  378.         TimerStartMillis = millis();
  379.         DEBUG("webSwitchRelayOn(), Timer aktiviert, Sekunden: " + String(TimerSeconds), "loop()", _slInformational);
  380.       } else {
  381.         DEBUG(F("webSwitchRelayOn(), Parameter, aber mit TimerSeconds = 0"), "loop()", _slInformational);
  382.       }
  383.       switchRelay(RELAYSTATE_ON, NO_TRANSMITSTATE);
  384.     }
  385.  
  386.     //eingehende HTTP Anfragen abarbeiten
  387.     WebServer.handleClient();
  388.  
  389.     CurrentSwitchGPIO14State = digitalRead(SwitchGPIOPin14);
  390.     //GPIO14 als Schalter
  391.     if (GlobalConfig.GPIO14Mode == GPIO14Mode_SWITCH_ABSOLUT || GlobalConfig.GPIO14Mode == GPIO14Mode_SWITCH_TOGGLE) {
  392.       if (CurrentSwitchGPIO14State != LastSwitchGPIOPin14State) {
  393.         DEBUG("GPIO14 neuer Status = " + String(CurrentSwitchGPIO14State), "loop()", _slInformational);
  394.         LastSwitchGPIOPin14State = CurrentSwitchGPIO14State;
  395.         if (GlobalConfig.GPIO14asSender) {
  396.           if (GlobalConfig.GPIO14Mode == GPIO14Mode_SWITCH_ABSOLUT) {
  397.             if (GlobalConfig.BackendType == BackendType_HomeMatic) setStateCUxD(HomeMaticConfig.ChannelNameSender + ".SET_STATE",  (!CurrentSwitchGPIO14State ? "1" : "0"));
  398.           }
  399.           if (GlobalConfig.GPIO14Mode == GPIO14Mode_SWITCH_TOGGLE) {
  400.             if (GlobalConfig.BackendType == BackendType_HomeMatic) {
  401.               String currentState = getStateCUxD(HomeMaticConfig.ChannelNameSender + ".STATE", "State()");
  402.               DEBUG("CUxD Switch currentState = " + String(currentState));
  403.               setStateCUxD(HomeMaticConfig.ChannelNameSender + ".SET_STATE",  (currentState == "false" ? "1" : "0"));
  404.             }
  405.           }
  406.  
  407.         } else {
  408.           if (GlobalConfig.GPIO14Mode == GPIO14Mode_SWITCH_ABSOLUT)
  409.             switchRelay(!CurrentSwitchGPIO14State, TRANSMITSTATE); //HIGH = off, LOW = on
  410.           if (GlobalConfig.GPIO14Mode == GPIO14Mode_SWITCH_TOGGLE)
  411.             toggleRelay(TRANSMITSTATE);
  412.         }
  413.       }
  414.     }
  415.  
  416.     //Tasterbedienung am Sonoff abarbeiten
  417.     if (digitalRead(SwitchPin) == LOW || (GlobalConfig.GPIO14Mode == GPIO14Mode_KEY && CurrentSwitchGPIO14State == LOW)) {
  418.       if (!KeyPress) {
  419.         KeyPressDownMillis = millis();
  420.         if (millis() - LastMillisKeyPress > MillisKeyBounce) {
  421.           LastMillisKeyPress = millis();
  422.           if (GlobalConfig.SonoffModel != SonoffModel_TouchAsSender && !GlobalConfig.GPIO14asSender) {
  423.             toggleRelay(TRANSMITSTATE);
  424.           } else {
  425.             switchLED(On);
  426.           }
  427.           KeyPress = true;
  428.         }
  429.       }
  430.  
  431.       if ((GlobalConfig.SonoffModel == SonoffModel_TouchAsSender || GlobalConfig.GPIO14asSender) && (millis() - KeyPressDownMillis) > KEYPRESSLONGMILLIS && !PRESS_LONGsent) {
  432.         //PRESS_LONG
  433.         DEBUG("Touch or GPIO14 as Sender: PRESS_LONG", "loop()", _slInformational);
  434.         if (GlobalConfig.BackendType == BackendType_HomeMatic) setStateCUxD(HomeMaticConfig.ChannelNameSender + ".PRESS_LONG", "true");
  435.         if (GlobalConfig.BackendType == BackendType_Loxone) sendLoxoneUDP(String(GlobalConfig.DeviceName) + ":1 = PRESS_LONG");
  436.         switchLED(Off);
  437.         PRESS_LONGsent = true;
  438.       }
  439.  
  440.     } else {
  441.       if (GlobalConfig.SonoffModel == SonoffModel_TouchAsSender || GlobalConfig.GPIO14asSender) {
  442.         if (KeyPress) {
  443.           if ((millis() - KeyPressDownMillis) < KEYPRESSLONGMILLIS) {
  444.             //PRESS_SHORT
  445.             DEBUG("Touch or GPIO14 as Sender: PRESS_SHORT", "loop()", _slInformational);
  446.             if (GlobalConfig.BackendType == BackendType_HomeMatic) setStateCUxD(HomeMaticConfig.ChannelNameSender + ".PRESS_SHORT", "true");
  447.             if (GlobalConfig.BackendType == BackendType_Loxone) sendLoxoneUDP(String(GlobalConfig.DeviceName) + ":1 = PRESS_SHORT");
  448.           }
  449.           switchLED(Off);
  450.         }
  451.       }
  452.       KeyPress = false;
  453.       PRESS_LONGsent = false;
  454.     }
  455.  
  456.     //Timer
  457.     if (TimerSeconds > 0 && millis() - TimerStartMillis > TimerSeconds * 1000) {
  458.       DEBUG(F("Timer abgelaufen. Schalte Relais aus."), "loop()", _slInformational);
  459.       switchRelay(RELAYSTATE_OFF, TRANSMITSTATE);
  460.     }
  461.  
  462.     //POW Handling
  463.     if (GlobalConfig.SonoffModel == SonoffModel_Pow)
  464.       handleHLW8012();
  465.  
  466.     //needed for UDP packet parser
  467.     delay(10);
  468.   }
  469. }
  470.  
  471. void switchRelay(bool toState, bool transmitState) {
  472.   RelayState = toState;
  473.   DEBUG("Switch Relay to " + String(toState) + " with transmitState = " + String(transmitState), "switchRelay()", _slInformational);
  474.  
  475.   if (toState == RELAYSTATE_OFF) {
  476.     TimerSeconds = 0;
  477.   }
  478.  
  479.   if (RelayState == On) {
  480.     digitalWrite(RelayOnPin, LOW);
  481.     delay(250);
  482.     digitalWrite(RelayOnPin, HIGH);
  483.   } else {
  484.     digitalWrite(RelayOffPin, LOW);
  485.     delay(250);
  486.     digitalWrite(RelayOffPin, HIGH);
  487.   }
  488.  
  489.   softRelayState = RelayState;
  490.  
  491.   //digitalWrite(RelayPin, RelayState);
  492.  
  493.   setLastRelayState(RelayState);
  494.  
  495.   if (transmitState) {
  496.     if (GlobalConfig.BackendType == BackendType_HomeMatic) setStateCUxD(HomeMaticConfig.ChannelName + ".SET_STATE", String(RelayState));
  497.     if (GlobalConfig.BackendType == BackendType_Loxone) sendLoxoneUDP(String(GlobalConfig.DeviceName) + "=" + String(RelayState));
  498.   }
  499.  
  500.   switchLED((RelayState ? On : Off));
  501.  
  502.   if (GlobalConfig.SonoffModel == SonoffModel_Pow) {
  503.     LastHlwCollectMillis = millis();
  504.     LastHlwMeasureMillis = millis();
  505.   }
  506. }
  507.  
  508. bool getRelayState() {
  509.   return (digitalRead(RelayPin) == RELAYSTATE_ON);
  510. }
  511.  
  512. void toggleRelay(bool transmitState) {
  513.   TimerSeconds = 0;
  514.   if ( (UseSoftRelayState && softRelayState == On) || digitalRead(RelayPin) == LOW) {
  515.     switchRelay(RELAYSTATE_ON, transmitState);
  516.   } else  {
  517.     switchRelay(RELAYSTATE_OFF, transmitState);
  518.   }
  519. }
  520.  
  521. void switchLED(bool State) {
  522.   if ((GlobalConfig.SonoffModel == SonoffModel_Switch || GlobalConfig.SonoffModel == SonoffModel_TouchAsSender) && GlobalConfig.LEDDisabled) {
  523.     digitalWrite(LEDPin, Off);
  524.   } else {
  525.     digitalWrite(LEDPin, State);
  526.   }
  527. }
  528.  
  529. void blinkLED(int count) {
  530.   byte oldState = digitalRead(LEDPin);
  531.   delay(100);
  532.   for (int i = 0; i < count; i++) {
  533.     switchLED(!oldState);
  534.     delay(100);
  535.     switchLED(oldState);
  536.     delay(100);
  537.   }
  538.   delay(200);
  539. }
  540.  
  541. String IpAddress2String(const IPAddress& ipAddress) {
  542.   return String(ipAddress[0]) + String(".") + \
  543.          String(ipAddress[1]) + String(".") + \
  544.          String(ipAddress[2]) + String(".") + \
  545.          String(ipAddress[3]);
  546. }
Advertisement
Add Comment
Please, Sign In to add comment