summaryrefslogtreecommitdiffstats
path: root/oliver/dr_desk/src/dr_desk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'oliver/dr_desk/src/dr_desk.cpp')
-rw-r--r--oliver/dr_desk/src/dr_desk.cpp287
1 files changed, 287 insertions, 0 deletions
diff --git a/oliver/dr_desk/src/dr_desk.cpp b/oliver/dr_desk/src/dr_desk.cpp
new file mode 100644
index 0000000..46bf8eb
--- /dev/null
+++ b/oliver/dr_desk/src/dr_desk.cpp
@@ -0,0 +1,287 @@
1#include <Arduino.h>
2#include <ESP8266mDNS.h>
3#include <ArduinoOTA.h>
4#include <PubSubClient.h>
5#include <WiFiManager.h>
6#include <FastLED.h>
7#include "secrets.h"
8
9const char* autoconf_ssid = AUTOCONF_SSID; //AP name for WiFi setup AP which your ESP will open when not able to connect to other WiFi
10const char* autoconf_pwd = AUTOCONF_PASSWORD; // AP password so noone else can connect to the ESP in case your router fails
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
35WiFiClient espClient;
36PubSubClient client(espClient);
37char convBuffer[10];
38CRGB leds[RGB_NUM_LEDS];
39
40void switchMode(struct mode *mode);
41void modeOff();
42void modeSolid();
43void modeRainbow();
44void modeRainbowFast();
45void modeStrobo();
46
47struct mode {
48 const char *name;
49 void (*func)();
50};
51
52struct mode modes[] = {
53 { "off", modeOff },
54 { "solid", modeSolid },
55 { "rainbow", modeRainbow },
56 { "rainbowfast", modeRainbowFast },
57 { "strobo", modeStrobo },
58};
59
60struct
61{
62 struct mode *mode = &modes[0];
63 uint32_t color = CRGB::Red;
64 uint8_t brightness = 204; // 80%
65} set;
66
67struct
68{
69 uint8_t brightness;
70 bool idle = false;
71} current;
72
73void setup()
74{
75 Serial.begin(115200);
76 pinMode(BUILTIN_LED, OUTPUT);
77
78 FastLED.addLeds<RGB_CHIPSET, RGB_PIN, RGB_COLOR_ORDER>(leds, RGB_NUM_LEDS);
79 current.brightness = set.brightness;
80 // update leds
81 set.mode->func();
82 FastLED.show();
83
84 WiFiManager wifiManager;
85 wifiManager.autoConnect(autoconf_ssid, autoconf_pwd);
86
87 setup_ota();
88
89 client.setServer(mqtt_server, mqtt_port);
90 client.setCallback(callback);
91
92 digitalWrite(BUILTIN_LED, HIGH); //Turn off led as default
93}
94
95void setup_ota()
96{
97 // Set OTA Password, and change it in platformio.ini
98 ArduinoOTA.setPassword(OTA_PASSWORD);
99 ArduinoOTA.onStart([]() {});
100 ArduinoOTA.onEnd([]() {});
101 ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {});
102 ArduinoOTA.onError([](ota_error_t error)
103 {
104 if (error == OTA_AUTH_ERROR); // Auth failed
105 else if (error == OTA_BEGIN_ERROR); // Begin failed
106 else if (error == OTA_CONNECT_ERROR); // Connect failed
107 else if (error == OTA_RECEIVE_ERROR); // Receive failed
108 else if (error == OTA_END_ERROR); // End failed
109 });
110 ArduinoOTA.begin();
111}
112
113void reconnect()
114{
115 // Loop until we're reconnected
116 while (!client.connected())
117 {
118 // Create a random client ID
119 String clientId = "ESP8266Client-";
120 clientId += String(random(0xffff), HEX);
121
122 // Attempt to connect
123 if (client.connect(clientId.c_str()))
124 {
125 // Once connected, publish an announcement...
126 client.publish(mqtt_device_boot, "connected");
127 // ... and resubscribe
128 client.subscribe(mqtt_pingall_sub);
129
130 // publish states
131 Serial.println(mqtt_mode_sub);
132 client.subscribe(mqtt_mode_sub);
133 client.publish(mqtt_mode_pub, set.mode->name, true);
134
135 Serial.println(mqtt_color_sub);
136 client.subscribe(mqtt_color_sub);
137 itoa(set.color, convBuffer, 10);
138 client.publish(mqtt_color_pub, convBuffer, true);
139
140 Serial.println(mqtt_brightness_sub);
141 client.subscribe(mqtt_brightness_sub);
142 itoa(map(set.brightness, 0, 255, 0, 100), convBuffer, 10);
143 client.publish(mqtt_brightness_pub, convBuffer, true);
144 }
145 else
146 {
147 // Wait 5 seconds before retrying
148 delay(5000);
149 }
150 }
151}
152
153void callback(char *topic, uint8_t *payload, unsigned int length)
154{
155 uint8_t c_payload[length];
156 memcpy(c_payload, payload, length);
157 c_payload[length] = '\0';
158
159 if (strcmp(topic, mqtt_pingall_sub) == 0)
160 {
161 blink();
162 client.publish(mqtt_pingall_pub,
163 "{\"diningroom_desk\":\"connected\"}");
164 }
165 else if (strcmp(topic, mqtt_mode_sub) == 0)
166 {
167 for (uint8_t i = 0; i < NUM(modes); ++i)
168 {
169 if (strcmp(modes[i].name, (char *)c_payload) != 0)
170 continue;
171 switchMode(&modes[i]);
172 break;
173 }
174 }
175 else if (strcmp(topic, mqtt_color_sub) == 0)
176 {
177 // switch from OFF to SOLID
178 if (set.mode == &modes[0])
179 switchMode(&modes[1]);
180
181 set.color = atoi((char *)c_payload);
182 current.idle = false;
183 itoa(set.color, convBuffer, 10);
184 client.publish(mqtt_color_pub, convBuffer, true);
185 }
186 else if (strcmp(topic, mqtt_brightness_sub) == 0)
187 {
188 set.brightness = map(atoi((char *)c_payload), 0, 100, 0, 255);
189 current.idle = false;
190 itoa(map(set.brightness, 0, 255, 0, 100), convBuffer, 10);
191 client.publish(mqtt_brightness_pub, convBuffer, true);
192 }
193}
194
195void blink()
196{
197 //Blink on received MQTT message
198 digitalWrite(BUILTIN_LED, LOW);
199 delay(25);
200 digitalWrite(BUILTIN_LED, HIGH);
201}
202
203void calcBrightness()
204{
205 #define FADE_STEP 10
206 if (current.brightness == set.brightness)
207 return;
208 int fadeAmount = set.brightness - current.brightness;
209 if (abs(fadeAmount) > FADE_STEP)
210 fadeAmount = (fadeAmount > 0) ? FADE_STEP : -FADE_STEP;
211 current.brightness += fadeAmount;
212}
213
214void switchMode(struct mode *mode)
215{
216 if (set.mode == mode)
217 return;
218 Serial.print("Switching mode to ");
219 Serial.println(mode->name);
220 set.mode = mode;
221 current.idle = false;
222 client.publish(mqtt_mode_pub, set.mode->name, true);
223}
224
225void modeOff()
226{
227 fill_solid(leds, RGB_NUM_LEDS, CRGB::Black);
228 current.idle = true;
229}
230
231void modeSolid()
232{
233 fill_solid(leds, RGB_NUM_LEDS, set.color);
234 calcBrightness();
235 nscale8_video(leds, RGB_NUM_LEDS, current.brightness);
236 current.idle = (current.brightness == set.brightness);
237}
238
239void modeRainbow()
240{
241 static CRGBPalette16 palette = RainbowColors_p;
242 static uint8_t hue = 0;
243 calcBrightness();
244 for (int i = 0; i < RGB_NUM_LEDS; ++i)
245 leds[i] = ColorFromPalette(palette, hue, current.brightness);
246 hue++;
247}
248
249void modeRainbowFast()
250{
251 static CRGBPalette16 palette = RainbowColors_p;
252 static uint8_t hue = 0;
253 calcBrightness();
254 for (int i = 0; i < RGB_NUM_LEDS; ++i)
255 leds[i] = ColorFromPalette(palette, hue, current.brightness);
256 hue+=5;
257}
258
259void modeStrobo()
260{
261 static bool state = 0;
262 if (set.color == CRGB::Black)
263 return;
264 fill_solid(leds, RGB_NUM_LEDS, (state) ? set.color : CRGB::Black);
265 calcBrightness();
266 nscale8_video(leds, RGB_NUM_LEDS, current.brightness);
267 state = !state;
268}
269
270void loop()
271{
272 if (!client.connected())
273 reconnect();
274 client.loop();
275 ArduinoOTA.handle();
276
277 EVERY_N_MILLISECONDS(100)
278 {
279 if (!current.idle)
280 {
281 set.mode->func();
282 FastLED.show();
283 }
284 if (!current.idle && current.brightness == 0)
285 current.idle = true;
286 }
287}