31

Building a complicated system to get me to drink water

 5 years ago
source link: https://wanderdata.com/water-platform/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

October 17, 2019

How (and why) I built an over-complicated data-driven system to remind me to drink water

Data, Golang, Python, Android, Docker, gRPC, Firebase, Cloud, BigQuery. Oh my!

How (and why) I built an over-complicated data-driven system to remind me to drink water

Water. Agua. H2O. The elixir of life. The envy of the other planets.

Yet as essential this divine liquid is to us humans, we, and by we I mean I, usually forget to consume it. At the time of writing, I’m backpacking through Asia. Amid the excitement, enjoyment, and adventures of my new life, drinking water is a thought that barely crosses my mind. And when it does, I typically disregard it telling myself, “Nah, I’ll be fine. It’s just water. I’m not thirsty anyway.” But then, the night arrives, and in the winding down of what was another successful day, the headaches and tiredness come, reminding me that I should have refilled my bottle. Obviously, I had to find a solution.

As a data practitioner, of course the solution had to involve data. But I wanted more than that —  I wanted something exaggerated. My problem could have been easily solved by setting a timer or by downloading one of the many water-drinking-related apps. But no — again, I wanted more. Suddenly the problem became more a matter of how far can I take my solution than just reminding me to refresh my life a little. But a more realistic reason why I built this is because I honestly missed working with such a system. Back when I was employed, I used to deal with data, Golang, cloud, and production systems every single day. Now I don’t. So, I wanted to put together a system, where I could use all these tools (also I don’t want to become rusty, since I know I’ll have to impress the recruiters once I decide to say goodbye my outdoor adventures and replace them for an office chair).

DJI_0644.jpgWater (but non-potable). Photo by me (https://www.instagram.com/juandesr)

My over-complicated platform, which I named Team Aqua after the famous Pokemon villainous team who wanted to expand the sea, destroy all human civilization and return the world to its original state (Pokemon can be very, very violent), uses the following platforms/services/components:

  • A Fitbit device
  • Fitbit’s API
  • One Python service
  • Two Golang services
  • gRPC (and thus, Protobufs)
  • Firebase (Messaging Service)
  • An Android app
  • Docker
  • Google Cloud’s Container Registry
  • Google Cloud’s Compute Engine
  • BigQuery
  • Google’s Data Studio

In this piece, I’ll describe how I built the system, how it works, and of course the source code behind it. However, for simplicity reasons and to keep this piece as short and focused as possible, I won’t explain every nook and cranny of the platform —  e.g., what Gradle is and why is it used on Android. Nonetheless, at the end of the article, you’ll find a link to the system’s repo.

Now to the explanation.

C70A7839.jpgMore water.

Overview

Before I start to explain each component, I want to give you a small recap showing the system’s architecture, all the moving pieces, and what they do. The beginning of this lovely tale takes place on my Fitbit watch (or app). Here, I’m going to entry each water session (let’s call it that), generating in the process the data the platform needs (that’s why I’m calling this a data-driven solution). After logging the water session, this data will be sent to Fitbit and stored there.

To retrieve this data, I have a Python service (called Water Retriever) that talks to Fitbit’s API every X minutes and gets all the water sessions I’ve logged today. Then, the Python client will communicate through gRPC, with the back-end (written in Golang), which I named Archie, after Team Aqua’s leader. Archie’s role is to keep the water sessions in memory and write them into BigQuery.

Besides Archie, there’s a second Golang component, called The Reminder. This little fella will ask Archie, every X minutes, for the amount of water I’ve consumed during that time. If I’ve consumed not a single drop of water during this time, it will send a notification to an Android app I wrote as part of the platform, reminding me that I haven’t had any water in the last X minutes. Otherwise, if I have hydrated myself, the notification will congratulate me, saying I’ve drink Y ml. of water in the last X minutes. The push notification is handled by Firebase Cloud Messaging.

The three services are contained in the same Docker image, which is hosted in Google Cloud’s Container Registry. Said image is executed on a “normal” Compute Engine machine (not a Kubernetes cluster, Cloud Run, or any of that fancy stuff). Lastly, to analyze the data, since it already resides in BigQuery, I just run a couple of queries and visualize them using Google’s Data Studio.

The following image is a chart of the complete architecture.

team-aqua.jpgI should get a drawing tablet

First, there’s me, logging the water data in Fitbit and sending it to their servers. Then, Water Retriever (WR) gathers this data and sends it to Archie, who keeps the data and writes a copy in BigQuery. Next to it, there’s The Reminder, who gets data from Archie and send a notification that ultimately is read by me.

In the route below Archie, there’s BigQuery, who provides data to Data Studio for me to analyze it.

Now, without further ado, let’s look at the specifics.


Fitbit Device

The system’s entry point and the place where the data is generated is my Fitbit. Here, every time I drink water, I’ll enter the amount of it. How do I really know the exact quantity? Well, I don’t! Unless I’m drinking from a bottle that has its volume written on it, I usually just estimate it.

image.pngMy Fitbit (a bit dirty), and Fitbit's app.

Python Service (Water Retriever)

The first of the services I want to introduce is Water Retriever, a Python program that queries Fitbit’s API every X minutes to retrieve how much water I’ve consumed on the current day. To develop it, I used the phenomenal library, python-fitbit, to interface with the API. This is the code:


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK