Makerlog #8 - State Management of IoT Devices - Firestore vs MQTT

Scoreboard with Firebase winning 1-0 against MQTT

One of my freelance products I have worked on a few years back is a scoreboard for a local football club. The scoreboard software runs on a Raspberry Pi, and a user has to use TeamViewer to connect to the Pi and access the controls, not the most user friendly.

To improve the user experience I had quickly build a small progressive web app. Using MQTT to send data to the scoreboard. This led to a few problems.

topic: scoreboard
payload: {
	field: "homeTeamScore",
	value: 1
}  
   

First, I had to maintain the app, the scoreboard and the MQTT server. If one fails all fail. Not the ideal scenario since I’m just maintaining it on the side.

Second, there is no central state management, when another users connects to the scoreboard it has no idea what the first user has already sent to it. It’s possible to request the state from the device every time. But it’s not very handy.

And third, I had a bug with the timers. When a timer was started in the app, it would start the timer on the scoreboard with a few seconds delay, and sometimes when the timer was paused, it would continue running. I’ll elaborate on this issue and my fix next week.

So, how did I tackle this issue? Firebase! I moved all the data, like team and team logos to Firebase. I’m also planning to deploy the scoreboard software and the app both from Firebase Hosting.

For the state I’m using Firestore Real Time Database. I created a collection "state" with a document "gameState" and this object has all the data I need. The selected teams, the score, elapsed time etc. With Firestore Real Time Database both the scoreboard and anybody with the app can listen to this state, when one client performs an update this will be propagated to all the other clients and the scoreboard.

{
   "awayScore":1,
   "awayTeam":{
      "image":"https://link.to/awayteamlogo.png",
      "name":"Away Team"
   },
   "elapsedTime":0,
   "homeScore":2,
   "homeTeam":{
      "image":"https://link.to/hometeamlogo.png",
      "name":"Home Team"
   },
   "id":"scoreboard",
   "startTime":"19:30",
   "status":"PLAYING",
   "timerTimestamp":null
}
  

I’m still not sure if it’s an anti-pattern and I’m sure it will have it’s downsides. For example I don’t think the game state can handle big amounts of updates in a short time. But for this use case it works and I have almost nothing to maintain anymore!

Scoreboard deployed in the real world.