Simple Kicker Status and Reservation System With Slack Integration

by zolv in Circuits > Raspberry Pi

5554 Views, 21 Favorites, 0 Comments

Simple Kicker Status and Reservation System With Slack Integration

IMG_20170405_222348.jpg

In a company where I work there is a kicker table. The company occupies many floors and for some of the employees it takes up to 3 minutes to get to the table and...to realize that the table is already occupied.

Therefore an idea arised to build a kind of simple status broadcasting and reservation system which operates in real time.

Company uses Slack communication tool where every employee has an account. We have even a #kicker channel just for discussions about...kicker. The channel could be used as a kind of "entry point" for reservation and to be informed about current table's status.

As usual, there are many concepts how to deal with such a system. But generally, one basic rule appeared in all of them: it has to be simple to use without any excessive steps to perform when dealing with the system.

The device and the service are not sticked to the kicker table and can be used for any "common resource" (like ping-pong table, console, etc...) which needs some kind of status broadcadting amd reservation solution.

So, let's get started...

Proof of Concept and Prototyping

IMG_20170326_121624.jpg
IMG_20170325_215852.jpg
IMG_20170325_215906.jpg
IMG_20170325_220419.jpg
IMG_20170325_215822.jpg
IMG_20170325_215738.jpg

Raughly the idea was to build a device which will be laying next to the kicker table following these requirements:

  • some indicators about the current table status - if You are standing next to it, You should be able to know that it is free or reserved and somebody will come to play in a 3 minutes. Traffic lights fits to the idea perfectly:
    • green light - free to play,
    • yellow light - reserved,
    • red light - occupied.
  • button(s) You can click before and after the game so everybody else get informed about current table's status. Instead of 1 toggle button I decided to use 2 separated buttons:
    • red button - occupy the table, start a game (after reservation or ad hoc).
    • green button - release table.
  • some display with more detailed informations about "what's going on" - reservation timeout, repeated table status, playtime timeout etc...

By reservation I mean just the reservation for next 3 minutes. System is not designed so that user can reserve the table at exact time (e.g. 02:00PM). It does not work like reservation e.g. in restaurants but just for upcomming minutes.

Because of lack of LAN connection in place, the only option is to use WLAN - it is the best option anyway. The brain of the system must use Slack API to send and receive commands from Slack channel. First I tried to use NodeMCU. I was able to get and receive messages to and from Slack but because of HTTPS usage and also Slack's "welcome message" size (~300kB), NodeMCU was loosing connection and/or got some weird exception which I couldn't resolve digging through Internet.

So I decided to use something more powerful: Raspberry Pi 3 (Zero W with WiFi was not yet released on that time). By having RPi, I could switch the implementation language from C to Java as it is more convenient for me - so this was an advantage. Today You can use something more powerful than NodeMCU and less powerful than RPi. Raspberry Zero maybe?

After building first prototype on a breadboard with some crazy wiring, lot of sketching and prototyping, the system looked like it can work.

Having all of these ideas and working PoC, I started to plan different placement configurations of above items on a front panel so they will be the most informative and convenient to use. You can check some of the other proposals, maybe some fits better to You. The last one was the chosen one by me.

Materials and Tools

Materials I used:

Tools I used:

  • Sharp knife (e.g. utility knife for cutting carpet)
  • Rotary tool
  • Hot glue gun
  • Soldering station
  • Pliers, diagonal pliers/side cutters
  • Screwdriver
  • File
  • Me

Tools You probably need:

  • All of the above but instead of "Me" it should be: "You" :)

Front Panel - LCD Screen

IMG_20170328_203952.jpg
IMG_20170328_211716.jpg

Hole for LCD screen was straightforward. Just a rectangle which fits to my LCD screen. After trying to cut it with a sharp knife, I realized that plastic of the box is quite hard. So I used drilling tool to cut the window and to polish the edges.

Front Panel - Status LEDs

IMG_20170328_220046.jpg
IMG_20170328_221721.jpg

LED holes are also straightforward. I just took a big drill for wood and then I polished the edges with drilling tool. The big LEDs fitted perfectly tight. I didn't solder any resistors to the LEDs yet - I left it for the assembling process.

