I recently got into tracking my weight via Google Fit to keep track of its history and evolution over time; however that required me to step up onto the scale, read my weight, open the Google Fit app, wait for it to load and log a new entry... Way to complicate, don't you think? So, I went on and built a new scale using the load sensors of an old scale I had lying around.
It features four user capabilities, direct Google Fit weight logging, a simple button-led user interface, OTA updates, and a customizable Android notification system.
HardwareSince I have access to a wood working shop, I made the whole body of the scale out of wood. If you want to replicate the project you can use a variety of techniques, from 3D printing an housing for the electronic to stick to your old scale to making it out of metal, so I won't go into details here.
The important thing is to have the four sensor on a square pattern, to later wire them correctly to the ESP8266. You can buy them separately or use those of a cheap digital scale; mine was something like that in the image below.
For the interface I used four leds and two buttons: the leds will indicate the status of the scale (all on -> booting up; all flashing -> ready; one flashing -> user selected; two by two flashing -> OTA update mode; all fast flashing -> weight logged, turning off) and the buttons will turn the scale on from deep sleep (the left one, connected to the board Reset pin) and select the mode/user (the right one). Again, you can customize in any way your build (rotary encorer, an Android app..) so I won't give so much details here.
Once you're done phisically building the scale, we can start wiring it togheter.
The core of the electronics is a NodeMCU 8266, which reads the voltage output from the four load cells; since the built in ADC is not suited for so little voltages drop, we need to use a more accurate one: this is the reason we will use the HX711 24-Bit ADC which offers a much greater precision.
The four load cells are wired to the HX711 in a Wheatstone bridge configuration, to better manage uneven weight distribution and to "merge" the four reading in one. If you want to learn more about this configuration and about load cells, this Instructable is decently writte, so check it out.
The Arduino - or NodeMCU - will then communicate with the HX711 via I2C inferface to pull the readings. Again, this Hackster post can give you some more infos. To make things easier a library can be used - I used this one from bogde. Check which pins are used for I2C with your board; for the NodeMCU 8266 I used pin D1 (GPIO5) for data and D2 (GPIO4) for clock - for these are the default ones.
Last thing to be added are the buttons and the leds; I hooked up mine to pins D3, D5, D6 and D7 for the leds, the "select" button on D9 and the on/reset button between GND and RST.
After putting it all together we're done with the phisical part and can move on to the software side.
I know, I gave you barely any information/instruction on how I built it or how to build one... this depends on your skill with working with different materials and which tools you can use, so it was better to stay on the generic side.
Communicating with Google FitBefore tackling the software discussion we'd better take a look on how the ESP will log your weight entries to Google Fit. We will use Google's APIs and OAUTH2... It's a bit tricky, but bare with me.
First thing to do is to register a new Google APIs project: navigate to Google APIs Dashboard, log in or register if needed, then select "Enable APIs and services"; look for "Fitness API" and click on "manage". Now, on the left side select "Credentials," "Create Credentials," "OAuth Client ID," and "Web application."
You'll be asked for some infos: type a suitable name (ex.: "Smart Scale"), leave the other two empty - for now - and save.
On the screen two strings will appear, a Client ID and a client secret; save them on a txt file for later. Leave the Google APIs concole opened in a browser window.
In order to gain access to our Fit data via REST calls we must give authorization through our Google account; since it's a bit tricky to do on our own we will use Temboo's service.
Once registered to Temboo open their "Google OAuth initialize" page, and paste your client ID where asked. The scope used to write to Fit is https://www.googleapis.com/auth/fitness.body.write so go ahead and paste that too. Once you're done click "Run now" and then open the link under the label "AuthorizationURL": you'll be greeted by a "400, Error: redirect_uri_mismatch". This is why we didn't tell Google which redirect URLs are safe, so it won't accept any.
So... in the 400 page url look for the part "...&response_type=code&redirect_uri=https://[username].temboolive.com/callback/google&approval_prompt=force..."; what we care about is the url https://[username].temboolive.com/callback/google: copy that and head back to Google APIs console, open your newly created project, paste the url into the "Authorized redirect URIs" field. Save.
Now refresh the old 400 page: it shall now work! Sign in, authorize, click OK, etc... When a blank screen appears, you're done.
Good, back to Temboo: copy the CallbackID somewhere and open the second - and last - choreo (as they call'em), i.e. Finalize OAuth. Paste ClientID, ClientSecret and CallbackID we saved earlier and run. Boom. We are done with Temboo!
Copy the RefreshToken of the third field, that's the only string we care about now!
If you don't know how OAuth2 works, here is it simply: once granted access to our account to the API key we generated (what we have done 'till now) we'll ask Google to give us a temporary token (valid for one hour) which, together with our ClientID, will allow us to send POST requests to Google Fit servers.
But! But... we are not done yet.
We need to create a database in Fit to host our weight values. For this scope we'll use Insomnia.
Once donwloaded and installed it, open the software. On the left side select the plus icon -> "New request", name "Refresh token" type "POST". Save. In the upper url bar paste https://www.googleapis.com/oauth2/v4/token, under it click Body and select "Form URL encoded"; in the newly created form add four names: "client_secret", "grant_type", "refresh_token", "client_id", and add their values - the one we saved before from the console and temboo; for "grant_type" paste "refresh_token".
If this is too messy try pasting the following code in the url bar; this should populate the fields, you'll only have to paste your values.
curl --request POST \
--url https://www.googleapis.com/oauth2/v4/token \
--header 'content-type: application/x-www-form-urlencoded' \
--data 'client_secret=[your_client_secret]&grant_type=refresh_token&refresh_token=[your_refresh_token]&client_id=[your_client_id]'
Leave this apart; create a new request, name "Create datasource", method POST; from the Body menu below select the JSON option, and paste what follows:
{
"dataStreamName": "ScaleDataSource",
"type": "derived",
"application": {
"detailsUrl": "http:\\example.com",
"name": "arduino_scale",
"version": "1"
},
"dataType": {
"field": [
{
"name": "weight",
"format": "floatPoint"
}
],
"name": "com.google.weight"
},
"device": {
"manufacturer": "MeMyself",
"model": "ArduinoScale",
"type": "scale",
"uid": "9988012",
"version": "1"
}
}
In the Auth section select Bearer token: to have the token you shall run the request "Refresh token" we created earlier, and copy it from the JSON on the right side of the screen (the "access_token" item), then paste it in the bearer section of the "Create datasource" request.
Alternatively you can paste this curl:
curl --request POST \
--url https://www.googleapis.com/fitness/v1/users/me/dataSources \
--header 'authorization: Bearer [your_bearer]' \
--header 'content-type: application/json' \
--data '{
"dataStreamName": "ScaleDataSource",
"type": "derived",
"application": {
"detailsUrl": "http:\\example.com",
"name": "arduino_scale",
"version": "1"
},
"dataType": {
"field": [
{
"name": "weight",
"format": "floatPoint"
}
],
"name": "com.google.weight"
},
"device": {
"manufacturer": "MeMyself",
"model": "ArduinoScale",
"type": "scale",
"uid": "9988012",
"version": "1"
}
}'
Run this request too; if everything has gone well the right side of the screen should contain a JSON that sums up your newly created datasource.
With Google Fit we're done for now. We'll see later how to post new weight logs.
Communicating with Our Android DeviceIn order to send push notifications to an Android device we'll use Pushbullet.
After logging in into their site, go to the Settings page and click "Create Access Token." Copy the string. We will use that to authenticate when sending notifications from the ESP8266 to the Android device, via a HTTP request like the following one:
curl --request POST \
--url https://api.pushbullet.com/v2/pushes \
--header 'access-token: [YOUR_ACCESS_TOKEN]' \
--header 'content-type: application/json' \
--data '{"body":"[BODY_TEXT]",
"title":"[TITLE]",
"type":"note",
"device_iden":"[YOUR_DEVICE_IDEN]"}'
You can choose whether to use the "device_iden" or not; using it would target only a specific device, omitting it would send the notification to all the devices you are logged in with your Pushbullet account. More infos on the Pushbullet API website.
A more elegant solution to using pushbullet is to create an Android application and send to it push notifications using the Firebase dedicated service. In the Github project page you'll find the source code for that too, but I won't tackle that discussion in this post, because man, that would be a LOT of stuff to write down.
SoftwareOnce Google Fit and Pushbullet are out of the way, the rest of the code is pretty straight forward. There are mainly leds, interrupt and if statements involved, so it shouldn't be too difficult... Have a look to the Github repo if you're interested, I'll link it below.
As I said, a library for HX711 has been used; please refer to the example sketch of the library to calibrate the scale before using it.
Hope you liked this post! If you'll create a scale like mine, let me know.
Comments