SugarBush - The Firmware

From The TinkerNet Wiki
Jump to navigation Jump to search

platformio.ini

Yes, this looks insanely complex...

The good news is that it's fairly straightforward once you wrap your head around what the various parts do.

  • [env] is fairly obvious. It's the definition of the hardware...
  • [common] is all the stuff that's common to all of the builds.
  • [env:WhatEver] blocks are the magic part. They define the differences between all of the various builds.

Note things like ${common.lib_deps} & ${common.build_flags}, These simply pull in the stuff from [common] for each individual build.

  1 [platformio]
  2 ; default_envs = SugarShack_Alert
  3 
  4 [env]
  5 platform = espressif8266
  6 ; For now, let's stick with the 8266 family MCUs
  7 board = d1_mini
  8 
  9 framework = arduino
 10 
 11 monitor_speed = 115200
 12 ; I like my serial comms fast.  (Without this line you get the default of 9600)
 13 
 14 [common]
 15 lib_deps =
 16         PubSubClient
 17         SimpleTimer
 18 
 19 build_flags =
 20         -D DEBUG        ; This is just plain handy.  Use it to turn debugging output on/off...
 21         ; -D DEBUG0       ; Show WiFi Debug info
 22         ; -D DEBUG1       ; Show extra WiFi Debug info
 23         ; -D DEBUG2       ; Show Sensor Debug info
 24         ; -D DEBUG3       ; Show extra Sensor Debug info
 25         ; -D DEBUG4       ; Show MQTT Debug info
 26         ; -D DEBUG5       ; Show Pixels Debug info
 27         -D WAP=2        ; Select the WiFi Access Point. (Might also select servers based on WAP choice)
 28                         ; WAP 0  = TinkerToys           (Test setup / Skeeter.tinkerNet.ca for MQTT)
 29                         ; WAP 1  = TinkerToysB          (Victoria Drive setup / SkyNet.tinkerNet.ca for MQTT)
 30                         ; WAP 2  = vanneck              (SugarBush setup / 192.168.0.222 for MQTT)
 31                         ; WAP 3  = paradise             (paradise / SkyNet.MillersParadise.ca for MQTT)
 32                         ; WAP 4+ = VictoriaDrive2B      ()
 33 
 34 [env:SugarShack_Alert]
 35         ; Little noisy blinkenbox
 36         ;     4 Neopixels hung off GPIO 12
 37         ;     Speaker hung off GPIO 14
 38         ;       Pixel 1 GRN = 25%
 39         ;       Pixel 2 GRN = 50%
 40         ;       Pixel 3 GRN = 75%
 41         ;       All 4 RED = Tank Full!
 42         ;       Pixel 4 slowly blinking:
 43         ;         GRN = OK
 44         ;         ORA = No MQTT
 45         ;         RED = No WiFi
 46 lib_deps =
 47         ${common.lib_deps}
 48         jfturcot/SimpleTimer
 49         Adafruit NeoPixel
 50 
 51 build_flags =
 52         ${common.build_flags}
 53         -D SS_Alert
 54         -D d_Pixels
 55         -D d_Audio
 56 
 57 [env:SugarShack_PHTank]
 58         ; Monitor depth probes in the PumpHouse Tank
 59         ;       ~25% Level: GPIO 4
 60         ;       ~50% Level: GPIO 5
 61         ;       ~75% Level: GPIO 12
 62         ;       100% Level: GPIO 13
 63         ; MIGHT need to do some sort of output for the relays on the lightbar
 64 lib_deps =
 65         ${common.lib_deps}
 66         jfturcot/SimpleTimer
 67 
 68 build_flags =
 69         ${common.build_flags}
 70         -D SS_PHTank
 71         -D s_Depth
 72 
 73 [env:SugarShack_PHLightBar]
 74         ; Control the lightbar in the PupHouse camera view
 75 lib_deps =
 76         ${common.lib_deps}
 77 
 78 build_flags =
 79         ${common.build_flags}
 80 
 81 [env:SugarShack_PHDumper]
 82         ; Monitor the dumper cycles
 83         ;       Switch on GPIO 4 (Maybe Hall-Effect...  Maybe Reed Switch...)
 84 lib_deps =
 85         ${common.lib_deps}
 86         jfturcot/SimpleTimer
 87 
 88 build_flags =
 89         ${common.build_flags}
 90         -D SS_Dumper
 91 
 92 [env:SugarShack_RO]
 93         ; Monitor the R/O system
 94 lib_deps =
 95         ${common.lib_deps}
 96 build_flags =
 97         ${common.build_flags}
 98 
 99 [env:SugarShack_Evaporator]
100         ; Monitor the levels in the Evaporator
101         ;       At least 2 depth probes
102         ;       Some NeoPixels
103         ;       Maybe a speaker
104 lib_deps =
105         ${common.lib_deps}
106 build_flags =
107         ${common.build_flags}
108 
109 [env:SugarShack_BottlingTank]
110         ; Monitor temperature in Bottling Tank
111         ;       Maybe depth too...
112 lib_deps =
113         ${common.lib_deps}
114 build_flags =
115         ${common.build_flags}
116 [env:SugarShack_Climate]
117         ; Monitor temperature, humidity & barometric pressure in the SugarShack
118 lib_deps =
119         ${common.lib_deps}
120 build_flags =
121         ${common.build_flags}
122 
123 [env:SugarShack_HoldingTanks]
124         ; Monitor depth probes in the Outside Holding Tanks
125 lib_deps =
126         ${common.lib_deps}
127 build_flags =
128         ${common.build_flags}
129 [env:SugarShack_FeedTank]
130         ; Monitor depth probes in the Feed Tank for the Evaporator
131         ;       (This unit will likely have more than 4 probes)
132 lib_deps =
133         ${common.lib_deps}
134 build_flags =
135         ${common.build_flags}

