The ultimate Raspi-Meeting-Room project

COVID-19…virtues of an extended lockdown !

Server

Sync meeting rooms events

The purpose of the server is to collect the events regarding each meeting rooms calendars.

After booting, the server picks-up from the provider API, the daily events for each meeting rooms defined into the events_config.json file, and subscribe to push notifications in order to be updated if any modification occures (adding, updating and cancellation). Afterwards, events are dispatched to the display devices which are kept up-to-date each time a push notification occures.

Meeting rooms’ display devices automatically subscribe to the server at their own boot time. IP addresses are automatically added to the events-config.json file, after their registration occuring at boot time.

The server is the only local entry point for the meeting rooms’ calendars events. It can run on a display device or on a dedicated one.
Because it has to subscribe to the provider push notifications’ API, it must provides a valid SSL certificat in order to allow https requests (supports only PEM files format).

Prerequisiter are as follow:

  • Raspberry PI Zero W or B+, with a prepared SD card as describe here 
  • SSL certificats (key and cert files – PEM format only) for the push notifications’ web-hook url. If you do not have one, go here
  • Firewall rule in  order to redirect incoming push notifications from the provider to the server
  • Meeting rooms calendars provider: Google GSuite or Microsoft Business

1st step: Download package

1) Move to home directory

pi@raspberrypi: ~$ cd /home/pi/

2) Copy project from Github with Subversion

pi@raspberrypi: ~$ svn checkout https://github.com/gpelizzo/PUB-RASPI-MEETING-ROOM-SERVER.git/trunk/dist

3) Create new folder to host /dist files

pi@raspberrypi: ~$ mkdir /home/pi/raspi-meeting-room-server

4) Move /dist content to the new folder

pi@raspberrypi: ~$ mv PUB-RASPI-MEETING-ROOM-SERVER/dist/ raspi-meeting-room-server

2nd step: install dependencies

1) Move to server directory

pi@raspberrypi: ~$ cd /home/pi/raspi-meeting-room-server

2) Install depedencies from package.json file 

pi@raspberrypi: ~$ npm install

After a while, a new directory named node-modules will appear including all dependencies modules.

3rd step: set server parameters

Open config.json file 

pi@raspberrypi: ~$ nano /home/pi/raspi-meeting-room-server/config.json

and fill-out the settings, e.g.:

{

“event_provider”: “microsoft”,
“impersonate_user_email”: “admin@raspimeetingroom.fr”,
“logs_path”: “/home/pi/raspi-meeting-room-server/logs.log”,
“log_level”: “debug”,
“event_config_path”: “/home/pi/raspi-meeting-room-server/events_config.json”,
“ssl_key_path”: “/home/pi/ssl/raspimeetingroom.fr.key.pem”,
“ssl_cert_path”: “/home/pi/ssl/raspimeetingroom.fr.cert.pem”,
“google_private_key”: “/home/pi/raspi-meeting-room-server/raspi_meeting-room.json”,
“google_customer_id”: “ABCD123456”,
“MSGraph_application_id”: “abcdefghij123456789”,
“MSGraph_client_secret”: “<rstuvwxya789456+41123-12345>”,
“MSGraph_active_directory_id”: “lhgfdti,kvjloolkk,ed789456123123”,
“push_notification_web_hook_addr”: “https://meetings.raspimeetingroom.fr”,
“push_notifications_web_hook_port”: “8100”,
“tcp_devices_port”: 8081,
“tcp_devices_token”: “abcdef123456”,
“tcp_server_port”: 8082,
“tcp_server_token”: “uvwxyz987654”,

}

  • event_provider: “google” or “microsoft” depending on the provider.
  • impersonate_user_email: email adress of an admin to perform some API operations;
  • logs-path: full path to the logs file.
  • log_level: level of the logs as defined into winston package.
  • event_config_path: full path to the meeting room config file…see below
  • ssl_key_path: full path to SSL certificat key.PEM file.
  • ssl_cert_path:  full path to SSL certificat cert.PEM file. 

Google only (otherwise can be removed):

  • google_private_key: full path to the Google API project key (see here).
  • google_customer_id: Google Gsuite account’s customer ID (see here).

Microsoft only (otherwise can be removed):

  • MSGraph_application_id: Microsoft Graph/Azure application id (see here).
  • MSGraph_client_secretMicrosoft Graph/Azure client secret (see here).
  • MSGraph_active_directory_idMicrosoft Graph/Azure active directory id (see here).

IMPORTANT: firewall shall be configured in order to redirect all incoming requests on weeb hook port to the server IP address (same port)

  • push_notification_web_hook_addr: URL for incoming push notification from the provider (https only).
  • push_notification_web_hook_port: port to listen for incoming push notification.
  • tcp_devices_port: port listen by display devices.
  • tcp_devices_token: display devices Bearer Token (user defined).
  • tcp_server_port: port listen by the server for display devices requests.
  • tcp_server_token: server Bearer Token (user defined).

4th step: set meeting rooms subscriptions

Open config.json file 

pi@raspberrypi: ~$ nano /home/pi/raspi-meeting-room-server/events_config.json

