When Function App updates won’t save…

I accidentally deployed a dodgy bit of code to one of my function apps. Then, even when I tried to revert to a “known good” version of my code via the GUI, it still didn’t work. No matter what I did, I kept getting the dreaded “Compilation Failed” error – but there was no more information. No useful compilation errors…

2016-10-23T20:35:46.853 Function started (Id=5ededb27-6144-40d1-8d14-8db77d70b771)
2016-10-23T20:35:47.901 Function compilation error
2016-10-23T20:35:47.901 Function completed (Failure, Id=5ededb27-6144-40d1-8d14-8db77d70b771)
2016-10-23T20:35:48.369 Exception while executing function: Functions.fetchDepartureBoardOrchestrator. Microsoft.Azure.WebJobs.Script: Script compilation failed.

It was so frustrating. Until I worked out that you can actually restart the power app host – just go to the Function App Settings then click “Go To App Service Settings” at the bottom.  You’ll see the traditional “full” properties and settings blade, and at the top is a “Restart” button. Then I was able to save my updated code.

National Rail LDBWS to Twitter

I’ve been playing around with my Nextion and a Particle Photon for a while. The idea is to pull data from a variety of services and have it available on a display by the front door – things like the weather, the outside temperature (from my Netatmo), and the next 3 trains to Seven Sisters from our station. Living, as we do, at the end of the Enfield Town branch line, it can be a bit hit and miss as to whether or not you make the train, or if it’s even running.

Anyway, I got the first part of this working. I regularly poll the National Rail SOAP API, parsing the content in to a simple minified JSON format using a Power App. Took me a while.

Then I discovered that someone has written a JSON proxy for the LDBWS. I’ll try that next.

missing dependencies Microsoft.CodeAnalysis.CSharp.Scripting

While trying to install the C# scripting package Microsoft.CodeAnalysis.CSharp.Scripting from nuget, but was getting odd messages about missing dependencies. I spent ages trying to figure it out as all the dependency versions appeared to match (e.g.

Unable to find a version of ‘Microsoft.CodeAnalysis.Common’ that is compatible with ‘Microsoft.CodeAnalysis.CSharp 2.0.0 constraint: Microsoft.CodeAnalysis.Common (= 2.0.0)’, ‘Microsoft.CodeAnalysis.Scripting.Common 2.0.0 constraint: Microsoft.CodeAnalysis.Common (= 2.0.0)’

however, eventually I discovered that you neeed .NET 4.6. Doh!

Logic Apps are so expensive!!

I started writing EnfieldTownBot using Azure Logic Apps. It’s pretty easy, but i soon hit a challenge – it’s so expensive! My app was pretty simple – a trigger, a “for…each”, a condition and a http callout to my Twitter Poster Function App:

enfieldtownbotlogicapp

So – if there are no delays, that’s (recurrence + httprequest + foreach + 3 x (condition)) = 6 actions. There could be up to 9 if the postToTwitter action also triggers. I want to run this function 2x (once for trains FROM Enfield Town, once for trains TO Enfield Town), so that’s 12-18 actions per request. And I want to run it every 15-30 seconds to get the latest information published ASAP. So that’s 48-72 actions per minute. Over a day, that’s 69,120 to 103,680 actions. Over a (31 day) month, that’s 2,142,720 to 3,214,080 actions. Taking a mean of these (2,678,400), and looking at the current pricing, it would cost me £450 a month to run this app. Wow. I don’t care about late trains THAT much…

So – I rewrote the whole lot as a function app (actually 2 or 3 function apps, as some of the items, such as parsing the XML from National Rail to JSON are reusable elsewhere). Each execution takes about 300ms, and it executes (24 hours x 60 minutes per hour x 4 times per minute) = 5,760 per day. Over a month that’s 178,560 executions. That’s well within the “permanent free grant” provided for Functions. In fact, I’d have to run it something like 30,000,000 times per month, or about 600 times per second to even hit a cost of £1.

Twitter bot as a function app!

After my last post, I spent some time looking through this. Eventually, I found a really lightweight class which does what i need:

https://gist.github.com/sdesalas/c82b92200816ecc83af1

After spending some time adding some error handling to the api.request() method, I then wrapped a webrequest around it and created a function app. You can find it here: https://github.com/mnbf9rca/TwitterFunctionApp

the app takes a simple JSON:

{

  oauth_token: “<your oAuth token>”,

  oauth_token_secret: “<your oAuth token secret>”,

  oauth_consumer_key: “<your consumer key>”,

  oauth_consumer_secret: “<your consumer secret>”,

  “tweet”: “<the message to send>”

}

You can obtain the oAuth token and oAuth secret by following the instructions on the Twitter Developer site.

The Function App will return a JSON with the data returned by the Twitter API, or an error. Note that as long as it gets SOME response from the Twitter API it’ll return a 200 code. In future I’ll work on making this more granular (e.g. pass through 50x errors).

BMW API

Earlier this year, we got a new car, a BMW 3 series. It came subscribed to the BMW ConnectedDrive service, and that comes with an iPhone or Android app. So, of course, I immediately set about deconstructing the traffic to figure out what was going on, inspired by the work of Terence Eden. Unfortunately, BMW appears to have implemented certificate pinning in the time since Terrence wrote his paper, so my favourite tool, Charles Proxy, was useless – the BMW app simply dropped the connection.

So – I decided to reverse engineer the iphone app itself. I finally managed to get an OAuth appID and app secret from the code base – only to discover that the /webapi/v1/user/vehicles/:VIN/status method now requires location:

{
  "error": {
    "code": 500,
    "description": "(SmartPhoneUtil-A-101) Mandatory
parameter(s) missed or blank: dlat and dlon are required for BMW
vehicles!"
  }
}

if i add the lat + long of my home as querystring paramaters (/?dlat=x&dlon=y) it works but i don’t get a lot of other data (e.g. door status) although i guess that’s to do with the options available on my car:
{
  "vehicleStatus": {
    "vin": "(my VIN)",
    "updateTime": "2016-08-28T17:52:44+0200",
    "position": {
      "lat": "5x.xxxxx",
      "lon": "-y.yyyyy",
      "status": "OK"
    }
  }
}

Here’s the problem – if the car is more than half a KM from home, when i get:
{
  "vehicleStatus": {
    "vin": "(my VIN)",
    "updateTime": "2016-08-28T17:52:44+0200",
    "position": {
      "status": "TOO_FAR_AWAY"
    }
  }
}

(not sure what the “updateTime” value is as that’s clearly a long time ago).

Bummer.