main.cpp

  1 /*
  2  * Monitor tele/TankLevel
  3  * 
  4  * If Tank == PumpHouse && Level == 0
  5  *  Turn off all lights & Screamer
  6  * If Tank == PumpHouse && Level >= 25
  7  *  Turn on Light 1
  8  * If Tank == PumpHouse && Level >= 50
  9  *  Turn on Light 2
 10  * If Tank == PumpHouse && Level >= 75
 11  *  Turn on Light 3
 12  * If Tank == PumpHouse && Level >= 100
 13  *  Turn on Light Screamer
 14  */
 15 
 16 /*
 17  * Maybe add a PAUSE button...
 18  *  (Disable the screamer for half an hour?)
 19  */
 20 
 21 #include "libraries.h"
 22 #include "functions.h"
 23 #include "externs.h"
 24 #include "TopSecret.h"
 25 
 26 SimpleTimer timer;
 27 
 28 #ifdef SS_Dumper
 29 int ReedPin = 4;
 30 int HallPin = 5;
 31 // int  Dumptime = 0;
 32 #endif // SS_Dumper
 33 
 34 void setup()
 35 {
 36   char debugTEXT[46];
 37 
 38   Serial.begin(115200);
 39   delay(500); // Delay to let the ESP get booted before sending out serial data
 40   debug_TitleScreen();
 41 
 42   // WiFi //////////////////////////////////////////////////////////////////////
 43   WiFi_init();
 44   debug_Separator();
 45 
 46   // MQTT //////////////////////////////////////////////////////////////////////
 47   MQTT_init();
 48 
 49 // Pixels ////////////////////////////////////////////////////////////////////
 50 #ifdef d_Pixels
 51 
 52   Pixels_init();
 53 
 54   for (int i = 0; i < PixelCount; i++)
 55   {
 56     SetAPixel(i, BLU);
 57   }
 58 
 59 #endif // d_Pixels
 60 
 61 // Depth Probes ////////////////////////////////////////////////////////////////
 62 #ifdef s_Depth
 63 
 64   Depth_init();
 65 
 66 #endif // d_Depth
 67 
 68 // Audio ////////////////////////////////////////////////////////////////
 69 #ifdef d_Audio
 70 
 71   Noise_init();
 72 
 73 #endif // d_Audio
 74 
 75   // Hall-Effect ///////////////////////////////////////////////////////////////
 76 #ifdef SS_Dumper
 77   debug_Separator();
 78   debug_SectionTitle("Hall Effect Sensor");
 79   pinMode(HallPin, INPUT);
 80   attachInterrupt(digitalPinToInterrupt(ReedPin), DumpDetect, CHANGE);
 81   sprintf(debugTEXT, "Reed Switch on pin %d", ReedPin);
 82   debug_LineOut(debugTEXT);
 83   attachInterrupt(digitalPinToInterrupt(HallPin), DumpDetect2, CHANGE);
 84   sprintf(debugTEXT, "Hall Effect Sensor on pin %d", HallPin);
 85   debug_LineOut(debugTEXT);
 86 #endif // SS_Dumper
 87 
 88   // Interval Timers ///////////////////////////////////////////////////////////
 89   debug_Separator();
 90   debug_SectionTitle("Interval Timers");
 91 
 92   timer.setInterval(20, MQTT_handler);
 93   debug_LineOut("MQTT");
 94 
 95   timer.setInterval(2000, WiFi_Test);
 96   debug_LineOut("WiFiCheck");
 97 
 98 #ifdef s_Depth
 99   timer.setInterval(5000, CheckProbes);
100   debug_LineOut("Check Probes");
101 #endif // s_Depth
102 
103   // READY /////////////////////////////////////////////////////////////////////
104   debug_ReadyScreen();
105 }
106 
107 void loop()
108 {
109   // Run the interval timers
110   // Running processes here in loop() is a synchronous flow.
111   // Running processes via the interval timers is assynchronous.
112   // If your actions don't depend directly on each other,
113   // synchronous flow makes no sense at all...
114   timer.run();
115 
116 #ifdef SS_Dumper
117   //   This is just here to give me console output while developing...
118   // Serial.print(".");
119   // delay(1000);
120 #endif // SS_Dumper
121 }

Debugging.cpp

 1 #include "libraries.h"
 2 #include "functions.h"
 3 
 4 void debug_TitleScreen()
 5 {
 6     Serial.printf("\n\n#================================================#\n");
 7 #ifdef SS_Alert
 8     Serial.printf("# SugarShack PumpHuose Alerter                   #\n");
 9     Serial.printf("# ESP With a Peizo & Pixels                      #\n");
10     Serial.printf("+------------------------------------------------+\n");
11 #endif //SS_Alert
12 #ifdef SS_PHTank
13     Serial.printf("# SugarShack PumpHuose Tank Monitor              #\n");
14     Serial.printf("+------------------------------------------------+\n");
15 #endif // SS_PHTank
16 #ifdef SS_Dumper
17     Serial.printf("# SugarShack PumpHuose Dumper Monitor            #\n");
18     Serial.printf("+------------------------------------------------+\n");
19 #endif // SS_Dumper
20     Serial.printf("# WiFi Enabled...                                #\n");
21     Serial.printf("# Speaks fluent MQTT...                          #\n");
22     Serial.printf("#================================================#\n");
23 }
24 
25 void debug_ReadyScreen()
26 {
27   Serial.printf("#================================================#\n");
28   Serial.printf("#                 Ready To Run.                  #\n");
29   Serial.printf("#================================================#\n");
30 }
31 
32 void debug_Separator()
33 {
34     Serial.printf("+------------------------------------------------+\n");
35 }
36 
37 void debug_SectionTitle(const char *Title)
38 {
39     Serial.printf("| %-46s |\n", Title);
40 }
41 
42 void debug_LineOut(const char *Line)
43 {
44     Serial.printf("|    %-43s |\n", Line);
45 }
46 
47 void debug_Action(const char *Line)
48 {
49     {
50         const char* SPACE = "                              ";
51         char BUFFER[100];
52         char BUFFER2[100];
53 
54         int BuffSize = (23 - (strlen(Line) / 2));
55 
56         strcpy(BUFFER, SPACE);
57         BUFFER[BuffSize] = '\0';
58 
59         sprintf(BUFFER2, "%s%s", BUFFER, Line);
60         Serial.printf("| %-46s |\n", BUFFER2);
61     }
62 }
63 
64 void debug_Trouble(const char *Line)
65 {
66     Serial.printf("* %-46s *\n", Line);
67 }
68 
69 void debug_Success(const char *Line)
70 {
71     Serial.printf("+ %-46s +\n", Line);
72 }
73 
74 void debug_ProgressBar0()
75 {
76         Serial.printf("| ");
77 }
78 void debug_ProgressBar1()
79 {
80             Serial.printf(".");
81 
82 }
83 void debug_ProgressBar2(int dotcount)
84 {
85         for (int i = 0; i < (47 - dotcount); i++)
86         {
87             Serial.printf(" ");
88         }
89         Serial.printf("|\n");
90 }