Front Panel - Buttons

IMG_20170328_225832.jpg
IMG_20170328_232651.jpg
IMG_20170328_232312.jpg
IMG_20170328_232658.jpg

The biggest problem with these 2 big buttons was to place them evenly with the proper spacing. I cut the holes just using my drilling tool as I could increase diameter step by step so the buttons fit tight.

Power Connector

IMG_20170404_231411.jpg

A small hole for micro USB power was a very delicate job to do. I wanted the hole to be as fit as possible so I spent here a lot of time for polishing. But I was satisfied with the final result.

Then I cut a short mini USB cable which was placed inside the box. One side it is plugged into RPi, and on the other side, all cables were soldered to the micro USB interface according to USB pinouts.

Then I hot-glued the small PCB directly to the box (it can be seen on a photo in the assembling step).

Putting Everything Together

IMG_20170329_225718.jpg
IMG_20170329_002618.jpg
IMG_20170329_232053.jpg
IMG_20170329_232119.jpg
IMG_20170404_235423.jpg
IMG_20170405_222339.jpg

First I soldered appropriate resistors to the LEDs according to their color (voltage) for 3.3V volt. I used 100Ω for red, two resistors 82 and 100 for yellow (green and red node), and 100Ω for green. You can use the one of the online resistor for LED calculator. But please do some research by Yourself according to the brightness and exact color tone You want to achieve.

Legs of yellow LED were soldered together so the LED itself can be controlled just by one pin on RPi.

According to this pinout diagram:

LED nodes were connected:

  • Green LED - GPIO1 on Rpi
  • Yellow LED (both legs) to GPIO2 on RPi
  • Red LED to GPIO0 on RPi

I connected LCD using I2C pins on RPi pins

  • LCD SDA to GPIO8 on RPi
  • LCD SCL to GPIO9 on RPi
  • LCD PWR to 5V on RPi
  • LCD GND to GND on RPi

The LCD was hot-glued to the box as an additional protection.

I connected 3.3V and GND to the small breadboard so I could use them for buttons.

Green button was connected to the 3.3V through mini breadboard and to GPIO5 on RPi.

Red button was connected to the 3.3V through mini breadboard and to GPIO4 on RPi.

So whenever You press the button, there is a high state on the RPi pin.

The mini bradboard works just fine so I skipped soldering all the wires into PCB. Instead I just covered the mini breadboard with hot glue so the cables will not fall off.

I also hot-glued RPi's cover to the box so it will not be wobbling inside.

I screwed the front panel with all the stuff inside.

Then I printed, cut and stick simple labels next to the traffic lights and buttons.

Slack Configuration

slack-integrations.png
create-channel.png

Create Your team on Slack.com or use the one You have and You have at least admin rights.

In Slack, create a channel for service's Slack integration (or skip creating a channel if You want to use one You already have).

Add Incomming Webhooks integration to Your team. Select the channel and copy the webhook URL.

Add Bots integration to Your team. Choose some name for Your bot and copy the bot API token.

Your managing custom integrations's page should look like on the picture.

You have to invite the bot as a member of Your channel. You could do it already during creating a channel.

If You want to customize the service later on, please check the Slack API.

Software Implementation

I used Raspbian as an operating system for my RPi by following this tutorial. Please forgive me I will skip explaining it as it is already documented in many places and the process is straightforward. I hope You are skilled and experienced enough to manage to setup RPi on Your own. Please don't forget to configure WiFi access on Your Raspberry Pi ;)

As mentioned in prototyping section, I used Java to implement the brain of the whole system. The code is available on GitHub - https://github.com/zolv/kicker-management.

The Java libraries I used:

You need to edit configuration file in src/resources/config.properties. There are 3 entries You have to configure to use Slack API:

  • channelName - name of the channel You want to post status changes and receive commands.
  • slackBotToken - token of a bot configured in Your Slack team integrations which will be used to post messages to the channel mentioned above. Please note You have to add Slack Bot as a member of the channel.
  • webhookUrl - the URL You can get from Slack Team's custom integrations.

