You'll have noticed I haven't updated much recently. Even when I did, if was with distinctly non-tech stuff. The reason being I've been busy. Not "I've got a big to-do list" busy or "I've had a couple of browser tabs open for a few weeks that I'll get round to eventually" busy, either. I've got a text-file to-do list that's been open, unsaved in the background since January 2017 and there are a couple of background tabs I've been meaning to get round to reading since late 2014. Really.
A couple of years back, a few of us got interested in how IoT devices could work with location. What's the smallest, simplest device we can connect to the cloud and pin point on a map? Within a few weeks, we had a basic cloud and at CES in January this year, we launched a fully-fledged product. In that time, I've moved from 'prototyper who built version 0.1 on his laptop during the Christmas holidays' to something roughly equivalent to CTO of a medium-sized tech company. Not bad.
What's it do?
In essence, a small IoT device with some combination of GSM, WiFi and Bluetooth does a scan to find out what wireless networks, Bluetooth beacons and cell towers are visible and how strong they appear. They send their scan to HERE Tracking where it gets resolved into a latitude/longitude and then saved. The best bit is that it works indoors and outdoors.
Look, we've even got our own shiny video with cheesy voiceover!
And another that shows what it actually does!
There are a bunch of other features as well such as geofences, notifications, filtering, etc. but the main focus is this large-scale ingestion and storage of data.
At this point, our original Tracking team has grown to include HERE Positioning (the clever people who actually figure out where the devices are) and HERE Venues (we recently acquired Micello). By combining, the Tracking, Positioning and Venues bits together, we can follow one of these devices from one factory, across the country on a truck or train, overseas, into another country, into another factory, out into a shop... and so on.
Seeing as both Prolog and CSS are declarative languages, I found myself wondering if it would be possible to create a mapping from one to the other. It was an interesting thought experiment that quickly found itself being turned into code.
Way back when, Prolog was actually one of the first languages I learned to program in. It had been a while since I'd last used it for anything (a chess endgame solver in high school, I think) so I looked up an online tutorial. The following example is derived from section 1.1. of Learn Prolog Now
Simple rules
If you think of Prolog facts as denoting true/false attributes of elements, you can consider every known item in a KnowledgeBase (KB) as a DOM Element. For example:
mia.
Is equivalent to:
<div id="mia"></div>
While
woman(mia).
Equates to:
<div id="mia" class="woman"></div>
You can make multiple statements about an item in the KB:
The only real issue is that CSS values can’t be aggregated. If they could be, you could always use the same attribute (e.g. box-shadow) and combine them:
And here are the queries that could be answered by looking at the visual output:
?- woman(mia).
Yes (the element with id="mia" has a yellow background)
?- playsAirGuitar(jody).
Yes (the element with id="jody" has a solid black border)
?- playsAirGuitar(mia).
No (the element with id="mia" does not have a solid black border)
?- playsAirGuitar(vincent).
No (there is no element with id="vincent")
?- tattooed(jody).
No (there is no CSS style for a class '.tattooed')
?- party.
Yes (the element with id="party" exists)
?- rockConcert.
No (the element with id="rockConcert" does not exist)
Sure, it's all a bit silly but it was quite a fun little experiment. There are probably a few big aspects of Prolog that are unmappable but I like to think it might just be possible to create a chess endgame solver using nothing but a few thousand lines of CSS.
Thanks to some great work by Daniel Wabyick and his team, Hardy has had a bunch of improvements over the last few weeks.
The biggest change in this version is that, if you have GraphicsMagick installed on your machine, Hardy will use it for native image diffs but fall back to the built-in method if you don't. The current image diff technique involves creating an HTML page with a canvas, opening that with PhantomJS, loading the image into the canvas and using imagediff.js to calculate the diffs. It works everywhere PhantomJS works but it's slow. Daniel benchmarked the difference and it's a huge performance gain if you rely on image diff tests.
There's also some minor improvement around logging and the cucumber report format but I'll write about them later once I've had a chance to update the Hardy website.
I've been working on a new little side project recently (more info soon) which involves a Chrome Devtools extension. These are Chrome extensions that aren't targeted at changing your usual browsing experience like a normal extension but are actually aimed at modifying or providing extra behaviour for the Chrome Devtools panel. It's a little bit meta.
The theory behind them isn't that tricky and if you have any experience with standard Chrome extensions, you'd probably 'get' devtools extensions quite easily. Unfortunately, I was coming in with no prior knowledge at all and got quite lost for a few days. The docs are very helpful and the Google Group is handy but it still took me a while.
The main area I had difficulty with was the message passing. Sending info from my panel in the devtools window to the page being inspected and vice versa proved to be... complicated. I've used message events before but it still took me a while to figure out what was going where. It seems there are three individual execution contexts:
The Panel
The Background
The Page
They each have access to different bits of the Chrome Extension API and the inspected page. I won't go into details of that here as others haveexplained it better. What I will do, though, is share this project - Devtools Extension Starter Kit. This does nothing more than create a panel containing three buttons. The first executes a snippet of JS in the context of the inspected page, the second attaches a complete JS file to the inspected page (allowing execution) and the third replaces the entire inspected page with a button. When you click on this button, it will send data back from the inspected page to the devtools panel.
Essentially, it's all the communication channels I found I needed for my extension and should be a useful starting point for anyone wanting to do something similar.
I also heard today about a new Yeoman generator that makes building Chrome Extensions easier. It would probably have made the first bit of my investigations a lot easier if I'd known about that beforehand.