WiFi.cpp

  1 #include "libraries.h"
  2 #include "functions.h"
  3 
  4 ////////////////////////////////////////////////////////////////
  5 // These exist because the variables are declared elsewhere in
  6 // the project.  (Specifically, in TopSecret.h)
  7 extern char *WiFi_ssid;
  8 extern char *WiFi_password;
  9 extern char *WiFi_ClientName;
 10 ////////////////////////////////////////////////////////////////
 11 
 12 // Initialize the WiFi
 13 //
 14 // If we don't get a connection, we just keep trying forever.
 15 // Probably be an idea to eventually just give up, but most
 16 // ESP8266 devices are kinda useless without the connection...
 17 void WiFi_init()
 18 {
 19     char debugTEXT[46];
 20 
 21     WiFi.mode(WIFI_STA); // Connecting as a STATION
 22     WiFi.begin(WiFi_ssid, WiFi_password);
 23 
 24     // We start by connecting to a WiFi network
 25     sprintf(debugTEXT, "Connecting to: %-22s", WiFi_ssid);
 26     debug_SectionTitle(debugTEXT);
 27     {
 28         debug_ProgressBar0();
 29         int dotcount = 0;
 30         while (WiFi.status() != WL_CONNECTED) // Give it a bit of time to establish the WiFi connection...
 31         {
 32             dotcount++;
 33             delay(500);
 34             debug_ProgressBar1();
 35             if (dotcount >= 46)
 36             {
 37                 debug_ProgressBar2(dotcount);
 38                 dotcount = 0;
 39                 debug_ProgressBar0();
 40             }
 41             // SSD1306_Static("  no WiFi  ", 3);
 42         }
 43         debug_ProgressBar2(dotcount);
 44     }
 45     sprintf(debugTEXT, "WiFi connected on Channel %-2d", WiFi.channel());
 46     debug_LineOut(debugTEXT);
 47     sprintf(debugTEXT, "IP address: %-15s", WiFi.localIP().toString().c_str());
 48     debug_LineOut(debugTEXT);
 49 
 50     sprintf(debugTEXT, "My name is NOT %-22s", wifi_station_get_hostname());
 51     debug_LineOut(debugTEXT);
 52     sprintf(debugTEXT, "Really... It's %-22s", WiFi_ClientName);
 53     debug_LineOut(debugTEXT);
 54 
 55     // SSD1306_Static(" WiFi good ", 3);
 56 
 57     // Add "build_flags = -D DEBUG1" to your platformio.ini to get some extra WiFi stats
 58 #ifdef DEBUG1
 59     WiFi.printDiag(Serial);
 60     sprintf(debugTEXT, "RSSI: %d dBm", WiFi.RSSI());
 61     debug_LineOut(debugTEXT);
 62     sprintf(debugTEXT, "HostName: %-13s !!!! BULLSHIT !!!!", WiFi.hostname().c_str());
 63     debug_LineOut(debugTEXT);
 64     // Apparently, the ESP8266WiFi library does not actually support DHCP completely
 65     // { https://www.reddit.com/r/arduino/comments/d6mvc7/getting_hostname_from_dhcp_with_esp8266/ }
 66     // { https://github.com/esp8266/Arduino/issues/5695 }
 67 #endif
 68 }
 69 
 70 int WiFi_strength()
 71 {
 72     return (WiFi.RSSI());
 73 }
 74 
 75 int blip[3] = {000, 255, 000};  // GRN
 76 
 77 void WiFi_Test()  // Is Good...  Maybe
 78 {
 79     if (WiFi.status() != WL_CONNECTED)
 80     {
 81         Serial.println("Oh Poop!");
 82         blip[0] = 128;
 83         blip[1] = 128;
 84     }
 85     else
 86     {
 87     if (blip[1] == 255)
 88         blip[1] = 0;
 89     else
 90         blip[1] = 255;
 91     }
 92 #ifdef d_Pixels
 93     SetAPixel(3, blip);
 94 #endif // d_Pixels
 95 }
 96 
 97 int blip2[3] = {255, 000, 000}; // RED
 98 
 99 void WiFi_Test2() // Lost WiFi
100 {
101     if (blip2[0] == 255)
102         blip2[0] = 0;
103     else
104         blip2[0] = 255;
105 #ifdef d_Pixels
106     SetAPixel(3, blip2);
107 #endif // d_Pixels
108 }
109 
110 int blip3[3] = {255, 128, 000}; // ORA
111 
112 void WiFi_Test3() // lost MQTT
113 {
114     if (blip3[0] == 255)
115     {
116         blip3[0] = 0;
117         blip3[1] = 0;
118         blip3[2] = 0;
119     }
120     else
121     {
122         blip3[0] = 255;
123         blip3[1] = 128;
124         blip3[2] = 000;
125     }
126 #ifdef d_Pixels
127     SetAPixel(3, blip3);
128 #endif // d_Pixels
129 }

