-
Notifications
You must be signed in to change notification settings - Fork 0
/
PersonAsLamp.ino
349 lines (290 loc) · 10.4 KB
/
PersonAsLamp.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
#include<Bounce2.h>
#include<ESP8266WiFi.h>
#include<PubSubClient.h>
#include<FS.h>
//things attached to pins:
const int rpin = 4;
const int gpin = 5;
const int bpin = 15;
const int buttonPin = 14;
//potentiometer rolling average for brightness control:
const int numAverage = 70;
int potentiometer[numAverage];
int brightness = 1024;
int sum;
int i = 0;
//button debounce:
Bounce button = Bounce(buttonPin, 50);
//button press behavior:
long int pressStart;
const long int longPressLength = 1500;
//color stuff:
//labels: warm white red orange yellow green light blue blue purple off
const int colors[9][3] = {{950, 900, 850}, {1024, 0, 0}, {900, 300, 0}, {750, 450, 0}, {0, 1024, 0}, {0, 550, 450}, {0, 0, 1024}, {330, 0, 880}, {0, 0, 0}};
int displayColor; //the color currently displayed by the lamp
int storedColor = 0; //the color assigned to the lamp by the MQTT broker
int sendColor = 0; //the color to be sent to the MQTT broker by the lamp
const int numSteps = 50; //the number of steps to use when transitioning between colors
const int brightMin = 30; //the minimum brightness settable by the dial
const int pulseHang = 200; //milliseconds to hang at max brightness during a pulse
//WiFi Stuff:
WiFiClientSecure wifiClient;
String myHostname = "MQTT-lamp"; //this will be the hostname visible to the network
//MQTT Stuff:
PubSubClient client(wifiClient);
const IPAddress broker(10,0,0,161);
const int port = 1883;
const char mqttUsername[] = "username"; //set this to this lamp's username in the MQTT broker
const char mqttPassword[] = "password"; //set this to this lamp's password in the MQTT broker
char sendColorChar[10];
const long int delayToSend = 5000; //how long to wait before sending the current selected color to the MQTT broker
bool willSend; //are we going to send a color in the future?
void setup() {
WiFi.setSleepMode(WIFI_NONE_SLEEP);
pinMode(rpin, OUTPUT);
pinMode(gpin, OUTPUT);
pinMode(bpin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(A0, INPUT);
delay(10);
transition(8, 0);
for (int j = 0; j < 8; j++) {
transition(j, j+1);
}
showColor(8);
Serial.begin(115200);
delay(2000);
loadcerts();
wifiClient.setInsecure();
connectToWiFi();
client.setServer(broker, port);
client.setCallback(callback);
connectToBroker();
delay(1000);
}
void loop() {
//reconnect to WiFi if disconnected:
if (WiFi.status() != WL_CONNECTED) {
connectToWiFi();
}
//reconnect to MQTT broker if disconnected:
if (!client.connected()) {
connectToBroker();
}
client.loop();
handlePotentiometer(); //deals with the potentiometer; sets brightness
handleButton(); //deals with the button; also will deal with sending colors based on the button inputs
showColor(displayColor); //shows the proper color
delay(10);
}
void connectToWiFi() {
int count = 0;
Serial.print("Attempting to connect to WiFi with hostname " + myHostname);
WiFi.hostname(myHostname);
WiFi.mode(WIFI_STA);
WiFi.begin("", ""); //if you want to manually enter the wifi SSID and password, put them in here. The format is WiFi.begin("SSID", "password");
while (WiFi.status() != WL_CONNECTED && count < 10) { //WiFi is disconnected and we've been trying to connect for less than 5 seconds
delay(500);
Serial.print(".");
count++;
}
if (WiFi.status() != WL_CONNECTED) { //the connection failed; use WPS
Serial.println("Could not connect with stored credentials; requesting WPS setup. Push WPS button on router, then button on lamp to begin WPS setup.");
count = 0;
button.update();
while (button.read()) {
pulse(0);
delay(300);
button.update();
}
Serial.println("Attempting WPS");
WiFi.beginWPSConfig();
delay(5000);
}
if (WiFi.status() == WL_CONNECTED) { //WiFi connection succeeded
pulse(4);
Serial.println();
Serial.print("Connected to WiFi network ");
Serial.println(WiFi.SSID());
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
else { //WiFi connection failed
pulse(1); //pulse the RGB LED red
Serial.println();
Serial.print("WiFi Config Failed. Reset to try again.");
}
}
void connectToBroker() {
while (!client.connected()) {
Serial.print("Attempting to connect to broker at ");
Serial.println(broker);
client.connect("personAsLamp", mqttUsername, mqttPassword);
if (client.connect("personAsLamp")) {
pulse(5);
Serial.println("Connected.");
client.publish("ConnectionInfo", "Hello world from personAsLamp");
client.subscribe("ConnectionInfo");
client.subscribe("personAsLampColor"); //the MQTT topic for this lamp's color
}
else {
delay(1000);
Serial.print("Failed; state: ");
Serial.println(client.state());
Serial.println("Will try again in 5 seconds...");
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
char message[length];
for (int count = 0; count < length; count++) {
message[count] = payload[count];
}
Serial.print("New message from ");
Serial.print(topic);
Serial.print(", contents: ");
for (int count = 0; count < length; count++) {
Serial.print(message[count]);
}
Serial.println();
if (strcmp(topic, "personAsLampColor") == 0) {
String messageString = message;
storedColor = messageString.toInt();
if (!willSend) { //if we're not currently in the process of sending a color:
transition(displayColor, storedColor);
displayColor = storedColor;
}
//we don't need to do anything more if we are currently in the process of sending a color; that was done when we set storedColor=messageString.toInt() in line 184;
}
if (strcmp(topic, "ConnectionInfo") == 0) { //if the topic is ConnectionInfo, remind the other lamp what their color should be
client.publish("personBsLampColor", sendColorChar);
Serial.println("Publishing sendColorChar to personBsLampColor.");
}
}
void loadcerts() {
if (SPIFFS.begin()) {
Serial.println("Filesystem loaded.");
}
File cert = SPIFFS.open("/personAslampclient.crt", "r");
if (cert) {
Serial.println("Certificate opened.");
}
delay(1000);
if (wifiClient.loadCertificate(cert)) {
Serial.println("Certificate loaded.");
}
File privateKey = SPIFFS.open("/personAslampclient.key", "r");
if (privateKey) {
Serial.println("Private key opened.");
}
delay(1000);
if (wifiClient.loadPrivateKey(privateKey)) {
Serial.println("Private key loaded.");
}
File ca = SPIFFS.open("/ca.der", "r");
if (ca) {
Serial.println("CA file opened.");
}
/* //can't get this part to work for some reason
delay(1000);
if (wifiClient.loadCACert(ca)) {
Serial.println("CA loaded.");
}
*/
}
void handlePotentiometer() {
//reset i for rolling average, if necissary:
if (i == numAverage) {
i = 0;
}
//read the potentiometer and add that to the array of potentiometer values:
potentiometer[i] = analogRead(A0);
//sum up all potentiometer values:
for (int count = 0; count < numAverage; count++) {
sum += potentiometer[count];
}
//set brightness equal to the rolling average of the potentiometer (0 - 1024):
brightness = map(sq(sum/numAverage), 0, 1048576, brightMin, 1024);
Serial.println(analogRead(A0));
//reset the sum and incriment i
sum = 0;
i++;
}
void handleButton() {
//update the state of the button
button.update();
//when the button is depressed, save the time in milliseconds since program start:
if (button.fell()) {
pressStart = millis();
}
//turn the display on or off
if (!button.read() && millis() - pressStart >= longPressLength && !willSend) { //the button's been depressed for longer than longPressLength and we're not working on sending a color
if (displayColor != 8) { //if the lamp is on, turn it off
transition(displayColor, 8);
displayColor = 8;
button.update();
delay(300);
}
else { //if the lamp is off, turn it on
transition(8, storedColor);
displayColor = storedColor;
button.update();
delay(300);
}
}
//start the process to send a color
if (button.rose() && millis() - pressStart < longPressLength && displayColor != 8) { //the button is released AND the press was short AND the lamp is on
rotateSendColor();
transition(displayColor, sendColor);
displayColor = sendColor;
willSend = true;
}
//send the selected sendColor if criteria are met
if (button.read() && millis() - pressStart >= delayToSend && willSend) { //the button is not depressed AND it's been delayToSend since the last press AND we're supposed to send a color
sprintf(sendColorChar, "%0d", sendColor);
client.publish("personBsLampColor", sendColorChar);
Serial.println("Publishing sendColorChar to personBsLampColor.");
transition(sendColor, 8);
rotateSendColorBack();
transition(8, storedColor);
displayColor = storedColor;
willSend = false;
}
}
void rotateSendColor() {
if (sendColor == 7) {
sendColor = 0;
}
else {
sendColor++;
}
}
void rotateSendColorBack() {
if (sendColor == 0) {
sendColor = 7;
}
else {
sendColor--;
}
}
void pulse(int c) { //c is the color to pulse
transition(8, c);
delay(pulseHang);
transition(c, 8);
showColor(8);
}
void transition(int c1, int c2) { //create the change that will happen to R, G, and B for each step:
float colorStep[] = {(colors[c2][0] - colors[c1][0]) / numSteps, (colors[c2][1] - colors[c1][1]) / numSteps, (colors[c2][2] - colors[c1][2]) / numSteps};
for (int count=0; count<=numSteps; count++) {
analogWrite(rpin, (brightness * (colors[c1][0] + count*colorStep[0]))/1024);
analogWrite(gpin, (brightness * (colors[c1][1] + count*colorStep[1]))/1024);
analogWrite(bpin, (brightness * (colors[c1][2] + count*colorStep[2]))/1024);
delay(10);
}
}
void showColor(int c) {
analogWrite(rpin, (brightness * colors[c][0])/1024);
analogWrite(gpin, (brightness * colors[c][1])/1024);
analogWrite(bpin, (brightness * colors[c][2])/1024);
}