Project is Mavenized so to build it just type (You need at least Java 8 and Maven installed):

mvn clean package

And in target tirectory You can find the Springbooted JAR file. To start a service:

sudo java -jar kicker-reservation-service-0.3.0.jar

I set this line to .sh script and added it as an autostart. So whenever the power is on, the service boots automatically.

One special explanation is needed to the LCD.

I tried different approaches/libraries to control LCD over I2C from RPi but I just failed. For some LCD was not working properly, for some it was showing some rubbish.

But one thing was working very nice just out of the box. It is the utility command line tool I found You can use to control LCD. So I decided to just use this tool directly from Java. It works like this that a normal Linux process (lcdi2c) is called (with prepared parameters) every time I want to display something on the LCD screen.

You need to download the tool and place it next to the JAR service.

Using this tool is a kind of hack and stupid solution But I follow the 1st rule of engineering:

If it is stupid, but it works...it is not stupid

Usage Instruction

slack-channel-log.png

You can check kicker table current status on created Slack channel by typing "status" (or shortly "st") command or directly check the traffic lights on the device.

If You just want to play - press red button. Message will be send to Slack channel with info that kicker table is occupied. When You've finished playing - press green button. Message will be send to the Slack channel with info that kicker table is free to play.

Traffic lights will also change and LCD screen will show some detailed information.

Just in case You forget to release the table after You've finished playing, there is a timeout set to 20 minutes. If You are still playing and need more time, press red button again and the match will be extended by 5 minutes (only apply when there is less than 5 minutes left before timeout). Playing timeout will be presented on LCD screen.

To reserve kicker table, write a message „reserve” (or just: „res”) to the Slack channel.

The Yellow traffic light will switch on informing others near the kicker table that it is reserved and soon somebody will come to play.

Reservation timeout is set to 3 minutes. After that, kicker table switches its state to free to play.

If You need, You can cancel reservation by writing „cancel” on the Slack channel.

System has also some other minor features like:

  • After reservation, buttons get freezed for 5 seconds. This is so to prevent situations, that just in the same time somebody reserve and a milisecond later somebody presses red button thinking that He/She is the one occupying the table but without a knowledge that somebody reserved the table just a milisecond before.
  • Pressing any button freezes both of them for half of a second. This is so to prevent crazy button clickers so Slack channel will not be spammed that much.
  • Free version of Slack allows to store 10000 messages by the whole team. To preserve some of the messages, service delete the old messages related to reservation/status system) and keep only last 6 of them. Why 6? Because most often there are 2 status scenarios: "Reserved-Occupied-Free" and "Occupied-Free". So the system can store at least 2 full occupied-free sessions. To clean all the system messsages, type "clean" (or "clear") command.

Releasing

IMG_20170410_115028.jpg
IMG_20170410_115021.jpg

Till now (the moment of publishing this instructable), the system is running for 2.5+ month and is used by more than 30 people. Because of the kicker table status update, we always know when it is free or occupied so we don't loose time going back and forth anymore. The connection and the service are very stable so we can rely on it.

So far, so good...

FAQ

Why reservation timeout is set to 3 minutes?

3 minutes is the max reservation time, adopt it as You like in the code. Generally it will rarely happen, that full 3 minutes will pass and reservation will be timed-out. In most cases somebody will come eventually and occupy the table.

Why playing timeout is set to 20 minutes?

Depending on a players, average playing time is ~10 minutes. If You need to play longer, press red button again when less than 5 minutes left and timeout will be extended back to 5 minutes. This timeout is set up just in case somebody forgets to release the table.

Why there is no PIN pad on the device to confirm reservation; no logins and passwords?

Main idea was to keep-it-simple-stupid. Otherwise, if reservation, starting and finishing the game need too much effort, then nobody will want to use it.

Why the device looks so industrial-ugly?

Because I didn't have laser cutter, CNC, 3D printer, fancy colored label maker etc. You are more than pleased to improve it and make it more beautiful.

Why not just implement some app and stick cheap tablet to the wall with the same functionality?

Apps, apps everywhere. People like to physically interact with things and not just tap on a flat screens.