MQTT.cpp

  1 #include "libraries.h"
  2 #include "functions.h"
  3 #include "externs.h"
  4 
  5 #include "MQTT.h"
  6 
  7 WiFiClient espClient;
  8 PubSubClient MQTT_client(espClient);
  9 
 10 void MQTT_handler()
 11 {
 12     if (!MQTT_client.connected())
 13     {
 14         MQTT_reconnect();
 15     }
 16     MQTT_client.loop();
 17     // MQTT_beacon();
 18 }
 19 
 20 ////////////////////////////////////////////////////////////////
 21 // MQTT Functions
 22 ////////////////////////////////////////////////////////////////
 23 
 24 void MQTT_init()
 25 {
 26     MQTT_client.setServer(MQTT_broker, 1883);
 27     MQTT_client.setCallback(MQTT_callback);
 28 
 29     //  Build the topic names
 30     strcpy(MQTT_inTopic, "cmnd/"); //  in - Commands
 31     strcat(MQTT_inTopic, MQTT_ClientName);
 32     strcat(MQTT_inTopic, "/#");
 33     strcpy(MQTT_teleTopic, "tele/"); // out - Telemetry
 34     strcat(MQTT_teleTopic, MQTT_ClientName);
 35     strcpy(MQTT_statTopic, "stat/"); // out - Status
 36     strcat(MQTT_statTopic, MQTT_ClientName);
 37     strcpy(MQTT_outTopic, "noti/"); // out - Notifications
 38     strcat(MQTT_outTopic, MQTT_ClientName);
 39 
 40     MQTT_reconnect();
 41 }
 42 
 43 void MQTT_callback(char *topic, byte payload[100], int length)
 44 {
 45     char debugTEXT[46];
 46 
 47     char MQTT_msg_in[MQTT_BUFFER_SIZE];
 48     char *MQTT_command = strrchr(topic, '/');
 49     char CNasT[MQTT_BUFFER_SIZE];
 50     strcpy(CNasT, "/");
 51     strcat(CNasT, MQTT_ClientName); // "ClientName as Topic"
 52 
 53 #ifdef DEBUG4
 54     debug_SectionTitle("Message arrived");
 55     sprintf(debugTEXT, "Topic: %30s", MQTT_command);
 56     debug_LineOut(debugTEXT);
 57 #endif
 58 
 59     // if (length < MQTT_BUFFER_SIZE)
 60     // if (length < 63)
 61     // Messages 63 characters long or bigger make BOOM
 62     // with a "Soft WDT reset"
 63     // MQTT_BUFFER_SIZE is 100
 64     // I R cornfoozed...
 65     if (length < 59) // & now 59 is bad...  :|
 66     {
 67 
 68         MQTT_msg_in[0] = '\0'; // start with an empty string!
 69         for (int i = 0; i < length; i++)
 70         {
 71             MQTT_msg_in[i] = (char)payload[i];
 72             MQTT_msg_in[i + 1] = '\0';
 73         }
 74 
 75 #ifdef DEBUG4
 76         sprintf(debugTEXT, "Message: %28s", MQTT_msg_in);
 77         debug_LineOut(debugTEXT);
 78         sprintf(debugTEXT, "Message Size: %d", length);
 79         debug_LineOut(debugTEXT);
 80 #endif
 81 
 82         /////////////////////////////////////////////////////
 83         // Message handling goes here...
 84         /////////////////////////////////////////////////////
 85 
 86         if (strcmp(MQTT_command, CNasT) == 0) // MQTT_ClientName as Topic
 87         {
 88             // Missing topic
 89 #ifdef DEBUG4
 90             debug_Trouble("Missing topic...");
 91 #endif
 92         }
 93         else if (strcmp(MQTT_command, "/Level") == 0) // Tank Level
 94         {
 95             if (strcmp(MQTT_msg_in, "") == 0)
 96             {
 97 #ifdef DEBUG4
 98                 debug_Trouble("No actual message...");
 99 #endif
100                 // Might be a good way to request status...
101             }
102             else
103             {
104                 int level = atoi(MQTT_msg_in);
105                 sprintf(debugTEXT, "Tank Level is: %d", level);
106                 debug_Action(debugTEXT);
107 
108 #ifdef d_Pixels
109 
110                 if (level == 0)
111                 {
112                     SetAPixel(0, BLK);
113                     SetAPixel(1, BLK);
114                     SetAPixel(2, BLK);
115                     SetAPixel(3, BLK);
116                     STFU();
117                 }
118                 if (level >= 25)
119                 {
120                     SetAPixel(0, GRN);
121                     SetAPixel(1, BLK);
122                     SetAPixel(2, BLK);
123                     SetAPixel(3, BLK);
124                     STFU();
125                 }
126                 if (level >= 50)
127                 {
128 
129                     SetAPixel(1, GRN);
130                     SetAPixel(2, BLK);
131                     SetAPixel(3, BLK);
132                     STFU();
133                 }
134                 if (level >= 75)
135                 {
136                     SetAPixel(2, GRN);
137                     SetAPixel(3, BLK);
138                     STFU();
139                 }
140                 if (level >= 100)
141                 {
142                     SetAPixel(0, RED);
143                     SetAPixel(1, RED);
144                     SetAPixel(2, RED);
145                     SetAPixel(3, RED);
146                     ScreamBloodyMurder();
147                 }
148 #endif // d_Pixels
149             }
150         }
151         else if (strcmp(MQTT_command, "/Dump") == 0) // Dumper has dumped
152         {
153             Boop();
154         }
155         else if (strcmp(MQTT_command, "/Screen") == 0) // Screen control
156         {
157             if (strcmp(MQTT_msg_in, "") == 0)
158             {
159 #ifdef DEBUG4
160                 debug_Trouble("No actual message...");
161 #endif
162                 // Might be a good way to request status...
163             }
164             // else if ((strcmp(MQTT_msg_in, "1") == 0) || (strcmp(MQTT_msg_in, "ON") == 0))
165             // SSD1306_on();
166             // else if ((strcmp(MQTT_msg_in, "0") == 0) || (strcmp(MQTT_msg_in, "OFF") == 0))
167             // SSD1306_off();
168             // else if ((strcmp(MQTT_msg_in, "+") == 0) || (strcmp(MQTT_msg_in, "UP") == 0))
169             // SSD1306_Bright();
170             // else if ((strcmp(MQTT_msg_in, "-") == 0) || (strcmp(MQTT_msg_in, "DOWN") == 0))
171             // SSD1306_Dim();
172             else
173                 debug_Trouble("Say What?");
174         }
175         else
176         {
177 #ifdef DEBUG4
178             debug_Trouble("Dunno Whatcha want...");
179 #endif
180         }
181     }
182     else
183     {
184 #ifdef DEBUG4
185         debug_Trouble("But, it's TOO Bloody Big!");
186 #endif
187     }
188 }
189 
190 void MQTT_reconnect()
191 {
192     char debugTEXT[46];
193 
194     // Loop until we're reconnected
195     while (!MQTT_client.connected())
196     {
197         /////////////////////////////////////////////////////////////////////////////////////////////////
198         sprintf(debugTEXT, "WiFi:%d dBm", WiFi_strength());
199         debug_Action(debugTEXT);
200         /////////////////////////////////////////////////////////////////////////////////////////////////
201         debug_SectionTitle("Attempting MQTT connection...");
202 
203         // Create a random client ID
204         String clientId = MQTT_ClientName;
205         clientId += String(random(0xffff), HEX);
206 
207         // Attempt to connect
208         if (MQTT_client.connect(clientId.c_str()))
209         {
210             /////////////////////////////////////////////////////////////////////////////////////////////////
211             sprintf(debugTEXT, "WiFi:%d dBm", WiFi_strength());
212             debug_Action(debugTEXT);
213             /////////////////////////////////////////////////////////////////////////////////////////////////
214             // SSD1306_Static(" MQTT good ", 3);
215             // delay(500);
216             // SSD1306_Static("           ", 3);
217             sprintf(debugTEXT, "connected to %-24s", MQTT_broker);
218             debug_LineOut(debugTEXT);
219             sprintf(debugTEXT, "My Name:  %-27s", MQTT_ClientName);
220             debug_LineOut(debugTEXT);
221             // Once connected, publish an announcement...
222             char MQTT_statTopic_Device[100];
223             strcpy(MQTT_statTopic_Device, MQTT_statTopic);
224             strcat(MQTT_statTopic_Device, "/HELLO");
225             // MQTT_client.publish(MQTT_statTopic_Device, "world");
226             MQTT_client.publish(MQTT_statTopic_Device, WiFi_ssid);
227             // ... and resubscribe
228             MQTT_client.subscribe(MQTT_inTopic);
229         }
230         else
231         {
232             /////////////////////////////////////////////////////////////////////////////////////////////////
233             sprintf(debugTEXT, "WiFi:%d dBm", WiFi_strength());
234             debug_Action(debugTEXT);
235             /////////////////////////////////////////////////////////////////////////////////////////////////
236 
237             if (WiFi.status() != WL_CONNECTED)
238             {
239                 WiFi_Test2();
240                 debug_Trouble("UH OH!!!  No WiFi!!!");
241             }
242             else
243             {
244                 // SSD1306_Static("  no MQTT  ", 3);
245                 WiFi_Test3();
246                 debug_Trouble("UH OH!!!  No MQTT!!!");
247             }
248 
249             sprintf(debugTEXT, "failed, rc=%d", MQTT_client.state());
250             debug_Trouble(debugTEXT);
251             debug_Trouble("trying again in 2 seconds");
252             // Wait 5 seconds before retrying
253             delay(2000);
254         }
255     }
256 }
257 
258 void MQTT_beacon()
259 {
260     /* Beacon signal published at set interval to indicate the device
261    * is still powered up and actively connected to MQTT...
262    * A keepalive of sorts
263    * also updates state within MQTT so it can be captured for
264    * indicator light elsewhere
265    * &, as a bonus, it's sending the WiFi strength.
266    */
267     char MQTT_statTopic_Device[100];
268     char WiFiSignal[10];
269     strcpy(MQTT_statTopic_Device, MQTT_statTopic);
270     strcat(MQTT_statTopic_Device, "/WiFi_strength");
271     sprintf(WiFiSignal, "%d dBm", WiFi_strength());
272 #ifdef DEBUG0
273     debug_SectionTitle("WiFi:");
274     debug_LineOut(WiFiSignal);
275 #endif
276 
277     MQTT_client.publish(MQTT_statTopic_Device, WiFiSignal);
278     blinkLED(5);
279 
280 #ifdef DEBUG4
281     debug_Action("Beacon sent");
282 #endif
283 }
284 
285 void MQTT_Status(char const *Device, char const *Status) // Send status messages
286 {
287     char MQTT_statTopic_Device[100];
288     strcpy(MQTT_statTopic_Device, MQTT_statTopic);
289     strcat(MQTT_statTopic_Device, "/");
290     strcat(MQTT_statTopic_Device, Device);
291 
292 #ifdef DEBUG4
293     char debugTEXT[46];
294 
295     sprintf(debugTEXT, "}- %16s = %-16s -{", Device, Status);
296     debug_Trouble(debugTEXT);
297 #endif
298     MQTT_client.publish(MQTT_statTopic_Device, Status);
299 }
300 
301 void MQTT_SendTELE(const char *Topic, char *Message)
302 {
303     char MQTT_teleTopic_Device[100];
304     strcpy(MQTT_teleTopic_Device, MQTT_teleTopic);
305     strcat(MQTT_teleTopic_Device, "/");
306     strcat(MQTT_teleTopic_Device, Topic);
307     MQTT_client.publish(MQTT_teleTopic_Device, Message);
308 }
309 
310 void MQTT_SendSTAT(const char *Topic, char *Message)
311 {
312     char MQTT_statTopic_Device[100];
313     strcpy(MQTT_statTopic_Device, MQTT_statTopic);
314     strcat(MQTT_statTopic_Device, "/");
315     strcat(MQTT_statTopic_Device, Topic);
316     MQTT_client.publish(MQTT_statTopic_Device, Message);
317 }
318 
319 void MQTT_SendCMND(const char *Topic, char *Message)
320 {
321     char MQTT_statTopic_Device[100];
322     strcpy(MQTT_statTopic_Device, Topic);
323     // strcat(MQTT_statTopic_Device, "/");
324     // strcat(MQTT_statTopic_Device, Topic);
325     MQTT_client.publish(MQTT_statTopic_Device, Message);
326 }
327 
328 void HandleMessages()
329 {
330 }

