Compare commits
	
		
			5 Commits
		
	
	
		
			4b571786ef
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 629e5017ac | |||
| c367091adf | |||
| 65a1a3027b | |||
| f00091ec99 | |||
| 7bb74a43b9 | 
| @@ -2,11 +2,6 @@ | ||||
|  * Libraries and global scope code | ||||
|  */ | ||||
|  | ||||
| unsigned long lastMillis = 0; | ||||
|  | ||||
| String devname;             // Device identifier for MQTT | ||||
| char nodename[80] = "UNDEF"; | ||||
|  | ||||
| struct Settings { | ||||
|   String name = ""; | ||||
|   String ip = ""; | ||||
| @@ -14,6 +9,16 @@ struct Settings { | ||||
|  | ||||
| time_t now; | ||||
|  | ||||
| /* | ||||
|  * Modules will plug in to this thing via function pointers | ||||
|  */ | ||||
|  // see also http://www.gammon.com.au/forum/?id=12607 | ||||
| //void module_message(const String& shorttopic, const String& message) { //@@@@FIXME@@@@ instead of brightness, adjust mode? | ||||
| //void module_message(const String& shorttopic, const String& message) { | ||||
| // | ||||
| //} | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Debugging might be nice sometimes | ||||
|  */ | ||||
|   | ||||
| @@ -13,6 +13,8 @@ WiFiClientSecure net; | ||||
|  | ||||
| //BearSSL::WiFiClientSecure net; | ||||
|  | ||||
| unsigned long ota_lastcheck = 0; | ||||
|  | ||||
| // | ||||
| // If the WifiManager configuration portal is called, we can do stuff | ||||
| // | ||||
| @@ -21,9 +23,13 @@ WiFiClientSecure net; | ||||
| //} | ||||
|  | ||||
| void wifi_associate() { | ||||
|   char apname[80]; | ||||
|   settings.name.toCharArray(apname, 80); | ||||
|  | ||||
|   WifiManager.setConfigPortalTimeout(300); // If no configuration is done in 5 mins, exit/restart quietly   | ||||
|   if (WifiManager.autoConnect(nodename)) { // @@@FIXME@@@ we should really set a PSK for the AP (but in my brief testing it crashed the ESP, so what's up with that) | ||||
|     PRINTLN_SERIAL("Wifi connected");   | ||||
|   if (WifiManager.autoConnect(apname)) { // @@@FIXME@@@ we should really set a PSK for the AP (but in my brief testing it crashed the ESP, so what's up with that) | ||||
|     settings.ip = WiFi.localIP().toString(); | ||||
|     PRINTLN_SERIAL("Figured out my network \\O/");   | ||||
|  | ||||
|     //wificlient.setFingerprint(WTR_SHA1); | ||||
|     net.setInsecure();    // Do not check fingerprint | ||||
| @@ -45,31 +51,98 @@ void wifi_associate() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| void wifi_checkin() { | ||||
|       // 'Native' in WiFiClient because we need to push the entire clientbuffer in the API | ||||
|       // As a result copying the buffer in to a new String for HTTPClient library use is highly inefficient | ||||
|       if (!net.connect(OTA_SERVER, OTA_PORT)) { | ||||
|         Serial.println("HTTPS connection failed"); | ||||
|       } else { | ||||
|         Serial.println("HTTPS connection up"); | ||||
|  | ||||
|     // Check for firmware upgrades | ||||
|     String version = settings.name; | ||||
|     version.concat("-v"); | ||||
|     version.concat(FW_VERSION); | ||||
|  | ||||
|         String json = "{\"mac\":\"" + WiFi.macAddress() + "\","; | ||||
|         json.concat("\"version\":\"" + version + "\","); | ||||
|         json.concat("\"millis\":" + String(millis()) + "}"); | ||||
|          | ||||
|         // Send request to the server: | ||||
|         net.println("POST " OTA_CHECKIN " HTTP/1.1"); | ||||
|         net.println("Host: " OTA_SERVER); | ||||
|         net.println("Accept: */*"); | ||||
|         net.println("Content-Type: application/json"); | ||||
|         net.print("Content-Length: "); | ||||
|         net.println(json.length()); | ||||
|         net.println("Connection: close"); | ||||
|         net.println(); | ||||
|         // Construct the REST/JSON POST data | ||||
|         net.print(json); | ||||
|         Serial.println("POST sent"); | ||||
|        | ||||
|         while (net.connected()) { | ||||
|           String line = net.readStringUntil('\n'); | ||||
|           if (line == "\r") { | ||||
|             Serial.println("Headers received"); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|         String line = net.readStringUntil('\n'); | ||||
|         Serial.println("reply was:"); | ||||
|         Serial.println("=========="); | ||||
|         Serial.println(line); | ||||
|         Serial.println("=========="); | ||||
|         Serial.println("closing connection"); | ||||
|         net.stop();  // DISCONNECT FROM THE SERVER | ||||
|       } | ||||
| } | ||||
|  | ||||
| void wifi_setup() { | ||||
| //  WifiManager.setAPCallback(WifiManagerCallback); // Enable WifiManager callback to clear the cache | ||||
|   wifi_associate(); | ||||
| } | ||||
|  | ||||
| void wifi_loop() { | ||||
|  | ||||
|   if(WiFi.status() != WL_CONNECTED) { | ||||
|     PRINTLN_SERIAL("Wifi disconnected, trying to reconnect"); | ||||
|     wifi_associate(); | ||||
|   } | ||||
| } | ||||
| /* | ||||
|  | ||||
|   // OTA routine to be run once every X seconds | ||||
|   unsigned long ota_check = millis()/1000; | ||||
|   if((ota_lastcheck == 0) || ((ota_check - ota_lastcheck) > OTA_UPDATE_INTERVAL)) { | ||||
|     PRINTLN_SERIAL("Checking for OTA update"); | ||||
|  | ||||
|     // Check for firmware upgrades | ||||
|     Serial.println("Checking for firmware upgrade"); | ||||
|     t_httpUpdate_return ret = ESPhttpUpdate.update(wificlient, WTR_SERVER, WTR_SRVPORT, "/fw/", nodeversion); | ||||
|     String version = settings.name; | ||||
|     version.concat("-v"); | ||||
|     version.concat(FW_VERSION); | ||||
|         PRINTLN_SERIAL("net.status: " + String(net.status())); | ||||
|  | ||||
|     t_httpUpdate_return ret = ESPhttpUpdate.update(net, OTA_SERVER, OTA_PORT, OTA_URI, version); | ||||
|               PRINTLN_SERIAL("after httpupdate check net.status: " + String(net.status())); | ||||
|  | ||||
|     switch(ret) { | ||||
|     case HTTP_UPDATE_FAILED: // HTTP 403, 404 | ||||
|         Serial.printf("Firmware upgrade available, but update failed (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); | ||||
|         PRINT_SERIAL("Connection error, update failed "); | ||||
|         APPEND_SERIAL("(ERR "); | ||||
|         APPEND_SERIAL(String(ESPhttpUpdate.getLastError())); | ||||
|         APPEND_SERIAL(") "); | ||||
|         APPENDLN_SERIAL(ESPhttpUpdate.getLastErrorString().c_str()); | ||||
|         break; | ||||
|     case HTTP_UPDATE_NO_UPDATES: // HTTP 304 | ||||
|         Serial.println("No firmware upgrade available"); | ||||
|         PRINTLN_SERIAL("No firmware upgrade available"); | ||||
|         break; | ||||
|     case HTTP_UPDATE_OK: // HTTP 200 | ||||
|         Serial.println("Firmware upgrade available, upgraded ok."); // may not called we reboot the ESP | ||||
|         PRINTLN_SERIAL("Firmware upgrade available, upgraded ok."); // may not called we reboot the ESP | ||||
|         break; | ||||
|     } | ||||
|     ota_lastcheck = ota_check; | ||||
|      | ||||
| */ | ||||
|     // Check in with IoT server | ||||
|     wifi_checkin(); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,23 +1,13 @@ | ||||
| #ifdef ENABLE_MQTT | ||||
|  | ||||
|  | ||||
| // sample schema's to use: https://www.home-assistant.io/integrations/light.mqtt/ | ||||
|  | ||||
| /* | ||||
|  * Define a function newcmd in your module to be able to accept mqtt commands | ||||
|  * Syntax and parameters are like this: | ||||
|  */ | ||||
| void newcmd(String cmd); | ||||
| void module_message(const String& shorttopic, const String& message); | ||||
|  | ||||
| #include <PubSubClient.h> | ||||
|      | ||||
| // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. | ||||
|   PubSubClient mqtt(net); | ||||
| // Setup the MQTT client class by passing in the WiFi client | ||||
| PubSubClient mqtt(net); | ||||
| String deviceprefix; | ||||
|  | ||||
| const char* fingerprint = "EA:2A:2B:80:C1:00:57:35:66:26:FF:FC:FA:27:EA:5F:3D:91:5A:F9"; | ||||
|  | ||||
| long logtimerMillis = 0; | ||||
|  | ||||
| void mqtt_subscribe(const String& topic) { | ||||
| @@ -76,24 +66,37 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) { | ||||
| } | ||||
|  | ||||
| void mqtt_connect() { | ||||
| /*  bool success= false; | ||||
|   success = net.connect(MQTT_SERVER, MQTT_SERVERPORT); | ||||
|   if (success) { | ||||
|     PRINTLN_SERIAL("Connection complete, valid cert, valid fingerprint."); | ||||
|   } else { | ||||
|     PRINTLN_SERIAL("Connection failed!"); | ||||
|   } */ | ||||
|                 PRINTLN_SERIAL("prepare mqtt connect check net.status: " + String(net.status())); | ||||
|  | ||||
|   mqtt.setServer(MQTT_SERVER, MQTT_SERVERPORT); | ||||
|   mqtt.setCallback(mqtt_callback); | ||||
|                 PRINTLN_SERIAL("before mqtt connect check net.status: " + String(net.status())); | ||||
|  | ||||
|   if(!mqtt.connected()) { | ||||
|     while (!mqtt.connected()) { | ||||
|       PRINTLN_SERIAL("MQTT not connected, connecting..."); | ||||
|   while (!mqtt.connected()) { | ||||
|     PRINTLN_SERIAL("MQTT not connected, connecting..."); | ||||
|                           PRINTLN_SERIAL("while mqtt connecting check net.status: " + String(net.status())); | ||||
|  | ||||
|       // Attempt to connect | ||||
|       // Note - the default maximum packet size is 128 bytes. If the | ||||
|       // combined length of clientId, username and password exceed this, | ||||
|       // you will need to increase the value of MQTT_MAX_PACKET_SIZE in | ||||
|       // PubSubClient.h | ||||
|       if (mqtt.connect(settings.name.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) { | ||||
|         PRINTLN_SERIAL("MQTT connected"); | ||||
|       } else { | ||||
|         PRINTLN_SERIAL("MQTT connection failed, rc=" + String(mqtt.state()) + "..."); | ||||
|         delay(10000); // @@@FIXME@@@ delays are not cool | ||||
|       } | ||||
|     // Attempt to connect | ||||
|     // Note - the default maximum packet size is 128 bytes. If the | ||||
|     // combined length of clientId, username and password exceed this, | ||||
|     // you will need to increase the value of MQTT_MAX_PACKET_SIZE in | ||||
|     // PubSubClient.h | ||||
|     if (mqtt.connect(settings.name.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) { | ||||
|       PRINTLN_SERIAL("MQTT connected"); | ||||
|                                   PRINTLN_SERIAL("mqtt just connected check net.status: " + String(net.status())); | ||||
|  | ||||
|     } else { | ||||
|       PRINTLN_SERIAL("MQTT connection failed, rc=" + String(mqtt.state()) + "..."); | ||||
|                                            PRINTLN_SERIAL("mqtt failed connected check net.status: " + String(net.status())); | ||||
|                                             | ||||
|       delay(10000); // @@@FIXME@@@ delays are not cool | ||||
|     } | ||||
|        | ||||
|     // (re)subscribe to the topics we need | ||||
| @@ -104,12 +107,13 @@ void mqtt_connect() { | ||||
|     mqtt_subscribe(deviceprefix + "#"); | ||||
|     mqtt_publish(deviceprefix + "log", "Connected " + settings.name + " running v" + FW_VERSION + " at " + settings.ip); | ||||
|     mqtt_publish(deviceprefix + "log", "Free Heap: " + String(ESP.getFreeHeap())); | ||||
|                 PRINTLN_SERIAL("after mqtt connect check net.status: " + String(net.status())); | ||||
|  | ||||
|   } | ||||
| } | ||||
|  | ||||
| void mqtt_setup() { | ||||
|   PRINTLN_SERIAL(devname + "initialising module MQTT"); | ||||
|   PRINTLN_SERIAL("Initialising MQTT"); | ||||
| } | ||||
|  | ||||
| void mqtt_loop() { | ||||
|   | ||||
| @@ -6,14 +6,10 @@ | ||||
| void newcmd(String cmd) { | ||||
|   cmd.toLowerCase(); | ||||
|   if(cmd.equals("off")) { | ||||
|     settings.mode = 0; | ||||
|     PRINTLN_SERIAL("Lights off"); | ||||
|     state.text = "Sonoff switched off"; | ||||
|   } | ||||
|   if(cmd.equals("on")) { | ||||
|     settings.mode = 1; | ||||
|     PRINTLN_SERIAL("Lights on"); | ||||
|     state.text = "Sonoff switched off"; | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ void setup() { | ||||
|   // If we run in to trouble, this can painlessly be removed and the resulting device name will just be longer | ||||
|   settings.name.remove(devlen+1, 6); | ||||
|  | ||||
|   PRINTLN_SERIAL("device name generated"); | ||||
|   PRINTLN_SERIAL("Figured out who I am \\O/"); | ||||
|  | ||||
|   wifi_setup(); | ||||
|  | ||||
| @@ -37,7 +37,7 @@ void setup() { | ||||
|   moon_setup(); | ||||
| #endif | ||||
|   // Start the cooperative scheduler loops | ||||
|   PRINTLN_SERIAL(devname + "done setting up, ready for main loop"); | ||||
|   PRINTLN_SERIAL("Done setting up, ready for main loop \\O/"); | ||||
| } | ||||
|  | ||||
| void loop() { | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
| // Implement versioning so that new firmware can be done OTA | ||||
|  | ||||
| // Todo: | ||||
| // Split the wifi and mqtt code in order to support http interface | ||||
| // maybe: loading settings on SPIFFS or similar so we can create more generic firmware? https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout | ||||
| // Stay on the lookout for watchdog crashes, see also https://www.sigmdel.ca/michel/program/esp8266/arduino/watchdogs_en.html#ESP8266_WDT_RECOV | ||||
| // Keeps crashing after a few days. Dunno why. https://www.pieterverhees.nl/sparklesagarbage/esp8266/130-difference-between-esp-reset-and-esp-restart | ||||
| // More on this subject https://github.com/esp8266/Arduino/issues/1017 | ||||
| @@ -30,11 +30,12 @@ | ||||
| // (background: http://iot-bits.com/esp8266/esp8266-reset-causes-rst-cause/ | ||||
|  | ||||
| // Version history: | ||||
| // v14: Initial OTA support | ||||
| // v13: Refactored so config-settings are in config.h, move from Adafruit Neopixel to WS2812FX library | ||||
| // v12: Refactored inbound commands to hook in to the modules (module_message function), completed assimilation of (never-published) Moon_Connected sketch | ||||
| // v11: Simplified scheduler, back to cooperative looping | ||||
| // v10: First 'production' run. MQTT over TLS, but no OTA support. | ||||
| const int FW_VERSION = 13; | ||||
| const int FW_VERSION = 14; | ||||
|  | ||||
| // | ||||
| // Configuration settings | ||||
|   | ||||
		Reference in New Issue
	
	Block a user