Adding to repo
This commit is contained in:
		
							
								
								
									
										65
									
								
								00_prologue.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								00_prologue.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | /* | ||||||
|  |  * Libraries and global scope code | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <ESP8266WiFi.h> | ||||||
|  | #include <WiFiClientSecure.h> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
|  | BearSSL::WiFiClientSecure net; | ||||||
|  | time_t now; | ||||||
|  | unsigned long lastMillis = 0; | ||||||
|  |  | ||||||
|  | String devname;             // Device identifier for MQTT | ||||||
|  |  | ||||||
|  | struct Settings { | ||||||
|  |   String name = ""; | ||||||
|  |   String ip = ""; | ||||||
|  |   uint8_t mode = 0,           // Current animation effect | ||||||
|  |         offset = 0, | ||||||
|  |         brightness = 20;    // Default brightness (range 0-255) | ||||||
|  |   long color  = 0x00A4B3; // Starting color | ||||||
|  | } settings; | ||||||
|  |  | ||||||
|  | struct State { | ||||||
|  |   String text = ""; | ||||||
|  |   uint8_t mode = 0; | ||||||
|  |   long color  = 0x00A4B3; // Starting color | ||||||
|  | } state; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Debugging might be nice sometimes | ||||||
|  |  */ | ||||||
|  | #define USE_SERIAL //uncomment for Serial debugging statements | ||||||
|  | bool serialinitialised = false; | ||||||
|  |  | ||||||
|  | char printbuffer[100]; | ||||||
|  |  | ||||||
|  | void PRINT_SERIAL(const String& line) { | ||||||
|  | #ifdef USE_SERIAL | ||||||
|  |   if(!serialinitialised){ | ||||||
|  |     Serial.begin(115200); | ||||||
|  |     serialinitialised = true; | ||||||
|  |   } | ||||||
|  |   Serial.print(settings.ip + " " + settings.name + " "); | ||||||
|  |   Serial.print(line); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | void APPEND_SERIAL(const String& line) { | ||||||
|  | #ifdef USE_SERIAL | ||||||
|  |   Serial.print(line); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | void PRINTLN_SERIAL(const String& line) { | ||||||
|  | #ifdef USE_SERIAL | ||||||
|  |   PRINT_SERIAL(line); | ||||||
|  |   Serial.println(); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | void APPENDLN_SERIAL(const String& line) { | ||||||
|  | #ifdef USE_SERIAL | ||||||
|  |   Serial.println(line); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define NOP __asm__ __volatile__ ("nop\n") | ||||||
							
								
								
									
										1
									
								
								10_wlan_conf.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								10_wlan_conf.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | // Future use | ||||||
							
								
								
									
										1
									
								
								20_interface_webui.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								20_interface_webui.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | // Future use | ||||||
							
								
								
									
										158
									
								
								30_interface_mqtt.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								30_interface_mqtt.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | |||||||
|  | #ifdef ENABLE_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); | ||||||
|  | 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) { | ||||||
|  |   mqtt.subscribe(topic.c_str()); | ||||||
|  |   PRINTLN_SERIAL("Subscribed to " + topic); | ||||||
|  | } | ||||||
|  |    | ||||||
|  | void mqtt_publish(const String& topic, const String& message) { | ||||||
|  |   mqtt.publish(topic.c_str(), message.c_str()); | ||||||
|  |    PRINTLN_SERIAL("Published " + topic + ": " + message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Callback routine is called when a topic we subscribed to got a message | ||||||
|  |  */ | ||||||
|  | void mqtt_callback(char* topic, byte* payload, unsigned int length) { | ||||||
|  |   String fulltopic((char*)0); | ||||||
|  |   String shorttopic((char*)0); | ||||||
|  |   String message((char*)0); | ||||||
|  |    | ||||||
|  |   fulltopic.reserve(strlen(topic)); | ||||||
|  |   fulltopic = String(topic); | ||||||
|  |  | ||||||
|  |   // If deviceprefix is in topic, subtract it | ||||||
|  |   // Could do a similar thing for grouptopics if we implement them | ||||||
|  |   shorttopic.reserve(strlen(topic)); | ||||||
|  |   shorttopic = String(topic); | ||||||
|  |   shorttopic.replace(deviceprefix, ""); | ||||||
|  |  | ||||||
|  |   // Decode message into string | ||||||
|  |   message.reserve(length); | ||||||
|  |   for (int i = 0; i < length; i++) { | ||||||
|  |     message += (char)payload[i]; | ||||||
|  |   } | ||||||
|  |   PRINT_SERIAL(F("Received MQTT ")); | ||||||
|  |   APPEND_SERIAL(fulltopic); | ||||||
|  |   APPEND_SERIAL(F(": ")); | ||||||
|  |   APPENDLN_SERIAL(message); | ||||||
|  |  | ||||||
|  |   // Deal with global topic messages | ||||||
|  |   if(fulltopic.equals(MQTT_PREFIX "ping")) { | ||||||
|  |     mqtt_publish(deviceprefix + "pong", "This is " + settings.name + " v" + FW_VERSION + " at " + settings.ip); | ||||||
|  |  | ||||||
|  |   // Next quietly ignore all the things we send out ourselves | ||||||
|  |   } else if(shorttopic.equals(F("pong"))) {  | ||||||
|  |     // Ignore quietly | ||||||
|  |     //NOP; // delay 62.5ns on a 16MHz AtMega | ||||||
|  |   } else if(shorttopic.equals(F("log"))) {   | ||||||
|  |     // Ignore quietly | ||||||
|  |     //NOP; // delay 62.5ns on a 16MHz AtMega | ||||||
|  |  | ||||||
|  |   // And now to add a catchall to hand off to other module | ||||||
|  |   } else { | ||||||
|  |     module_message(shorttopic, message); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void WifiMQTTconnect() { | ||||||
|  |    | ||||||
|  |   if(WiFi.status() != WL_CONNECTED) { | ||||||
|  |     PRINTLN_SERIAL("Wifi not connected, connecting..."); | ||||||
|  |     WiFi.mode(WIFI_STA);  // Weird MQTT connection bug, https://github.com/knolleary/pubsubclient/issues/138#issuecomment-326113915   | ||||||
|  |     WiFi.begin(WLAN_SSID, WLAN_PASS); | ||||||
|  |     while (WiFi.status() != WL_CONNECTED) { | ||||||
|  |       PRINTLN_SERIAL("Waiting for Wifi..."); | ||||||
|  |       delay(500); | ||||||
|  |     } | ||||||
|  |     settings.ip = WiFi.localIP().toString(); | ||||||
|  |     PRINTLN_SERIAL("Wifi connected");   | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   PRINT_SERIAL("Setting time using SNTP"); | ||||||
|  |   configTime(-5 * 3600, 0, "pool.ntp.org", "time.nist.gov"); | ||||||
|  |   now = time(nullptr); | ||||||
|  |   while (now < 1510592825) { | ||||||
|  |     delay(500); | ||||||
|  |     APPEND_SERIAL("."); | ||||||
|  |     now = time(nullptr); | ||||||
|  |   } | ||||||
|  |   APPENDLN_SERIAL(" done!"); | ||||||
|  |   struct tm timeinfo; | ||||||
|  |   gmtime_r(&now, &timeinfo); | ||||||
|  |   PRINT_SERIAL("Current time: "); | ||||||
|  |   APPENDLN_SERIAL(asctime(&timeinfo)); | ||||||
|  |   net.setInsecure();  // verification options set to none | ||||||
|  |   mqtt.setServer(MQTT_SERVER, MQTT_SERVERPORT); | ||||||
|  |   mqtt.setCallback(mqtt_callback); | ||||||
|  |    | ||||||
|  |   if(!mqtt.connected()) { | ||||||
|  |     while (!mqtt.connected()) { | ||||||
|  |       PRINTLN_SERIAL("MQTT not connected, connecting..."); | ||||||
|  |              | ||||||
|  |       // 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 | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |        | ||||||
|  |     // (re)subscribe to the topics we need | ||||||
|  |     deviceprefix = MQTT_PREFIX; | ||||||
|  |     deviceprefix = deviceprefix + settings.name + "/"; | ||||||
|  |        | ||||||
|  |     mqtt_subscribe(MQTT_PREFIX "ping");   // global topic: send a ping, and we will respond with some device info | ||||||
|  |     mqtt_subscribe(deviceprefix + "#"); | ||||||
|  |     mqtt_publish(deviceprefix + "log", "Booting up " + settings.name + " running v" + FW_VERSION + " at " + settings.ip); | ||||||
|  |     mqtt_publish(deviceprefix + "log", "Free Heap: " + String(ESP.getFreeHeap())); | ||||||
|  |  | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mqtt_setup() { | ||||||
|  |   PRINTLN_SERIAL(devname + "initialising module MQTT"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mqtt_loop() { | ||||||
|  |   long currentMillis = millis(); | ||||||
|  |    | ||||||
|  |   // Check for MQTT instructions | ||||||
|  |   if(!mqtt.connected()) { | ||||||
|  |     WifiMQTTconnect(); | ||||||
|  |   } else { | ||||||
|  |     mqtt.loop(); | ||||||
|  |  | ||||||
|  |     // every 5 minutes (300000 milliseconds) | ||||||
|  |     if(currentMillis - logtimerMillis > 300000) { | ||||||
|  |       // reset timer | ||||||
|  |       logtimerMillis = currentMillis; | ||||||
|  |       // log something | ||||||
|  |       mqtt_publish(deviceprefix + "log", "Free Heap: " + String(ESP.getFreeHeap())); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										68
									
								
								60_module_sonoff.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								60_module_sonoff.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | #ifdef ENABLE_SONOFF | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Interface with other modules | ||||||
|  |  */ | ||||||
|  | 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"; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int sonoff_buttontoggle = 0;   // counter for the number of button presses | ||||||
|  | int sonoff_buttonstate = LOW;         // current state of the button | ||||||
|  | int sonoff_lastbuttonstate = LOW;     // previous state of the button | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Setup and loop code. Be cooperative! No delays, timers. | ||||||
|  |  */ | ||||||
|  |   | ||||||
|  | void sonoff_setup() { | ||||||
|  |   PRINTLN_SERIAL("initialising module Sonoff"); | ||||||
|  |      | ||||||
|  |   pinMode(SONOFF_LED, OUTPUT);      // Note that this LED is powered when voltage is LOW | ||||||
|  |   digitalWrite(SONOFF_LED, HIGH);   // turn the LED off (HIGH is the voltage level) | ||||||
|  |   pinMode(SONOFF_RELAY, OUTPUT);      // Note that this relay is powered when voltage is HIGH     | ||||||
|  |   digitalWrite(SONOFF_RELAY, LOW);   // turn the relay off (HIGH is the voltage level) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void sonoff_loop() { | ||||||
|  |   // This is a matter of last resort kind of thing: the built-in button will toggle power on or off, regardless of MQTT or network availability | ||||||
|  |   // As good measure, we might try reporting some kind of state when connecting later on. @@@FIXME@@@ | ||||||
|  |     | ||||||
|  |   // read the pushbutton input pin: | ||||||
|  |   sonoff_buttonstate = digitalRead(SONOFF_BUTTON); | ||||||
|  |  | ||||||
|  |   // compare the buttonState to its previous state | ||||||
|  |   if (sonoff_buttonstate != sonoff_lastbuttonstate) { | ||||||
|  |     // if the state has changed, increment the counter | ||||||
|  |     if (sonoff_buttonstate == LOW) { | ||||||
|  |       // if the current state is LOW then the button went from off to on: | ||||||
|  |       sonoff_buttontoggle = 1-sonoff_buttontoggle; | ||||||
|  |       PRINTLN_SERIAL("Button pressed"); | ||||||
|  |       if (sonoff_buttontoggle == 1) { | ||||||
|  |         newcmd("on"); | ||||||
|  |       } else { | ||||||
|  |         newcmd("off"); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       // if the current state is LOW then the button went from on to off: | ||||||
|  |       PRINTLN_SERIAL("Button released"); | ||||||
|  |     } | ||||||
|  |     // Delay a little bit to avoid bouncing | ||||||
|  |     delay(50); // @@@FIXME@@@ delays are undesirable! | ||||||
|  |   } | ||||||
|  |   // save the current state as the last state, for next time through the loop | ||||||
|  |   sonoff_lastbuttonstate = sonoff_buttonstate; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										221
									
								
								70_module_moon.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								70_module_moon.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,221 @@ | |||||||
|  | #ifdef ENABLE_MOON | ||||||
|  |  | ||||||
|  | // Needs refactoring | ||||||
|  | // Use https://adrianotiger.github.io/Neopixel-Effect-Generator/ for inspiration | ||||||
|  | // Read up on final comment at https://forum.arduino.cc/index.php?topic=534060.0 | ||||||
|  |  | ||||||
|  | #include <Adafruit_NeoPixel.h> | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Based on https://adrianotiger.github.io/Neopixel-Effect-Generator/ | ||||||
|  |  * TODO: Refactor for just a single string effect, less frills | ||||||
|  |  * Rainbow pattern | ||||||
|  |  */ | ||||||
|  | class Strip | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |   uint8_t   effect; | ||||||
|  |   uint8_t   effects; | ||||||
|  |   uint16_t  effStep; | ||||||
|  |   unsigned long effStart; | ||||||
|  |   Adafruit_NeoPixel strip; | ||||||
|  |   Strip(uint16_t leds, uint8_t pin, uint8_t toteffects) : strip(leds, pin, NEO_GRB + NEO_KHZ800) { | ||||||
|  |     effect = -1; | ||||||
|  |     effects = toteffects; | ||||||
|  |     Reset(); | ||||||
|  |   } | ||||||
|  |   void Reset(){ | ||||||
|  |     effStep = 0; | ||||||
|  |     effect = (effect + 1) % effects; | ||||||
|  |     effStart = millis(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct Loop | ||||||
|  | { | ||||||
|  |   uint8_t currentChild; | ||||||
|  |   uint8_t childs; | ||||||
|  |   bool timeBased; | ||||||
|  |   uint16_t cycles; | ||||||
|  |   uint16_t currentTime; | ||||||
|  |   Loop(uint8_t totchilds, bool timebased, uint16_t tottime) {currentTime=0;currentChild=0;childs=totchilds;timeBased=timebased;cycles=tottime;} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | Strip strip_0(7, MOON_PIXEL, 7 ); | ||||||
|  | struct Loop strip0loop0(1, false, 1); | ||||||
|  |  | ||||||
|  | //[GLOBAL_VARIABLES] | ||||||
|  | int speed = 200;  // started at 101 | ||||||
|  |  | ||||||
|  | uint8_t strip0_loop0_eff0() { | ||||||
|  |     // Strip ID: 0 - Effect: Rainbow - LEDS: 7 | ||||||
|  |     // Steps: 35 - Delay: 100 | ||||||
|  |     // Colors: 6 (255.255.0, 0.255.0, 0.0.255, 255.0.255, 255.0.0, 255.255.255, ) | ||||||
|  |     // Options: toLeft=true,  | ||||||
|  |   if(millis() - strip_0.effStart < 100 * (strip_0.effStep)) return 0x00; | ||||||
|  |   float factor1, factor2; | ||||||
|  |   uint16_t ind; | ||||||
|  |   for(uint16_t j=0;j<7;j++) { | ||||||
|  |     ind = strip_0.effStep + j * 1; | ||||||
|  |     switch((int)((ind % 35) / 5.833333333333333)) { | ||||||
|  |       case 0: factor1 = 1.0 - ((float)(ind % 35 - 0 * 5.833333333333333) / 5.833333333333333); | ||||||
|  |               factor2 = (float)((int)(ind - 0) % 35) / 5.833333333333333; | ||||||
|  |               strip_0.strip.setPixelColor(j, 255 * factor1 + 0 * factor2, 255 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2); | ||||||
|  |               break; | ||||||
|  |       case 1: factor1 = 1.0 - ((float)(ind % 35 - 1 * 5.833333333333333) / 5.833333333333333); | ||||||
|  |               factor2 = (float)((int)(ind - 5.833333333333333) % 35) / 5.833333333333333; | ||||||
|  |               strip_0.strip.setPixelColor(j, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2, 0 * factor1 + 255 * factor2); | ||||||
|  |               break; | ||||||
|  |       case 2: factor1 = 1.0 - ((float)(ind % 35 - 2 * 5.833333333333333) / 5.833333333333333); | ||||||
|  |               factor2 = (float)((int)(ind - 11.666666666666666) % 35) / 5.833333333333333; | ||||||
|  |               strip_0.strip.setPixelColor(j, 0 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 255 * factor2); | ||||||
|  |               break; | ||||||
|  |       case 3: factor1 = 1.0 - ((float)(ind % 35 - 3 * 5.833333333333333) / 5.833333333333333); | ||||||
|  |               factor2 = (float)((int)(ind - 17.5) % 35) / 5.833333333333333; | ||||||
|  |               strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2); | ||||||
|  |               break; | ||||||
|  |       case 4: factor1 = 1.0 - ((float)(ind % 35 - 4 * 5.833333333333333) / 5.833333333333333); | ||||||
|  |               factor2 = (float)((int)(ind - 23.333333333333332) % 35) / 5.833333333333333; | ||||||
|  |               strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 0 * factor1 + 255 * factor2, 0 * factor1 + 255 * factor2); | ||||||
|  |               break; | ||||||
|  |       case 5: factor1 = 1.0 - ((float)(ind % 35 - 5 * 5.833333333333333) / 5.833333333333333); | ||||||
|  |               factor2 = (float)((int)(ind - 29.166666666666664) % 35) / 5.833333333333333; | ||||||
|  |               strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 255 * factor1 + 255 * factor2, 255 * factor1 + 0 * factor2); | ||||||
|  |               break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   if(strip_0.effStep >= 35) {strip_0.Reset(); return 0x03; } | ||||||
|  |   else strip_0.effStep++; | ||||||
|  |   return 0x01; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t strip0_loop0() { | ||||||
|  |   uint8_t ret = 0x00; | ||||||
|  |   switch(strip0loop0.currentChild) { | ||||||
|  |     case 0:  | ||||||
|  |            ret = strip0_loop0_eff0();break; | ||||||
|  |   } | ||||||
|  |   if(ret & 0x02) { | ||||||
|  |     ret &= 0xfd; | ||||||
|  |     if(strip0loop0.currentChild + 1 >= strip0loop0.childs) { | ||||||
|  |       strip0loop0.currentChild = 0; | ||||||
|  |       if(++strip0loop0.currentTime >= strip0loop0.cycles) {strip0loop0.currentTime = 0; ret |= 0x02;} | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       strip0loop0.currentChild++; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void strips_loop() { | ||||||
|  |   if(strip0_loop0() & 0x01) | ||||||
|  |     strip_0.strip.show(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Interface with other modules | ||||||
|  |  */ | ||||||
|  |   | ||||||
|  | void newcmd(String cmd) { | ||||||
|  |   cmd.toLowerCase(); | ||||||
|  |   if(cmd.equals("off")) { | ||||||
|  |     settings.mode = 0; | ||||||
|  |     PRINTLN_SERIAL("Moon off"); | ||||||
|  |     strip_0.strip.setBrightness(0); // 0-255 | ||||||
|  |     state.text = "Moon switched off"; | ||||||
|  |   } | ||||||
|  |   if(cmd.equals("on")) { | ||||||
|  |     settings.mode = 1; | ||||||
|  |     PRINTLN_SERIAL("Moon switched on"); | ||||||
|  |     strip_0.strip.setBrightness(10); // 0-255 | ||||||
|  |     state.text = "Moon switched off"; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void module_message(const String& shorttopic, const String& message) { | ||||||
|  |   char msgptr[10]; | ||||||
|  |   String buffer; | ||||||
|  |  | ||||||
|  |   if(shorttopic.equalsIgnoreCase("cmd")) { | ||||||
|  |     if(message.equalsIgnoreCase("off")) { | ||||||
|  |       state.mode = 0; | ||||||
|  |       PRINTLN_SERIAL("Moon off"); | ||||||
|  |       strip_0.strip.setBrightness(0); // 0-255 | ||||||
|  |       state.text = "Moon switched off"; | ||||||
|  |     } else if(message.equalsIgnoreCase("on")) { | ||||||
|  |       state.mode = 1; | ||||||
|  |       PRINTLN_SERIAL("Moon switched on"); | ||||||
|  |       strip_0.strip.setBrightness(10); // 0-255 | ||||||
|  |       state.text = "Moon switched off"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } else if(shorttopic.equalsIgnoreCase("mode")) { | ||||||
|  |     if(message.equals("off")) { | ||||||
|  |       state.mode = 0; | ||||||
|  |       PRINTLN_SERIAL("Shutting off"); | ||||||
|  |     } else if(message.startsWith("0x")) { | ||||||
|  |       state.mode = 1; | ||||||
|  |       message.toCharArray(msgptr, 9); | ||||||
|  |       state.color = strtoll( &msgptr[2], NULL, 16); | ||||||
|  |       sprintf(printbuffer, "Switching to static color 0x%x", state.color); | ||||||
|  |       PRINTLN_SERIAL(printbuffer); | ||||||
|  |     } else if(message.startsWith("#")) { | ||||||
|  |       state.mode = 1; | ||||||
|  |       message.toCharArray(msgptr, 8); | ||||||
|  |       state.color = strtoll( &msgptr[1], NULL, 16); | ||||||
|  |       sprintf(printbuffer, "Switching to static color 0x%x", state.color); | ||||||
|  |       PRINTLN_SERIAL(printbuffer); | ||||||
|  |     } else if(message.equals("rainbow")) { | ||||||
|  |       state.mode = 2; | ||||||
|  |       PRINTLN_SERIAL("Switching to rainbow mode"); | ||||||
|  |     } | ||||||
|  |     mqtt_publish((deviceprefix + "log"), ("mode=" + String(state.mode)));  // @@@FIXME@@@ this needs to go elsewhere | ||||||
|  |      | ||||||
|  |   } else if(shorttopic.equalsIgnoreCase("brightness")) { | ||||||
|  |     PRINTLN_SERIAL("Setting brightness to " + message); | ||||||
|  |     settings.brightness = message.toInt(); | ||||||
|  |     strip_0.strip.setBrightness(settings.brightness); | ||||||
|  |     buffer = "brightness="; | ||||||
|  |     buffer.concat(settings.brightness); | ||||||
|  |     mqtt_publish((deviceprefix + "log"), buffer.c_str()); // @@@FIXME@@@ this needs to go elsewhere | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Setup and loop code. Be cooperative! No delays, timers. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | void moon_setup() { | ||||||
|  |   PRINTLN_SERIAL("initialising module Moon"); | ||||||
|  |   strip_0.strip.setBrightness(2); // 0-255 | ||||||
|  |   strip_0.strip.begin(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void moon_loop() { | ||||||
|  |   uint16_t r; | ||||||
|  |    | ||||||
|  |   switch(state.mode) { | ||||||
|  |     case 0:   // Off | ||||||
|  |       for(r=0; r< strip_0.strip.numPixels(); r++) { | ||||||
|  |         strip_0.strip.setPixelColor(r, 0,0,0); | ||||||
|  |       } | ||||||
|  |       strip_0.strip.show(); | ||||||
|  |       break;    | ||||||
|  |     case 1:   // Static color | ||||||
|  |       for(r=0; r< strip_0.strip.numPixels(); r++) { | ||||||
|  |         // Split the set color code up into r, g, b values | ||||||
|  |         int rval = state.color >> 16; | ||||||
|  |         int gval = state.color >> 8 & 0xFF; | ||||||
|  |         int bval = state.color & 0xFF; | ||||||
|  |         strip_0.strip.setPixelColor(r, rval, gval, bval); | ||||||
|  |       } | ||||||
|  |       strip_0.strip.show(); | ||||||
|  |       break; | ||||||
|  |    case 2:    // Rainbow | ||||||
|  |      strips_loop(); | ||||||
|  |      break; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										52
									
								
								99_setup_loop.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								99_setup_loop.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | /* | ||||||
|  |  * Setup and loop functions | ||||||
|  |  */ | ||||||
|  |   | ||||||
|  | /*************************** Sketch Code ************************************/ | ||||||
|  | void setup() { | ||||||
|  |   // Write banner | ||||||
|  |   PRINTLN_SERIAL(""); | ||||||
|  |   PRINTLN_SERIAL(""); | ||||||
|  |   PRINTLN_SERIAL("Booting " __FILE__ " built on " __DATE__ ", " __TIME__); | ||||||
|  |  | ||||||
|  |   // Generate device name from MAC | ||||||
|  |   PRINTLN_SERIAL("Network interface: " + WiFi.macAddress()); | ||||||
|  |   settings.name = DEVICEPREFIX; | ||||||
|  |   int devlen = settings.name.length(); | ||||||
|  |   settings.name = settings.name + "_" + WiFi.macAddress(); | ||||||
|  |   settings.name.remove(devlen+3, 1); | ||||||
|  |   settings.name.remove(devlen+5, 1); | ||||||
|  |   settings.name.remove(devlen+7, 1); | ||||||
|  |   settings.name.remove(devlen+9, 1); | ||||||
|  |   settings.name.remove(devlen+11, 1); | ||||||
|  |   // Only keep the last 6 characters from the MAC, hopefully that will be 'unique enough' in the LAN | ||||||
|  |   // 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"); | ||||||
|  |      | ||||||
|  |  | ||||||
|  | #ifdef ENABLE_MQTT | ||||||
|  |   mqtt_setup(); | ||||||
|  | #endif | ||||||
|  | #ifdef ENABLE_SONOFF | ||||||
|  |   sonoff_setup(); | ||||||
|  | #endif | ||||||
|  | #ifdef ENABLE_MOON | ||||||
|  |   moon_setup(); | ||||||
|  | #endif | ||||||
|  |   // Start the cooperative scheduler loops | ||||||
|  |   PRINTLN_SERIAL(devname + "done setting up, ready for main loop"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void loop() { | ||||||
|  | #ifdef ENABLE_MQTT | ||||||
|  |   mqtt_loop(); | ||||||
|  | #endif | ||||||
|  | #ifdef ENABLE_SONOFF | ||||||
|  |   sonoff_loop(); | ||||||
|  | #endif | ||||||
|  | #ifdef ENABLE_MOON | ||||||
|  |   moon_loop(); | ||||||
|  | #endif | ||||||
|  | } | ||||||
							
								
								
									
										70
									
								
								ESPGadget.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								ESPGadget.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | /*  | ||||||
|  |  *  ESP-SecureGadget by Florian Overkamp | ||||||
|  |  *  An ESP8266 based IoT/remote controlled gadget | ||||||
|  |  *  Design is modular so it can be used for things like Sonoff's but also for custom projects like Dex' Moon lamp | ||||||
|  |  *    | ||||||
|  |  *  Note that file ordering is important. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | // Done: | ||||||
|  | // Enable MQTT over SSL as per https://github.com/debsahu/ESP_MQTT_Secure/tree/master/ESP8266_MQTT_SSL/Arduino/ESP8266_PubSubClient_SSL | ||||||
|  | // Cooperative multitasking: Use timers always. Avoid delays where they can be avoided. | ||||||
|  | // Restructure mqtt topics a bit (report back with unique names for multiple fx lights, for instance) | ||||||
|  | // Implement versioning so that new firmware can be done OTA | ||||||
|  |  | ||||||
|  | // Todo: | ||||||
|  | // Split the wifi and mqtt code in order to support http interface | ||||||
|  | // 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 | ||||||
|  | // Implement more visual effects | ||||||
|  | // Implement speed controls for the visual effects | ||||||
|  | // Implement OTA https://www.bakke.online/index.php/2017/06/02/self-updating-ota-firmware-for-esp8266/ | ||||||
|  | // Refactoring sources: https://www.arduinolibraries.info/architectures/esp8266 | ||||||
|  | // Refactor String usage to minimize heap pollution. https://cpp4arduino.com/2018/11/21/eight-tips-to-use-the-string-class-efficiently.html | ||||||
|  |  | ||||||
|  | #define DEVICEPREFIX "Gadget" // Should be no longer than 8(?) chars or the MQTT clientId will become too long | ||||||
|  | const int FW_VERSION = 12; | ||||||
|  |  | ||||||
|  | // Version history: | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Compile time settings | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /************************* WiFi Access Point *********************************/ | ||||||
|  | #define WLAN_SSID       "MY_SSID" | ||||||
|  | #define WLAN_PASS       "MY_WIFIPASSWD" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /*********************** Select active modules *******************************/ | ||||||
|  | #define ENABLE_MQTT | ||||||
|  | //#define ENABLE_SONOFF | ||||||
|  | #define ENABLE_MOON | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifdef ENABLE_MQTT | ||||||
|  | /*************************** MQTT settings ***********************************/ | ||||||
|  | #define MQTT_SERVER      "MY_MQTT_SERVER" | ||||||
|  | #define MQTT_SERVERPORT  8883                   // 8883 for MQTTS | ||||||
|  | #define MQTT_USERNAME    "MY_MQTT_USER" | ||||||
|  | #define MQTT_PASSWORD    "MY_MQTT_PASSWD" | ||||||
|  | #define MQTT_PREFIX      "iot/"              // MQTT publish/subscribe will be prefixed by this (mind the trailing slash) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef ENABLE_SONOFF | ||||||
|  | /*************************** MQTT settings ***********************************/ | ||||||
|  | #define SONOFF_BUTTON 0 | ||||||
|  | #define SONOFF_RELAY 12 | ||||||
|  | #define SONOFF_LED 13 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef ENABLE_MOON | ||||||
|  | /*********************** NeoPixel Moon settings ******************************/ | ||||||
|  | #define MOON_PIXEL 4             // Which GPIO pin is the NeoPixel connected to | ||||||
|  | #define MOON_PIXEL_LEDS 7        // Amount of leds in the string | ||||||
|  | #endif | ||||||
|  |   | ||||||
		Reference in New Issue
	
	Block a user