Sensing

Depth.cpp

 1 #include "libraries.h"
 2 #include "functions.h"
 3 
 4 /*
 5  * Puplish to tele/TankLevel
 6  * 
 7  * If all probes are high
 8  *  publish {"Tank":"PumpHouse", "Level":0}
 9  * If bottom probe is low
10  *  publish {"Tank":"PumpHouse", "Level":25}
11  * If bottom probe is low
12  *  publish {"Tank":"PumpHouse", "Level":50}
13  * If bottom probe is low
14  *  publish {"Tank":"PumpHouse", "Level":75}
15  * If bottom probe is low
16  *  publish {"Tank":"PumpHouse", "Level":100}
17  */
18 
19 int Probe1 = 4; // no pullup...
20 int Probe2 = 5;
21 int Probe3 = 12; // no pullup...
22 int Probe4 = 13;
23 
24 void Depth_init()
25 {
26     char debugTEXT[46];
27     debug_Separator();
28     debug_SectionTitle("Configuring Depth Probes...");
29     // pinMode(Probe1, INPUT_PULLUP);
30     // pinMode(Probe2, INPUT_PULLUP);
31     // pinMode(Probe3, INPUT_PULLUP);
32     // pinMode(Probe4, INPUT_PULLUP);
33     pinMode(Probe1, INPUT);
34     pinMode(Probe2, INPUT);
35     pinMode(Probe3, INPUT);
36     pinMode(Probe4, INPUT);
37 #ifdef DEBUG
38     sprintf(debugTEXT, "Depth Probes on GPIOs %d %d %d & %d", Probe1, Probe2, Probe3, Probe4);
39     debug_LineOut(debugTEXT);
40 #endif
41 }
42 
43 void CheckProbes()
44 {
45     Serial.print("Probes: ");
46     Serial.print(digitalRead(Probe1));
47     Serial.print(" ");
48     Serial.print(digitalRead(Probe2));
49     Serial.print(" ");
50     Serial.print(digitalRead(Probe3));
51     Serial.print(" ");
52     Serial.print(digitalRead(Probe4));
53     Serial.println(" ");
54     if (!digitalRead(Probe4)) // 14   D5
55     {
56         MQTT_SendTELE("Level", "{\"Tank\":\"PumpHouse\", \"Level\":100}");
57         // MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "{\"Tank\":\"PumpHouse\", \"Level\":100}");
58         MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "100");
59         // Serial.println("PROBE 4");
60     }
61     // return 100;
62     else if (!digitalRead(Probe3)) // 13   D7
63     {
64         MQTT_SendTELE("Level", "{\"Tank\":\"PumpHouse\", \"Level\":75}");
65         // MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "{\"Tank\":\"PumpHouse\", \"Level\":75}");
66         MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "75");
67         // Serial.println("PROBE 3");
68     }
69     // return 75;
70     else if (!digitalRead(Probe2)) // 12   D6
71     {
72         MQTT_SendTELE("Level", "{\"Tank\":\"PumpHouse\", \"Level\":50}");
73         // MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "{\"Tank\":\"PumpHouse\", \"Level\":50}");
74         MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "50");
75         // Serial.println("PROBE 2");
76     }
77     // return 50;
78     else if (!digitalRead(Probe1)) // 5    D1
79     {
80         MQTT_SendTELE("Level", "{\"Tank\":\"PumpHouse\", \"Level\":25}");
81         // MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "{\"Tank\":\"PumpHouse\", \"Level\":25}");
82         MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "25");
83         // Serial.println("PROBE 1");
84     }
85     // return 25;
86     else
87     {
88         MQTT_SendTELE("Level", "{\"Tank\":\"PumpHouse\", \"Level\":0}");
89         // MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "{\"Tank\":\"PumpHouse\", \"Level\":0}");
90         MQTT_SendCMND("cmnd/SugarShack_Alarm/Level", "0");
91         // Serial.println("NO PROBE");
92     }
93     // return 0;
94 }