and fill-out the settings, e.g.:

[

{

“meeting_room_name”: “A01 – LONDON”,
“meeting_room_id”: “RASPI-MR-01”,
“calendar_id”: “raspi_london@raspimeetingroom.fr”,
“clients”: []

},

{

“meeting_room_name”: “A02 – LISKOV”,
“meeting_room_id”: “RASPI-MR-02”,
“calendar_id”: “raspi_liskov@raspimeetingroom.fr”,
“clients”: []

}

]

  • meeting_room_name: not used. Only to facilitate reading & identification .
  • meeting_room_id: ID of the meeting room used by the server and displays devices (user defined).
  • Calendar_id: email address of the meeting calendar (provider side).
  • client: Registering list of the display devices having subscribing to the meeting room. You do not have to fill-out this array. It will be automaticaly updated by the display devices themselves at boot time. But you can manually unregister a device by just removing the json record into the array.

Subscriptions to the provider’s push notifications and display devices registration perform an automatic update of the file, looking like as above. Multiple display devices can subscribe to receive the event of a meeting room (why not! – let’s imagine other categories of devices). the push_channel_notification_id key is automatically filled by the server for a technical purpose only (you must not delete of change the key and the value). 

[

{

“meeting_room_name”: “A01 – LONDON”,
“meeting_room_id”: “RASPI-MR-01”,
“calendar_id”: “raspi_london@raspimeetingroom.fr”,
“clients”: [
{
“ip”: “192.168.0.39”,
“mac”: “b01:a5:de:ff:45:bb”
}
],
“push_channel_notification_id”: “41866d44-fd7894df-f742bc4b”

},

{

“meeting_room_name”: “A02 – LISKOV”,
“meeting_room_id”: “RASPI-MR-02”,
“calendar_id”: “raspi_liskov@raspimeetingroom.fr”,
“clients”: [
{
“ip”: “192.168.0.48”,
“mac”: “b01:a5:de:ff:04:8c”
},
{
“ip”: “192.168.0.49”,
“mac”: “b01:a5:de:ff:04:9a”
}
],
“push_channel_notification_id”: “41866d44-fab8723df-e7841ab”

}

]

5th step: enable PM2 to run and manage the server app

1) Install PM2 as describedhere

2) Create and start a new process.

pi@raspberrypi: ~$ sudo pm2 start /home/pi/raspi-meeting-room-server/CMain.js —name server

3) Save current PM2 process (required for auto-run at boot time)

pi@raspberrypi: ~$ sudo pm2 save

Nice to know: 

List all running process

pi@raspberrypi: ~$ sudo pm2 list

Stop process

pi@raspberrypi: ~$ sudo pm2 stop

Restart process

pi@raspberrypi: ~$ sudo pm2 restart

Delete process

pi@raspberrypi: ~$ sudo pm2 delete

6th step: create a cron job

In order to avoid any disruption caused by memory leaks or unexpectable dysfunction (let’s talk about bugs !), I strongly recommand to automatically restart the server app every day during night. This can be perform by adding a cronjob. Then, open the crontab:

pi@raspberrypi: ~$ sudo crontab -e

and add following similar line (e.g. restart server app every day at 4AM)

0 4 * * * /sbin/shutdown -r now

7th step: tiny API

A tiny API is provided in order to perform some technical operations. I recommend using postman.
The API can be address from http://server-ip-adress:tcp_server_port. Don’t forget to add the Bearer Token as defined into the config.json file (tcp_server_token).

Details are commented into the CMain.ts file (check sources).

  • GET ‘/utilities/resources’: retreive the list of all meeting rooms resources from provider (incl. names and email addresses).
  • GET ‘/utilities/events-config’: retreive config.json content, including the up-to-date daily events.
  • GET ‘/utilities/push-notification-subscription’: retreive push notification channel details.
  • DELETE ‘/utilities/push-notification-subscription’: unregister push notifications for all meeting room calendars.
  • POST ‘/utilities/unregister-push-notification-subscription’: unregister a push notification channel.

8th step(optional): Install source files (visit GITHUB repository)

This step is mandatory only if you have expected to update the source files (bug fixing, improvement, etc.). It requires typescript commands (see how to install here).

Again, Raspberry Zero W is definitly not the right device to manage development operations, as typescript compilation which requires processor and memory resources. I rather recommand to use a Raspberry pi B+.

1) Move to home directory

pi@raspberrypi: ~$ cd /home/pi/

and copy source files from Github with Subversion

pi@raspberrypi: ~$ svn checkout https://github.com/gpelizzo/PUB-RASPI-MEETING-ROOM-SERVER.git/trunk/src

then, rename /src folder file and install dependancies as described above.

2) compile project in order to initialize /dist folder. Move to the source folder and run tsc command:

pi@raspberrypi/raspi-meeting-room-server: ~$ tsc

3) eventually, create and set config.json and events_config.json files as described above. these files must be placed into the new /dist folder.

pi@raspberrypi/raspi-meeting-room-server: ~$ nano dist/config.json

pi@raspberrypi/raspi-meeting-room-server: ~$ nano dist/events_config.json