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