HallEffect.cpp

 1 #include "libraries.h"
 2 #include "functions.h"
 3 #include "externs.h"
 4 
 5 extern int ReedPin;
 6 extern int HallPin;
 7 
 8  unsigned long Dumptime;
 9  unsigned long TIK = 0;
10  unsigned long TOK = 0;
11 
12 volatile bool DiDiT;
13 
14 void ICACHE_RAM_ATTR DumpDetect()
15 {
16     char debugTEXT[46];
17 
18     TOK = millis();
19     Dumptime = (TOK - TIK) / 1000;
20     TIK = TOK;
21 
22     if ((digitalRead(ReedPin) == HIGH) && (!DiDiT))
23     {
24         DiDiT = true;
25         sprintf(debugTEXT, "{\"Device\":\"Dumper\",\"Type\":\"Reed A\",\"Time\":%d}", Dumptime);
26         MQTT_SendTELE("Cycle", debugTEXT);
27     Serial.printf("\nWoo Hoo!  It Dumped! (Reed A)\t(%d Seconds)", Dumptime);
28     }
29     else if ((digitalRead(ReedPin) == LOW) && (DiDiT))
30     {
31         DiDiT = false;
32         sprintf(debugTEXT, "{\"Device\":\"Dumper\",\"Type\":\"Reed B\",\"Time\":%d}", Dumptime);
33         MQTT_SendTELE("Cycle", debugTEXT);
34     Serial.printf("\nWoo Hoo!  It Dumped! (Reed B)\t(%d Seconds)", Dumptime);
35     }
36 }
37 
38 void ICACHE_RAM_ATTR DumpDetect2()
39 {
40     char debugTEXT[46];
41 
42     TOK = millis();
43     Dumptime = (TOK - TIK) / 1000;
44     TIK = TOK;
45 
46     sprintf(debugTEXT, "{\"Device\":\"Dumper\",\"Type\":\"Hall\",\"Time\":%d}", Dumptime);
47     MQTT_SendTELE("Cycle", debugTEXT);
48     Serial.printf("\nWoo Hoo!  It Dumped! (Hall)\t(%d Seconds)", Dumptime);
49 }

Alerts

