summaryrefslogtreecommitdiffstats
path: root/oliver/dr_desk/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'oliver/dr_desk/src/main.cpp')
-rw-r--r--oliver/dr_desk/src/main.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/oliver/dr_desk/src/main.cpp b/oliver/dr_desk/src/main.cpp
new file mode 100644
index 0000000..706996b
--- /dev/null
+++ b/oliver/dr_desk/src/main.cpp
@@ -0,0 +1,315 @@
1#include <Arduino.h>
2#include <ESP8266mDNS.h>
3#include <PubSubClient.h>
4#include <WiFiManager.h>
5#include <FastLED.h>
6#include <ESP8266httpUpdate.h>
7
8#define _STR(s) #s
9#define STR(s) _STR(s)
10
11const char* mqtt_server = "192.168.1.2"; //MQTT Server IP, your home MQTT server eg Mosquitto on RPi, or some public MQTT
12const int mqtt_port = 1883; //MQTT Server PORT, default is 1883 but can be anything.
13
14const char* mqtt_pingall_sub = "home/pingall";
15const char* mqtt_pingall_pub = "home/pingall/response";
16
17#define MQTT_BASE "home/diningroom/desk"
18const char* mqtt_device_boot = MQTT_BASE "/device";
19
20const char* mqtt_mode_sub = MQTT_BASE;
21const char* mqtt_mode_pub = MQTT_BASE "/status";
22
23const char* mqtt_color_sub = MQTT_BASE "/color";
24const char* mqtt_color_pub = MQTT_BASE "/color/status";
25
26const char* mqtt_brightness_sub = MQTT_BASE "/brightness";
27const char* mqtt_brightness_pub = MQTT_BASE "/brightness/status";
28
29#define RGB_PIN 2
30#define RGB_NUM_LEDS 12
31#define RGB_CHIPSET WS2812B
32#define RGB_COLOR_ORDER GRB
33#define NUM(a) (sizeof(a) / sizeof(*a))
34
35#define FIRMWARE_VERSION 1
36//#define FIRMWARE_URL ""
37
38WiFiClient espClient;
39PubSubClient client(espClient);
40char convBuffer[10];
41CRGB leds[RGB_NUM_LEDS];
42
43void callback(char *topic, uint8_t *payload, unsigned int length);
44void blink();
45void checkFirmwareUpdate();
46
47void switchMode(struct mode *mode);
48void modeOff();
49void modeSolid();
50void modeRainbow();
51void modeRainbowFast();
52void modeStrobo();
53
54struct mode {
55 const char *name;
56 void (*func)();
57};
58
59struct mode modes[] = {
60 { "off", modeOff },
61 { "solid", modeSolid },
62 { "rainbow", modeRainbow },
63 { "rainbowfast", modeRainbowFast },
64 { "strobo", modeStrobo },
65};
66
67struct
68{
69 struct mode *mode = &modes[0];
70 uint32_t color = CRGB::Red;
71 uint8_t brightness = 204; // 80%
72} set;
73
74struct
75{
76 uint8_t brightness;
77 bool idle = false;
78} current;
79
80void setup()
81{
82 Serial.begin(115200);
83 pinMode(LED_BUILTIN, OUTPUT);
84
85 FastLED.addLeds<RGB_CHIPSET, RGB_PIN, RGB_COLOR_ORDER>(leds, RGB_NUM_LEDS);
86 current.brightness = set.brightness;
87 // update leds
88 set.mode->func();
89 FastLED.show();
90
91 WiFiManager wifiManager;
92 wifiManager.setConfigPortalTimeout(600);
93 Serial.printf_P(PSTR("Setting up WiFi\n"));
94 if (!wifiManager.autoConnect("ESP8266_DR_DESK")) {
95 Serial.printf_P(PSTR("Failed to connect and hit timeout\n"));
96 delay(5000);
97 ESP.restart();
98 }
99
100 yield();
101 checkFirmwareUpdate();
102 yield();
103
104 client.setServer(mqtt_server, mqtt_port);
105 client.setCallback(callback);
106
107 digitalWrite(LED_BUILTIN, HIGH); //Turn off led as default
108}
109
110void reconnect()
111{
112 // Loop until we're reconnected
113 while (!client.connected())
114 {
115 // Create a random client ID
116 String clientId = "ESP8266Client-";
117 clientId += String(random(0xffff), HEX);
118
119 // Attempt to connect
120 if (client.connect(clientId.c_str()))
121 {
122 // Once connected, publish an announcement...
123 client.publish(mqtt_device_boot, "connected");
124 // ... and resubscribe
125 client.subscribe(mqtt_pingall_sub);
126
127 // publish states
128 Serial.println(mqtt_mode_sub);
129 client.subscribe(mqtt_mode_sub);
130 client.publish(mqtt_mode_pub, set.mode->name, true);
131
132 Serial.println(mqtt_color_sub);
133 client.subscribe(mqtt_color_sub);
134 itoa(set.color, convBuffer, 10);
135 client.publish(mqtt_color_pub, convBuffer, true);
136
137 Serial.println(mqtt_brightness_sub);
138 client.subscribe(mqtt_brightness_sub);
139 itoa(map(set.brightness, 0, 255, 0, 100), convBuffer, 10);
140 client.publish(mqtt_brightness_pub, convBuffer, true);
141 }
142 else
143 {
144 // Wait 5 seconds before retrying
145 delay(5000);
146 }
147 }
148}
149
150void callback(char *topic, uint8_t *payload, unsigned int length)
151{
152 uint8_t c_payload[length];
153 memcpy(c_payload, payload, length);
154 c_payload[length] = '\0';
155
156 if (strcmp(topic, mqtt_pingall_sub) == 0)
157 {
158 blink();
159 client.publish(mqtt_pingall_pub,
160 "{\"diningroom_desk\":\"connected\"}");
161 }
162 else if (strcmp(topic, mqtt_mode_sub) == 0)
163 {
164 for (uint8_t i = 0; i < NUM(modes); ++i)
165 {
166 if (strcmp(modes[i].name, (char *)c_payload) != 0)
167 continue;
168 switchMode(&modes[i]);
169 break;
170 }
171 }
172 else if (strcmp(topic, mqtt_color_sub) == 0)
173 {
174 // switch from OFF to SOLID
175 if (set.mode == &modes[0])
176 switchMode(&modes[1]);
177
178 set.color = atoi((char *)c_payload);
179 current.idle = false;
180 itoa(set.color, convBuffer, 10);
181 client.publish(mqtt_color_pub, convBuffer, true);
182 }
183 else if (strcmp(topic, mqtt_brightness_sub) == 0)
184 {
185 set.brightness = map(atoi((char *)c_payload), 0, 100, 0, 255);
186 current.idle = false;
187 itoa(map(set.brightness, 0, 255, 0, 100), convBuffer, 10);
188 client.publish(mqtt_brightness_pub, convBuffer, true);
189 }
190}
191
192void blink()
193{
194 //Blink on received MQTT message
195 digitalWrite(LED_BUILTIN, LOW);
196 delay(25);
197 digitalWrite(LED_BUILTIN, HIGH);
198}
199
200void calcBrightness()
201{
202 #define FADE_STEP 10
203 if (current.brightness == set.brightness)
204 return;
205 int fadeAmount = set.brightness - current.brightness;
206 if (abs(fadeAmount) > FADE_STEP)
207 fadeAmount = (fadeAmount > 0) ? FADE_STEP : -FADE_STEP;
208 current.brightness += fadeAmount;
209}
210
211void switchMode(struct mode *mode)
212{
213 if (set.mode == mode)
214 return;
215 Serial.print("Switching mode to ");
216 Serial.println(mode->name);
217 set.mode = mode;
218 current.idle = false;
219 client.publish(mqtt_mode_pub, set.mode->name, true);
220}
221
222void modeOff()
223{
224 fill_solid(leds, RGB_NUM_LEDS, CRGB::Black);
225 current.idle = true;
226}
227
228void modeSolid()
229{
230 fill_solid(leds, RGB_NUM_LEDS, set.color);
231 calcBrightness();
232 nscale8_video(leds, RGB_NUM_LEDS, current.brightness);
233 current.idle = (current.brightness == set.brightness);
234}
235
236void modeRainbow()
237{
238 static CRGBPalette16 palette = RainbowColors_p;
239 static uint8_t hue = 0;
240 calcBrightness();
241 for (int i = 0; i < RGB_NUM_LEDS; ++i)
242 leds[i] = ColorFromPalette(palette, hue, current.brightness);
243 hue++;
244}
245
246void modeRainbowFast()
247{
248 static CRGBPalette16 palette = RainbowColors_p;
249 static uint8_t hue = 0;
250 calcBrightness();
251 for (int i = 0; i < RGB_NUM_LEDS; ++i)
252 leds[i] = ColorFromPalette(palette, hue, current.brightness);
253 hue+=5;
254}
255
256void modeStrobo()
257{
258 static bool state = 0;
259 if (set.color == CRGB::Black)
260 return;
261 fill_solid(leds, RGB_NUM_LEDS, (state) ? set.color : CRGB::Black);
262 calcBrightness();
263 nscale8_video(leds, RGB_NUM_LEDS, current.brightness);
264 state = !state;
265}
266
267void checkFirmwareUpdate()
268{
269 BearSSL::WiFiClientSecure update_client;
270 update_client.setInsecure();
271
272 client.publish(mqtt_device_boot, "fwupdate running");
273 ESPhttpUpdate.setLedPin(LED_BUILTIN, HIGH);
274 ESPhttpUpdate.rebootOnUpdate(true);
275 t_httpUpdate_return ret = ESPhttpUpdate.update(update_client, FIRMWARE_URL, STR(FIRMWARE_VERSION));
276 switch(ret)
277 {
278 case HTTP_UPDATE_FAILED:
279 {
280 Serial.printf_P(PSTR("HTTP_UPDATE_FAILED Error (%d): %s\n"),
281 ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
282 String tmp = String("fwupdate error: ") + ESPhttpUpdate.getLastErrorString();
283 client.publish(mqtt_device_boot, tmp.c_str());
284 }
285 break;
286
287 case HTTP_UPDATE_NO_UPDATES:
288 Serial.printf_P(PSTR("HTTP_UPDATE_NO_UPDATES\n"));
289 client.publish(mqtt_device_boot, "fwupdate noupdates");
290 break;
291
292 case HTTP_UPDATE_OK:
293 Serial.printf_P(PSTR("HTTP_UPDATE_OK\n"));
294 client.publish(mqtt_device_boot, "fwupdate ok");
295 break;
296 }
297}
298
299void loop()
300{
301 if (!client.connected())
302 reconnect();
303 client.loop();
304
305 EVERY_N_MILLISECONDS(100)
306 {
307 if (!current.idle)
308 {
309 set.mode->func();
310 FastLED.show();
311 }
312 if (!current.idle && current.brightness == 0)
313 current.idle = true;
314 }
315}