Push reservation notifications to meeting rooms!
Using remote modules equipped with RGB LEDs, GTFO lets meeting room occupants know the status of their current reservation. For example, 5 minutes before a meeting ends and another is set to begin, the room's LED will light up orange to let occupants know it's time to begin wrapping up.
The hardware setup consists of a host server and n number of remote modules.
A Unix-based system is required to run the host server which will control each remote module. A Raspberry Pi is recommended for its small footprint and power consumption, but a spare computer running OSX or Linux can be used just as well.
A network with 802.11b/g/n WiFi hotspots is required for the remote modules to connect to. Particle Photons are headless devices, so note that the hotspot security must not require a browser-based login portal for authenticating. (Router passwords, however, can be entered through Particle's terminal setup application.) MAC address white-listing can also be used for additional security.
The host server must be on the same LAN as the remote modules.
The host server will serve a map of the office on http://[host-ip-or-name]:3000
,
with programmatically-generate tiles for each remote module declared in environment/devices.json
.
For this map to be usable, you must provide your own background image(s) and the size and position of each room tile. See environment configuration documentation.
Minimum required hardware per each remote module:
- Particle Photon
- NeoPixel (or equivalent WS2812 LEDs)
Photon boards communicate with the Particle cloud and receive updates through the Particle API for JS.
Connect each board to your WiFi network.
Flash each module with firmware/firmware.cpp
.
(npm run flash
is a WIP script to flash every device listed in devices.json
.)
Retrieve the access tokens and device ids for each Photon, and place them into environment/devices.json
.
See environment configuration documentation.
Wire a set of NeoPixels to each Photon board. Optionally, wire a motion and temperature sensor.
Note that the firmware is configured to run with 12 NeoPixels. I recommend this ring for the best effects, but other NeoPixel configurations can be used. Just be sure to update PIXEL_COUNT
in firmware.cpp to the correct number of pixels.
Hardware: NeoPixel Ring (or equivalent WS2812 LEDs)
Wire | Pin |
---|---|
Data in | D2 |
PWR | 3v |
GRN | Ground |
Temperature and humidity sensor pin configuration (optional, must be enabled in environment configuration)
Hardware: DHT11 (with breakout board)
Wire | Pin |
---|---|
Out | A4 |
+ | 3v |
- | Ground |
Motion sensor pin configuration (optional, must be enabled in environment configuration)
Motion sensors enable detecting presence of room occupants in unreserved rooms, and setting the room status to "squatted" on the office map. Hardware: HC-SR501
Wire | Pin |
---|---|
Data | A0 |
VCC | 3v |
GND | Ground |
git clone https://github.com/Nase00/gtfo.git && cd gtfo && npm install
Before the application can be run, read how to configure it to your specific office or run npm run demo
to generate an example configuration. The application will not run otherwise.
# After environment files have been configured
npm run hot --mocks
This will start the application in development mode with mock data and hot-reloading. At this point, the application should find and connect to each Particle Photon, and light up the LEDs.
GTFO does not currently handle authentication, thus it does not query Outlook Web Acess, Exchange Web Services, or any other services containing reservation data directly. Instead, a "gateway" API must be used as middleware when running production mode or development mode with live data. (E.g., running yarn hot
with the --mocks
flag.)
GTFO was developed in tandem with ews-wrapper, but any service could be used in its place, so long as the output is an identical format.
[
{
"name": "SomeRoom",
"schedule": [
{
"subject": "Alice Murphy",
"start": {
dateTime: "2018-11-30T15:00:00.000Z"
},
"end": {
"dateTime": "2018-11-30T15:30:00.000Z"
}
},
{
"subject": "Anders Holmvik",
"start": {
dateTime: "2018-11-30T16:00:00.000Z"
},
"end": {
"dateTime": "2018-11-30T17:00:00.000Z"
}
},
{
"subject": "Alice Murphy",
"start": {
dateTime: "2018-11-30T17:00:00.000Z"
},
"end": {
"dateTime": "2018-11-30T18:00:00.000Z"
}
}
},
{
"name": "SomeOtherRoom",
"schedule": [
{
"subject": "Jillian Belk",
"start": {
dateTime: "2018-11-30T15:00:00.000Z"
},
"end": {
"dateTime": "2018-11-30T16:30:00.000Z"
}
}
}
]
In production mode, it assumed the gateway API is deployed on another domain, defined in environment/config.json
.
See environment configuration documentation.
npm install --production # Several dev dependencies are not Raspberry Pi compatible.
npm run prod # Production mode with live data. ews-wrapper or an equivalent service must be deployed and defined in environment/config.json!
Alexa, where is Kerbin?
Kerbin is on the east side of the office. I've highlighted it on map for you.
The Ping API allows external services to "ping" specific rooms on targetted clients. Clients can be targetted using "anchors." The anchor id used is completely arbitrary, but must be matched between the service making the ping and the client attempting to be pinged.
To anchor a client, simply add an anchor
query paramter to its route. E.g., http://hostname:3000/sears-tower-251?anchor=east-lobby
defines the client's anchor as east-lobby
.
To ping this client from an external service, direct a POST request to http://hostname:3000/api/ping
with the headers:
{
"id": "foo", // Required only when using a proxy (see blow), must match the application ID set in config.json
"targetId": "kerbin",
"anchor": "east-lobby",
"event": "NEW_ROOM_PING"
}
The result of this ping is that Kerbin lights up on the client anchored to the east lobby. An example use of this is anchoring a client on a display in the east lobby, and assigning a nearby Amazon Echo to highlight queried rooms on the TV.
Some internal office networks restrict exposing ports for making HTTP requests. This would make it impossible, for instance, for an Echo lamdba service hosted on AWS to send a ping request to a GTFO server hosted on the office intranet. For these restricted networks, Acheron was created to be hosted externally (e.g., on a cloud service) to accept and forward pings to GTFO via a WebSocket connection.
To avoid confusion, note that there are two distinct WebSocket services within GTFO. The socket controller exists to host a WebSocket server to which browser applications connect to as clients. The proxy controller controller exists to connect to the proxy host where GTFO itself is considered the sole client.
npm run hot
npm run test # Lints and tests client, server, and universal code.
# pipe flags with "--", e.g. "npm run hot -- --mocks --dhc"
--mocks # Disables Outlook api in favor of using mock reservation data.
--dhc # Disables consoleController's fancy terminal output, sometimes needed for debugging.
--dd # Disables devices, useful for client testing without room module hardware.
Meeting room reservations aren't accurate
Make sure your server's system timezone is set correctly. Reservation times are compared against the system time to determine room reservation statuses. Raspberry Pi defaults to GMT+0.