Noise.cpp

 1 #include "libraries.h"
 2 #include "functions.h"
 3 #include "Noise.h"
 4 
 5 void Noise_init()
 6 {
 7   char debugTEXT[46];
 8 
 9   debug_Separator();
10   debug_SectionTitle("Configuring Audio");
11     sprintf(debugTEXT, "Configured speaker/piezo on pin %d", piezoPin);
12   debug_LineOut(debugTEXT);
13 }
14 
15 void ScreamBloodyMurder()
16 {
17     for (int counter = 0; counter < 5; counter++)
18     {
19         tone(piezoPin, 666);
20         delay(500);
21         noTone(piezoPin);
22         tone(piezoPin, 333);
23         delay(500);
24         noTone(piezoPin);
25     }
26     debug_Action("Holy POOP!  The Pumphouse is gonna flood!");
27 }
28 
29 void STFU()
30 {
31     noTone(piezoPin);
32 }
33 
34 void Boop()
35 {
36     tone(piezoPin, 111);
37         debug_Action("BOOP!");
38         delay(125);
39         noTone(piezoPin);
40 }#include "libraries.h"
41 #include "functions.h"
42 #include "Noise.h"
43 
44 void Noise_init()
45 {
46   char debugTEXT[46];
47 
48   debug_Separator();
49   debug_SectionTitle("Configuring Audio");
50     sprintf(debugTEXT, "Configured speaker/piezo on pin %d", piezoPin);
51   debug_LineOut(debugTEXT);
52 }
53 
54 void ScreamBloodyMurder()
55 {
56     for (int counter = 0; counter < 5; counter++)
57     {
58         tone(piezoPin, 666);
59         delay(500);
60         noTone(piezoPin);
61         tone(piezoPin, 333);
62         delay(500);
63         noTone(piezoPin);
64     }
65     debug_Action("Holy POOP!  The Pumphouse is gonna flood!");
66 }
67 
68 void STFU()
69 {
70     noTone(piezoPin);
71 }
72 
73 void Boop()
74 {
75     tone(piezoPin, 111);
76         debug_Action("BOOP!");
77         delay(125);
78         noTone(piezoPin);
79 }

Pixels.cpp

 1 #ifdef d_Pixels
 2 
 3 #include "libraries.h"
 4 #include "functions.h"
 5 #include "Pixels.h"
 6 
 7 void Pixels_init()
 8 {
 9   char debugTEXT[46];
10 
11   debug_Separator();
12   debug_SectionTitle("Configuring Pixels");
13 
14   pixels.begin();
15   for (int i = 0; i < PixelCount; i++)
16   {
17     SetAPixel(i, BLK);
18   } // strip.clear(); would be better if it worked right!
19   // for(int i = 0; i < 8; i++) { pixels1.setPixelColor(i, 0, 0, 0); }
20   pixels.setBrightness(PixelBright);
21   pixels.show();
22 
23   sprintf(debugTEXT, "Configured %d Pixels on pin %d", PixelCount, PixelPin);
24   debug_LineOut(debugTEXT);
25   sprintf(debugTEXT, "Brightness: %d", PixelBright);
26   debug_LineOut(debugTEXT);
27 }
28 
29 void SetAPixel(int PixelNumber, int Colour[])
30 {
31   char debugTEXT[46];
32   // Serial.printf(" -> %d, %d\n", PixelNumber, Colour);
33   pixels.setPixelColor(PixelNumber, Colour[0], Colour[1], Colour[2]);
34   pixels.show();
35 #ifdef DEBUG5
36   sprintf(debugTEXT, "Pixel %d Pixel colour: %03d,%03d,%03d", PixelNumber, Colour[0], Colour[1], Colour[2]);
37   debug_LineOut(debugTEXT);
38 #endif
39 }
40 
41 #endif // d_Pixels

Controls

Triggers.cpp

1 /*
2  * Simple GPIO pull downs to turn on relays...
3  */

Header Files

TopSecret.h

 1 #ifndef TOPSECRET_H
 2 #define TOPSECRET_H
 3 
 4 #ifdef SugarBush
 5 const char* WiFi_ClientName = "SugarShack_Climate";
 6 const char* MQTT_ClientName = "SugarShack_Climate";
 7 const char* DISP_Title = "SugarBush";
 8 #elif SugarBushDev
 9 const char* WiFi_ClientName = "SugarShack_Climate_Dev";
10 const char* MQTT_ClientName = "SugarShack_Climate_Dev";
11 const char* DISP_Title = "SugarBush";
12 #elif SS_Alert
13 const char* WiFi_ClientName = "SugarShack_Alarm";
14 const char* MQTT_ClientName = "SugarShack_Alarm";
15 const char* DISP_Title = "SugarBush";
16 #elif SS_PHTank
17 const char* WiFi_ClientName = "SugarShack_TankLevel";
18 const char* MQTT_ClientName = "SugarShack_TankLevel";
19 const char* DISP_Title = "SugarBush";
20 #elif SS_Dumper
21 const char* WiFi_ClientName = "SugarShack_Dumper";
22 const char* MQTT_ClientName = "SugarShack_Dumper";
23 const char* DISP_Title = "SugarBush";
24 #else
25 const char* WiFi_ClientName = "Test";
26 const char* MQTT_ClientName = "Test";
27 const char* DISP_Title = "Dude!";
28 #endif
29 
30 // WiFi
31 
32 #if WAP==0
33 const char* WiFi_ssid = "TinkerToys";
34 const char* WiFi_password = "Password";
35 const char* MQTT_broker = "skeeter.tinkernet.ca";
36 const char* MQTT_user = "";
37 const char* MQTT_pass = "";
38 
39 #elif WAP==1
40 const char* WiFi_ssid = "TinkerToysB";
41 const char* WiFi_password = "Password";
42 const char* MQTT_broker = "skynet.tinkernet.ca";
43 const char* MQTT_user = "";
44 const char* MQTT_pass = "";
45 #elif WAP==2
46 const char* WiFi_ssid = "vanneck";
47 const char* WiFi_password = "Password";
48 const char* MQTT_broker = "192.168.0.222";
49 const char* MQTT_user = "";
50 const char* MQTT_pass = "";
51 #elif WAP==3
52 const char* WiFi_ssid = "paradise";
53 const char* WiFi_password = "Password";
54 const char* MQTT_broker = "skynet.millersparadise.ca";
55 const char* MQTT_user = "";
56 const char* MQTT_pass = "";
57 #else
58 const char* WiFi_ssid = "VictoriaDrive2B";
59 const char* WiFi_password = "Password";
60 const char* MQTT_broker = "skynet.tinkernet.ca";
61 const char* MQTT_user = "";
62 const char* MQTT_pass = "";
63 #endif
64 
65 #endif // TOPSECRET_H

