Using Sunset to adjust Philips Hue Sensor On/Off Times

I’ve been meaning to do this for ages, and it turned out to be a bit easier than I thought. The Python I’m using is a bit rough and ready – rather than the 8 separate API calls to PUT the date changes back [4 rules for each sensor], I could do this with one API call, based on the single data structure for all of the rules. It doesn’t really matter that much.

I haven’t done anything for sunrise processing, which fits our usage patterns with the sensors.

Here’s the script, which I’m calling from cron, once a day, which is a bit of overkill. I could probably do it weekly:

#!/usr/bin/env python3

import requests
import json
import time
from datetime import datetime, timedelta

fudgeFactorMins = -30
morningOffTime = "T08:00:00"

The fudgeFactorMins variable is an offset for the actual sunset: I eventually subtract this from the sunset date. The rule numbers are not going to be nailed on, but they do appear to be contiguous for each sensor, in groups of 4:

# Format: "T20:00:00/T08:00:00"

# 8am / 8pm: day-on
bathroomDayOnRuleURL = "http://yourIP/api/yourKey/rules/1"
# 8am / 8pm: day-dark-on
bathroomDayDarkOnRuleURL = "http://yourIP/api/yourKey/rules/2"
# 8pm / 8am: night-on
bathroomNightOnRuleURL = "http://yourIP/api/yourKey/rules/3"
# 8pm / 8am: night-dark-on
bathroomNightDarkOnRuleURL = "http://10.40.0.3/yourIP/api/yourKey/rules/4"

# 8am / 8pdm: day-on
livingroomDayOnRuleURL = "http://yourIP/api/yourKey/rules/9"
# 8am / 8pm: day-dark-on
livingroomDayDarkOnRuleURL = "http://yourIP/api/yourKey/rules/10"
# 8pm / 8am: night-on
livingroomNightOnRuleURL = "http://yourIP/api/yourKey/rules/11"
# 8pm / 8am: night-dark-on
livingroomNightDarkOnRuleURL = "http://yourIP/api/yourKey/rules/12"

This is a bit messy but…

allUrls = [bathroomDayOnRuleURL,bathroomDayDarkOnRuleURL,bathroomNightOnRuleURL,bathroomNightDarkOnRuleURL,li
vingroomDayOnRuleURL, livingroomDayDarkOnRuleURL, livingroomNightOnRuleURL, livingroomNightDarkOnRuleURL]

The sunsetAPIurl refers to a free API. I had a look at one implementation on StackOverflow which calculates locally. This endpoint is returning results within a few mins of the app on my phone, which is certainly good enough.

One slight nuisance is that I need to adjust for British SummerTime. What I’m doing for now is using Daylight Saving as the Python datetime library gives you it for free. It’s going to ‘wrong’ for the week or so when DST and BST are out of synch at the start and end of the summer, but I can live with that for now:

sunsetAPIurl = "https://api.sunrise-sunset.org/json?lat=yourLat8&lng=-yourLong"

def getSunset(sunsetAPIurl):
   r = requests.get(sunsetAPIurl)
   jsonData = r.json()
   # date format is 8:08:18 PM
   dateFromJson = datetime.strptime(jsonData["results"]["sunset"], '%I:%M:%S %p')
   if is_dst():
     adjustedSunset = dateFromJson + timedelta(hours=1)
     return adjustedSunset
   else:
     return dateFromJson

def is_dst( ):
    return bool(time.localtime( ).tm_isdst)

So another quick adjustment to reformat to the requirements of the Hue endpoint date handling, after processing the fudge factor:

def adjustSunsetToString(sunset, fudgeFactorMins):
  fudgeAdjusted = sunset + timedelta(minutes=fudgeFactorMins)
  return fudgeAdjusted.strftime('T%H:%M:%S')

def hitEndpoint(allUrls, dayOnString, nightOnString):
  for oneUrl in allUrls:
    r = requests.get(oneUrl)
    jsonData = r.json()
    currentDate = jsonData["conditions"][0]["value"]
    #print("currentDate: " + currentDate)
    ruleName = jsonData["name"]
    #print("rulename: " + ruleName)

The dates that I push back into the JSON need to conditionally flick around [earliest / latest or vice versa], which I do based on the substring search for ‘day’ on the rule name:

 
    if "day" in ruleName:
      jsonData["conditions"][0]["value"] = dayOnString
    else:
      jsonData["conditions"][0]["value"] = nightOnString
    newJsonPayload = {"conditions": jsonData["conditions"], "actions": jsonData["actions"]}
    r = requests.put(oneUrl, json = newJsonPayload)
    #print("response: " + r.text)


sunset = getSunset(sunsetAPIurl)
adjStrDate = adjustSunsetToString(sunset, fudgeFactorMins)

dayOnString = morningOffTime + "/" + adjStrDate
nightOnString = adjStrDate + "/" +  morningOffTime

hitEndpoint(allUrls, dayOnString, nightOnString)

 

Deleting My Apps From The App Store…

Five and a bit years after I released my first app, WeighMe, I’ve just deleted it and Pin Your Pics from the App Store. Here were the total downloads:

Total App Downloads

The reason I’ve zapped them is simple: it doesn’t make sense to continue to invest serious amounts of time in Objective C, in [for Pin Your Pics in particular] what developed into pretty large and complicated codebases. Apple made an announcement quite recently that support for iPhone X screen dimensions is about to become a mandatory requirement, which was going to be quite a bit of work for me.

But the more immediate death knell for Pin Your Pics came a few weeks ago when Google announced a change to their Maps API. Up until this month you could get an API key, and it would just stop working above a fairly generous threshold. Now you have to sign up with your card details. While my app usage is unlikely to trouble the new limit, it’s a chance I’m not prepared to take.

I am a bit gutted that, when Google cut over the API, the app is going to break quite unceremoniously, which is a bit rubbish for people using it. But I hadn’t updated it in ages and it was starting to get fairly unstable anyway.

I still code up the odd utility in Objective C but I’m not going to renew my developer subscription when it expires this year: I really can’t see myself publishing any more apps.

Some interesting numbers buried in the 5k download total. More than half were in China. I have no idea why. Also, that spike last September was weird: 1.9k downloads that month alone. I did absolutely no marketing for either of the apps. Finally, to my lone ‘customers’ in each of Uzbekistan and Kazakstan, thank you for using my apps, whoever you are :).

Fitting a Mastery Bridge to an American Pro Jaguar

I bought a Mastery M1 to replace the stock Fender bridge on my 2017 Jaguar during the week. I asked at a store to double check that it was compatible – I wasn’t sure if I needed the kit, including the thimbles – and was told it was.

I then found that the posts on the Mastery were too wide, by about a millimetre or so.

I searched everywhere online to try to figure out what I needed to do to fit the thing. I was hoping that it would be something that I could do myself, but I really didn’t want to tackle anything that was irreversible.

I couldn’t find anything specific to the American Pro, which is why I’m writing this up, on the off chance that Google lands someone else here who is thinking of doing the same thing.

Long and short of it, it’s a doddle. The plastic mountings [thimbles?] that the stock bridge fits into are less than a centimetre deep. I very carefully levered them out of the metal fittings they are inserted into using one of the Allen keys that came with the Mastery. As I couldn’t tell the dimensions of them before I started, I initially thought I’d have to take them out and replace them with the Mastery thimbles.

You don’t need the Mastery thimbles.The M1 fits perfectly on its own.

Here’s a quick snap showing the little mounting that I removed:

American Pro Jag with Mastery M1 Bridge