The Twin Feed Monitor (Part 1 of 2)

In order to ease into ionic development, I came up with an idea for a display that shows the time elapsed since my twin boys last ate. My wife and I both have the Baby Connect app which we use to track feedings (and sometimes poopy diapers.)

Whenever one of the boys gets fussy, the first question asked is usually, “when did he eat last?” This is exacerbated when family is over helping to hold and feed babies. We have to reach for our phone, open the app, navigate to the appropriate child, and check the time of the last feeding. I know, first world problem.

Having done this enough times to go into problem solving mode, I thought it would be cool to have a display in the room which continously showed the last feeding times of each boy. Then, whenever someone feels inclined to ask said question, instead they could just look to the baby dashboard!

How is Babby Connect Formed?

As you might have guessed from the (clever) heading, I first wanted to see if I could reverse engineer the app and get the latest feeding times.

My first idea was to have the ionic app scrape the website. This would probably be pretty messy, so I decided to instead write a proxy service to do the scraping instead. On second thought, I decided the mobile app must be calling into a service that I should be able to call directly.

Since I can’t use fiddler on OSX, I had to find a replacement. I discovered a fantastic little “interactive, SSL-capable man-in-the-middle proxy for HTTP with a console interface,” called mitmproxy. On my phone, I just needed to enable the proxy settings to point at my laptop, install a CA Certificate, and now I can sniff the encrypted network traffic as I interact with the phone app. Here is the tutorial I used.

After some poking, I realized the app only synchronizes updates from other users (e.g. my wife adding a new feed time.) I was able to get a complete data dump after deleting/reinstalling the app, but that was a non-starter. So I had to figure out how to get every update including mine, not just those added by my wife.

The solution? Create a new user!

I registered a “bot” account, and gave it caregiver rights on my account. Now, I can create a service that polls for updates from both me and my wife.

I Feel Hapi

Now that I have the service request figured out, I could just called it from the ionic app. But their service requires things like authentication, and I’d have to track the last synchronized entries, so I still wanted to create a proxy that was simple to consume by my app. Another benefit is being able to patch the proxy service without having to deploy a new app. Separation of concerns and all that.

The easiest way I know to spin up a simple rest service is to use hapi.js. So let’s give it a shot.

Creating the Service

You can find the server code here.

Each kid is given a unique ID which I made configurable in a config.json.

{
    "uri": "https://seacloud-2.appspot.com/CmdListI?cmd=StatusList&lg=en",
    "username": "...",
    "password": "...",
    "kids": [
        {
            "id": "<kid1-id>",
            "name": "Baby A"
        },
        {
            "id": "<kid2-id>",
            "name": "Baby B"
        }
    ]
}

The service I’m calling is used for synchronization, so for each kid, you essentially need to ACK the ID of the last entry you received. I accomplished this by seeding a node-persist /persist/kid-map.json lookup file with an initial last property. I sniffed these values using mitmproxy.

{
  "<kid1-id>": { "last": "<kid1-last>" },
  "<kid2-id>": { "last": "<kid2-last>" }
}

I used the h2o2 proxy plugin to accept a GET \ request which internally makes a POST to the sync service. To request new entries, you zip the 2 values together in the query string like so:

config.uri + &kids=<kid1-id>,<kid1-last>,<kid2>,<kid2-last>

The response body includes any new entries for each kid since the specified last entry. I update the kid-map.json with these values to be used in the next call. I also store the feeding data.

My service then just dumps the kid-map.json file which now has the last feeding entry for each kid. This is much easier to consume than having to deal with auth and the sync logic. Every time you call my service, you are guaranteed to just get the last feeding entry for each kid.

{
  "<kid1-id>": {
    "last": "<new-kid1-last>",
    "item": {
      ...
      "e": "1/3/2016 12:07",
      "Txt": "Kid1 drank 4 oz of milk",
    }
  },
  "<kid2-id>": {
    "last": "<new-kid2-last>",
    "item": {
      ...
      "e": "1/3/2016 12:37",
      "Txt": "Kid2 drank 2 oz of formula",
    }
  }
 }

Finally, I used pm2 to keep the service running. The one issue I’m having is I can’t get the startup script to work correctly. When I reboot the server, the script appears to run, but I get a connection refused when hitting it. It starts working if I manually restart the service. Anyone know what I’m doing wrong?

Stay tuned for Part 2 where I create the ionic app to display the dashboard.

Tangled Up in Blue

The junk drawer is where obscure cables in my house go to die. My wife got fed up with the tangled mess and put them all in snack bags

tangled

Genius? I think so.

GitHub Images

I’m also testing out images on this blog. The free app CodeHub lets you upload images to github issues. I created an Images issue where I can easily post images from my phone. Then I just link to them here. No need to commit or push anything.

I don’t see any way to use the new git large file storage from my phone, but I’ll keep an eye on it.

How do you post images to your github pages

Posting from my phone

Trying out Octopage on my phone. Hoping this will make frequent blogging easier.

I could have made a simple app to create new posts using the github api, but for only $1 this will let me focus on the task at hand.

Let's start a blog

Reddit recently announced they are giving developers until March 17th to move to OAuth2. Originally, the deadline was August 3rd (oops), but I guess they decided to push it back (yay.) My iOS app Subdit uses RedditKit which at the time of this writing does not support OAuth2 (but has an open issue to add it.)

In addition to supporting OAuth2, I have a couple new features in the works that need a little polish. Having chosen to use storyboards, I feel like developing the UI is prohibitively slow. Also, the primary design consists of dynamically sized table cells which doesn’t really work that great on iOS. I mean, it works, but is incredibly cumbersome having to calculate each height based on the rendered text context and any chrome.

I also don’t have an Android app.

So I’ve decided to rewrite Subdit as a hybrid app on the ionic framework. Dynamic cell heights are trivial in html, plus I’m excited about Angular and have used ionic in the past.

My goal is parity with the current iOS app and releasing an Android version.

So what does any of this have to do with writing a blog? Well, apparently I’m using npm on OSX wrong.

Sudo all the things.

The first step is to update my install of the ionic commandline tools. The README says OSX users will need to sudo install it globally. But then you notice the following nagging remark

or users can setup proper file permissions on OSX for npm to install without sudo.

It is these types of discoveries along the way that I like to share with colleagues, usually through email. Though, for posterity I’d rather have somewhere to easily bookmark interesting articles and capture ideas.

So let’s start a blog.

What was I doing again?

Oh, right. Ionic. Well, instead of updating the commandline tools, I now have several tabs open for creating a blog, github pages, jekyll, and setting up a separate environment for ruby on OSX because apparently I’m installing gems wrong too.

If you are reading this, then we’ve successfully started a blog!

Oh, and I’ll also list movies I’ve recently watched that I liked.