MQTT.h

 1 #ifndef MQTT_H
 2 #define MQTT_H
 3 
 4 #define MQTT_BUFFER_SIZE (100)       // This number is arbitrary
 5                                     // Topic can be up to 65,536 bytes
 6                                     // Message can be up to 268,435,456 bytes
 7 
 8 char MQTT_outTopic[MQTT_BUFFER_SIZE];
 9 char MQTT_inTopic[MQTT_BUFFER_SIZE];
10 char MQTT_teleTopic[MQTT_BUFFER_SIZE];
11 char MQTT_statTopic[MQTT_BUFFER_SIZE];
12 
13 char MQTT_msg_out[MQTT_BUFFER_SIZE *10];
14 
15 unsigned long beacon_timer = 0;
16 #define BEACON_INTERVAL 30000 // Timer interval for the "keep-alive" status beacon
17 
18 extern char *MQTT_broker;
19 extern char *MQTT_user;
20 extern char *MQTT_pass;
21 extern char *MQTT_ClientName;
22 
23 extern char *WiFi_ssid;
24 
25 #endif  // MQTT_H

functions.h

 1 #ifndef FUNCTIONS_H
 2 #define FUNCTIONS_H
 3 
 4 // WiFi ////////////////////////////////////////////////////////////////////////
 5 
 6 void WiFi_init();       // Initialize the WiFi
 7 int WiFi_strength();    // Check the signal strength
 8 void WiFi_Test();
 9 void WiFi_Test2();
10 void WiFi_Test3();
11 
12 // MQTT ////////////////////////////////////////////////////////////////////////
13 
14 void MQTT_init();
15 
16 void MQTT_callback(char *topic, byte *payload, int length);
17 void MQTT_reconnect();
18 void MQTT_beacon();
19 
20 void MQTT_handler();
21 
22 void MQTT_SendTELE(const char *Topic, char *Message);
23 void MQTT_SendSTAT(const char *Topic, char *Message);
24 void MQTT_SendCMND(const char *Topic, char *Message);
25 
26 void HandleMessages();
27 
28 // Supplimental Stuff //////////////////////////////////////////////////////////
29 
30 void blinkLED(int speed); // Just a little function to blink the LED
31 
32 // Debug ///////////////////////////////////////////////////////////////////////
33 void debug_TitleScreen();                   // Title block for the project
34 void debug_ReadyScreen();                   // Indicate setup is finished
35 void debug_Separator();                     // Make a line
36 void debug_SectionTitle(const char* Title); // Text at the left
37 void debug_LineOut(const char* Line);       // Text 3 characters inset
38 void debug_Action(const char* Line);        // Text centred
39 void debug_Trouble(const char* Line);       // 
40 void debug_Success(const char* Line);       // 
41 void debug_ProgressBar0();
42 void debug_ProgressBar1();
43 void debug_ProgressBar2(int dotcount);
44 
45 // Pixels //////////////////////////////////////////////////////////////////////
46 void Pixels_init();
47 void SetAPixel(int, int*);
48 
49 // Noise ///////////////////////////////////////////////////////////////////////
50 void Noise_init();
51 void ScreamBloodyMurder();
52 void STFU();
53 void Boop();
54 
55 // Depth Probes ////////////////////////////////////////////////////////////////
56 void Depth_init();
57 void CheckProbes();
58 
59 // Hall Effect Trigger /////////////////////////////////////////////////////////
60 void DumpDetect();
61 void DumpDetect2();
62 
63 #endif // FUNCTIONS_H

libraries.h

 1 #ifndef LIBRARIES_H
 2 #define LIBRARIES_H
 3 
 4 // WiFi ////////////////////////////////////////////////////////////////////////
 5 #include <ESP8266WiFi.h>
 6 
 7 // MQTT ////////////////////////////////////////////////////////////////////////
 8 #include <PubSubClient.h>
 9 
10 // Supplimental Stuff //////////////////////////////////////////////////////////
11 #include <SimpleTimer.h>
12 
13 #include <Wire.h>
14 
15 // Pixels //////////////////////////////////////////////////////////////////////
16 #ifdef d_Pixels
17 #include <Adafruit_NeoPixel.h>
18 #endif
19 
20 #endif // LIBRARIES_H

externs.h

 1 #ifndef EXTERNS_H
 2 #define EXTERNS_H
 3 
 4 #ifdef d_Pixels
 5 
 6 extern int RED[];
 7 extern int GRN[];
 8 extern int BLU[];
 9 extern int BLK[];
10 extern int YEL[];
11 extern int PixelCount;
12 
13 
14 #endif // d_Pixels
15 
16 #endif // EXTERNS_H

Noise.h

1 #ifndef NOISE_H
2 #define NOISE_H
3 
4 int piezoPin = 14;
5 
6 #endif // NOISE_H

Pixels.h

 1 #ifndef PIXELS_H
 2 #define PIXELS_H
 3 
 4 ///////////////////////////////////////////////////
 5 // Which pin is your neoPixel strip connected to
 6 #define PixelPin 12    // GPIO13 / Tarduino D7
 7 int PixelCount = 4;
 8 #define OBL 2
 9 
10 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PixelCount, PixelPin, NEO_GRB + NEO_KHZ800);
11 
12 
13 // Setup some constants for use in SetAPixel()
14 
15 //int Bright1 = 6;    // 0-255    //  No-Name strip
16 //int Bright2 = 1;    // 0-255    //  AdaFruit strip
17 
18 int PixelBright = 5;    // 0-255    //  No-Name strip
19 
20 // The colours:
21 int RED[] = {255, 000, 000};
22 int GRN[] = {000, 255, 000};
23 int BLU[] = {000, 000, 255};
24 int BLK[] = {000, 000, 000};
25 int YEL[] = {255, 255, 000};
26 
27 #endif // PIXELS_H