SugarBush - The Firmware
Jump to navigation
Jump to search
Contents
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