This project idea was born during covid lockdown when it was the new normal to work from home. This realisation is made for Arduino Cloud Games.
This project has two devices:
- Arduino Oplà IOT Kit as a main device, it fetches meeting information from Google Calendar. It turns on the sign when a meeting is in progress and can end it early.
- on Air Sign as a secondary device which is placed around our home office door and illuminated when meeting is in progress. Optional as the Oplà Kit itself can be used for this purpose otherwise any IOT capable device can be repurposed for this functionality.
For connection it utilises Arduino IOT Cloud and implements Thing to Thing communication. (More information about: https://docs.arduino.cc/cloud/iot-cloud/tutorials/thing-to-thing )
I created a thing for ESP8266 and defined a variable there as boolean. That variable is used to toggle the on air sign on and off. I also created a dashboard to manage it from my phone.
I printed an enclosure with white PLA and printed the label by using 2 colours of PLA, stopping the printer after first layer and switch filament manually as I have a single extruder machine. I was also making experiments with other type of housing and they worked well too (e.g. wooden box with painted glass ).
After that I built the circuit by recycling a led panel from a flashlight. You can follow the schematics to replicate or build your own circuit. The code for the ESP8266 is attached and it uses port 2 behind the boolean variable from IOT Cloud.
To Program the ESP-01 I added reset and programming mode buttons to a USB-TTL device and I also had a fallback device built on breadboard. You can find the source code provided.
On this picture you can look at the electronics of my custom hardware for the sign, It consists:
- 18650 Battery and its holder
- 18650 charging and protection board
- ESP - 01 with a BS170 switch on Pin 2
- Led Panel recycled from flashlight
- On-Off switch
For Oplà kit I created a second Thing with same variable and configured to be synchronized.
Once my kit connects to my wifi and Arduino Cloud it fetches the Google calendar feed in iCal format by using the secret url (this technique is also referred as magic cookie url), had a few cycles to figure out how to do HTTPS requests and download file (which is over 100kb) without SD card and parsing the file content with limited memory. Optionally this can be done by using Google Script or custom code on Raspberry Pi.
#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoHttpClient.h>
char server[] = "calendar.google.com";
WiFiClient client;
int port = 443;
void sendRequestICalendarFeed() {
if (client.connectSSL(server, port)) {
String get("GET /calendar/ical/");
get += SECRET_ICALENDAR;
get += "/basic.ics HTTP/1.1";
client.println(get);
client.println("Host: calendar.google.com");
client.println("Connection: close");
client.println();
}
}
void readICalendarFeed() {
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "0\r") {
// end of response
break;
}
// parsing response...
}
}
Parsing logic looks like:
struct Event {
public:
String dtstart;
String dtend;
String dtstamp;
String uid;
String created;
String description;
String lastModified;
String location;
int sequence;
String status;
String summary;
String transp;
};
Event events[20];
int event_index = -1;
int event_length = event_index + 1;
void load(WiFiClient client) {
String line;
String buffer = "";
String key;
String value;
bool insideEvent = false;
bool today = false;
int idx = -1;
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "0\r") {
break;
}
if (line.charAt(0) == ' ') {
// collecting multiline prop
if (buffer.length() < 100)
buffer += line.substring(1);
} else {
if (buffer != "") {
// process previous prop
auto m = buffer.indexOf(':');
if (m == -1)
m = buffer.indexOf(';');
key = buffer.substring(0, m);
value = buffer.substring(m + 1);
if (key.compareTo("BEGIN") == 0 && value.compareTo("VEVENT\r") == 0) {
if (idx < 19){
idx++;
}
insideEvent = true;
} else if (key.compareTo("END") == 0 && value.compareTo("VEVENT\r") == 0) {
insideEvent = false;
if (!is_today(events[idx].dtstart.c_str(), ArduinoCloud.getLocalTime())) {
idx--;
}
} else if (key.compareTo("DTSTART") == 0 && insideEvent) {
events[idx].dtstart = value;
} else if (key.compareTo("DTEND") == 0 && insideEvent) {
events[idx].dtend = value;
} else if (key.compareTo("DTSTAMP") == 0 && insideEvent) {
events[idx].dtstamp = value;
} else if (key.compareTo("CREATED") == 0 && insideEvent) {
events[idx].created = value;
} else if (key.compareTo("DESCRIPTION") == 0 && insideEvent) {
events[idx].description = value;
} else if (key.compareTo("SUMMARY") == 0 && insideEvent) {
events[idx].summary = value;
}
buffer = "";
}
buffer = line;
}
}
event_length = idx + 1;
if (!client.connected()) {
client.stop();
}
}
When the file content was streamed I was looking for meetings scheduled for today and ignore the rest to fit in memory.
When list of meetings parsed for today I determined which is happening at the moment (or the next one) and displays it on the screen. At that moment the Oplà kit sets the boolean variable onAir to be true and if the sign is turned on then it starts illuminating.
The button at the top controls the on Air sign directly. When it is red, it means the On Air sign is on:
By using the buttons I can end the actual meeting early, so the sign turns off and led switches to green. I can also navigate through the list of meetings.
For further upgrades of this project I'm considering to enable the Oplà kit to edit meetings on Google Calendar like scheduling new meetings and also to use a second Oplà kit - for my wife - as a secondary device.











_dCZP5MjXGR.png)




Comments