Xiaomi Mi Band: Re-enable Early Bird Alarm

• Android • Comments

I bought a Xiaomi Mi Band 1S one year ago solely for the reason of taking advantage of the “Early Bird Alarm”. This feature essentially tells the band to watch your sleep cycles 30 minutes before your set alarm and wake you up if it detects you are in a light sleep some time during this timespan (you probably knew this already, why are you here otherwise? ;-}). Sadly, Xiaomi removed this feature some time in 2016 without ever mentioning why or if it ever returns. As I don’t use my band for everything else, I recently decided to recover my “Early Bird”. I was successful and want to share all the actions I tried in case others have a similar need for returning their smart alarm. I assume these steps can be applied to other Mi Band versions (Mi Band 1, Mi Band 1S, Mi Band 2) as well.

Prelude: I’m not certain if every action is needed. I tried dry testing my changes but all changes failed the tests, including the (fully working) one I’m using now. So I advise on “live” testing every change for two or three nights if you don’t want to pull completely through with everything. If you find out only parts of it are needed, I’d appreciate if you left a comment afterwards.

That said, here are all the steps I took to regain the Early Bird Alarm on my Mi Band:

1. Disable all Alarms in the Mi Fit App: This should be done before fiddling with other apps. Either disable the alarms in the Mi Fit App or straightforwardly delete all of them. Not doing this might result in failure of tests for all other steps.

2. Use alternative Apps: There are three Apps I know of which could still be able to set Early Bird Alarms, Notify& Fitness for Mi Band (free version available), Tools & Mi Band (2,99€) and the Open Source App Gadgetbride. Although I suspect all three Apps use the same mechanism to set an Early Bird Alarm, I’d still recommend trying all three after every step, just to be sure. I might eventually do this myself, so perhaps I’ll write an update in a few weeks or months. Please note that there are some Apps out there which advertise similar features but need to be connected to the band as soon as the “Early Bird” phase starts. My phone is either off or in Airplane mode at night, so this was no alternative for me. Still, this implementation is an easy way out.

3. Uninstall the Mi Fit App: If you don’t use your Mi Band for anything else except Alarms (like me), uninstall it. It’s possible that a future Firmware Update to the Mi Band (which is distributed via the Mi Fit App) completely purges the possibility of Early Bird making all your experimenting futile, so I’d get rid of this risk. Additionally depending on your nightly test results, you might install a different version of the App and need to uninstall your current version anyways.

4. Downgrade the Mi Band Firmware: Using Gadgetbride you can downgrade the firmware of the Mi Band. There’s a good article regarding this process in the Github wiki of the Gadgetbride repo, so I suggest you stick to this for a firmware downgrade. You need to get the *.fw file first which needs to be extracted from an older APK of the App. I use APKMirror.com for this. Early Bird Alarm was removed with version 2 of the Mi Fit App, so look for 1.x versions of the App. I personally tried the Mi Fit version 1.5.912 (1539) which contains the Firmware version and 1.8.711 (1610) which contains Firmware version According to the Gadgetbride wiki version is the best fit for my Mi Band 1A. I still settled with v05.15.12.10, but that’s more coincidence than intent. You will need to either use an alternative App for setting your alarms or the old version of Mi Fit containing this firmware. I wasn’t able to get the old versions of Mi Fit connecting to my band, but it might work for you. You can also try to combine an older firmware with a newer App version via injecting the old firmware file into the new App. You can use my blog post on how to modify and repackage Android Apps as a starting point for that. Afterwards I advise to do nightly tests again.

For now, the combination I use are the Firmware version and the “Tools & Mi Band”-App to set the alarms. This is pure chance, I already gave up on restoring the Early Bird functionality when it suddenly worked the night I used this combo. But as I already mentioned, my dry testing didn’t properly work for this combination either, so it’s very possible that other solution mixtures work as well and I might restart testing some time in the future.

If you find a different working solution, please comment with your Mi Band version and the solution so others can be helped as well.

Kubernetes Single Node installation on CoreOS Container Linux

• docker, Linux, and coreos • Comments

I’ve been playing with Kubernetes on CoreOS Container Linux for a couple of months now. As I prefer to implement real world workloads instead of examples, I planned on containerising a couple of applications my family and I rely on. Beforehand I wanted to create an easy way for installing a Kubernetes cluster spread across multiple VPS providers, securely connected over the internet via VPN or something similar. I did a speed test for initial evaluation of different methods and began working on a proof of concept CoreOS Kubernetes cluster secured via tinc. This prove more difficult than initially planned, taking me months for a simple setup and setting me back multiple times.

Therefore I settled with a Kubernetes installation residing on a single node. The clustering was a bit overkill for family applications anyways and this step just took to much time. For the Single Node installation I found a blog entry from Victor Palau who also created a GitHub repository for an automated Kubernetes installation to an existing Container Linux server. I tested his script on my server from Chicago VPS and although it largely worked, I was dissatisfied. As the script was initially intended to be run on Microsofts Azure, the requirements a bare metal installation has were not taken into account:
A couple of ports meant for internal use only were publicy accessible, insecure etcd2 being the worst one. Furthermore I didn’t like the apiserver listening on port 443. While on Azure you’d normaly prepend a Load balancer in front of the Single node, this doesn’t apply to a Bare Metal installation. Thusly HTTPS was effectively blocked on the node and there was no easy way for integrating a containerised load balancer like Træfɪk. Addtionally there were some smaller problems or additions I had in mind and wanted to integrate into the automation to ease installations for others and a possible reinstallation for myself.

So I took Victors script and expanded it to be more “Individual Production Ready” by:

If you want to check it out, you’ll obviously need a running CoreOS Container Linux installation. The steps you have to do on the server are quite simple:

git clone https://github.com/m3adow/k8single
cd k8single
./kubeform.sh [myip-address] [DNS entry for K8s apiserver (optional)]

You can use the second argument on kubeform.sh to add an additional FQDN to your API server if you want to use a FQDN for connection instead of an IP.
Afterwards you should be able to access the dashboard via https://fqdn-of-your-server.com:6443/ui authenticating with the credentials the script displayed at the end.

I still hope I can revisit my project to get a secured Baremetal Kubernetes cluster running one day, but for now this Single Node installation satisfies my needs. If you have any questions or remarks, feel free to comment.

Container Linux: Get a TTY without password

• coreos • Comments

I’ve been experimenting a lot with CoreOS Container Linux (formerly simply CoreOS). One of the issues I’ve had regularly was getting my cloud-config to the server after an initial install. There’s no meta data drive or something similar on bare metal servers or normal VPS.

Easy solution: Bypass the authentication. If you have access to a VNC or something similar, you can add coreos.autologin=tty0 (or just omit the =tty0) kernel option to get to a login shell directly. If you don’t know where to put that, it needs to be put in the Grub command line. Here’s an image of it.

Container Linux Grub

So you need to press e in the Grub menu, enter the option behind the original options (in my case I put it behind $linux_cmdline) and press Ctrl+x or F10 afterwards to boot with it.

That’s it, your window will now put you into a login shell of the coreos user and you’ll be able to curl cloud-config.

Simplifying cloud-config creation for clusters

• coreos and cloud • Comments

I’m still experimenting with container orchestration. Currently I’m in the process of building a three node CoreOS cluster with Kubernetes on top of it, connected over the Internet. One problem I was constantly struggling with was keeping my cloud-configs in sync. Most of the configuration settings were identical or nearly identical on all three nodes. Still, when adding a small change, I needed to apply this change to all three files. Forgetting one or mistyping led to errors and unnecessary debugging sessions.

This weekend I decided I’ve had enough of it. I created a small Python script to simplify working on several nearly identical configuration files, cloud-config-creator. By iterating over a set of node values and one master template the script creates the cloud-configs for all nodes. It’s little more than a wrapper for the Jinja2 templating engine, but I still find this incredibly useful. That’s why I want to add a bit more explanation around it.


You will need Python. I used Python 3, never tested it with 2.x. Furthermore you need to install the pyyaml and jinja2 modules. Before starting to use cloud-config-creator you should have basic knowledge of how to use templates. If you ever worked with a templating engine (e.g. for consul-template or Jekyll), you’ll quickly feel at home. Otherwise I recommend the Jinja2 documentation.
Furthermore you should know how to format YAML. My script uses PyYAML, which isn’t YAML 1.2 compatible (yet), so you’ll need to use YAML 1.1.

Script usage

./cloud-config --templatefile master.tmpl --valuesfile values.yml --outpath out/ --includepath includes/

Running Caddy and Go on ARMv6 Alpine Linux

• docker, go, raspberry pi, and linux • Comments

My goal was compiling Caddy for my old Raspberry Pi 1 Model B. Caddy only provides an ARMv7 binary which isn’t compatible to the original Pis ARMv6. My Raspi is running on Hypriot, the Docker distribution for the Pi, therefore I wanted Caddy to run in a container as well. I chose my own Alpine Linux base image as its foundation.

As Caddy is written in Go, compiling it from source should be very easy:

  1. go get github.com/mholt/caddy/caddy
  2. cd into your website’s directory
  3. Run caddy (assuming $GOPATH/bin is in your $PATH)

While trying to get Go running in my Alpine container I encountered a small problem.
Go officialy provides an ARMv6 binary package, which is able to natively run on the Pi. But when trying to run this package in my Alpine container, a rather nondescriptive error blocked me:

/bin/sh: go: not found

I admit I needed longer than expected to solve this problem. After straceing, debugging and a lot of Internet research without result, using a simple file gave me the deciding hint:

/go # file $(which go)
/usr/local/go/bin/go: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, not stripped

Go is looking for /lib/ld-linux-armhf.so.3 which isn’t available on a minimal Alpine Linux installation. Running apk add libc6-compat finally solved this problem.