Getting Started with Cal-HeatMap and the AngularJS Cal-HeatMap directive

Working on my AngularJS app that visualizes historical playback of received Amateur Radio signals (www.spotviz.info) I wanted to have a ‘heatmap’ type display that shows density of the received signals per day (or hour). Searching around, the most common library to display a heatmap seems to be Cal-HeatMap. And since this is an AngularJS based app, it makes sense to use a directive to display the heatmap in my view where needed – Angular Cal-HeatMap seemed to be what I needed.

Starting with anything new it’s far easier to build something small that works first, and then include it into something larger/more complicated. Here’s my standalone test app using Angular Cal-HeatMap with Cal-HeatMap. It has hardcoded data, just to show the heatmap rendering.

The first issue I ran into, was that my standalone app was rendering fine, but copying the same directive usage into my SpotViz app, I could not get the directive to recognize my config options, or render any data.

As with everything I’ve found so far with AngularJS, sometimes stuff that should be easy turns out to be hard, but in most cases only because I don’t understand what’s going on, or how I assume it to be working is completely wrong :-) At least I’m not the only one who finds this about AngularJS, to quote Nathan LeClair from one of his posts:

"As I’ve gotten a little into AngularJS I’ve been surprised
by how often my assumptions about how things will work 
have turned out to be wrong".

Lesson #1:

I don’t know if this is an issue specifically with how Angular Cal-HeatMap directive is implemented or not, but the way I was trying to use it, it appears it initializes before the point where I retrieve and setup the data for display. Once I retrieve the data, setting it in the $scope variable that the directive is using seems to have no effect; it doesn’t see the data and display as I’d expect.

My work around for this was to use ng-if to only initialize the directive when I toggle a flag after the data is ready. Previously I was using ng-show to toggle the display of the directive, but that apparently causes the directive to initialize even though it’s not visible. I don’t know if there’s something else I can do to re-initialize the directive, but this works for now.

Here’s what I ended up with:

<cal-heatmap ng-if="search.showDataDensity"
  config="search.heatmap.config"></cal-heatmap>

For context, here’s an example of what the heatmap looks like with some example received signal data from 2014:

heatmap_example

 

 

Lesson #2:

Cal-HeatMap uses 5 CSS styles by default for coloring according to how many data points are for each date, from .q1 through .q5. For data with a count > that whatever the top range is set to, apparently css class .q6 gets applied. Without any other change however, if you haven’t defined your own .q6, these dates will be displayed as if there’s no data on those dates. This wasn’t obvious to me, but is discussed in this post on SO. Add a custom CSS class for .q6 with a slightly darker color than .q5, problem solved.

Summary

I’ve some polishing and cleanup to do, but my heatmap display is almost ready to go!

(Page views: 5)

Re-flashing a WRT54GL running HSMM Ham Mesh firmware

I recently flashed the firmware on a spare Linksys WRT54GL to take a look at ham radio mesh networking on 2.4GHz re-using WiFi routers like the WRT54. I wanted to flash the router back to regular WiFi router firmware, and turned out this was more difficult than it should have been. For future reference, here’s a few notes.

The HSMM-Mesh firmware (3.0) has an admin page to either upload a new firmware to flash, or download an existing firmware from a list of available firmware versions. Neither of these worked for me – uploading a firmware gave an error that it wasn’t recognized, and then the router was connected to my network for internet access, it didn’t give any firmware options other than later versions of the HSMM firmware.

Elsewhere there are instructions for using the tftp approach to ftp a new firmware to the router as it boots. This seemed like an easy option, but I could not get it to work despite trying multiple times.

Instructions for OpenWrt here give steps for ensuring the tftp feature is enabled… this apparently is key, as before following the steps I could not get it to work, but after setting this options it worked first time.

ssh to the router using:

ssh root@10.72.105.9 -p 2222

this is the ip that my HSMM had on starting up, and sshd on the HSMM firmware is enabled by default and listening on 2222.

From thr OpenWrt page above, enter these commands to setup tftp:

nvram set boot_wait=on
nvram set boot_time=10
nvram set wait_time=10 #important for some models
nvram commit && reboot

Before the reboot step, set your ip address on laptop connected to router as:

192.168.1.2
netmask 255.255.255.0
router/gateway 192.168.1.1
Reboot router, start following the tftp procedure to upload the firmware:

If you are seeing WRQ messages with tftp trace turned on, the router is responding, but not yet accepting the tftp upload. You need to wait until you see messages like this to indicate the transfer is occurring:

sent DATA <block=6562, 512 bytes>
received ACK <block=6562>

These will repeat several times a second until the upload is complete, then they will stop, tftp will disconnect, and you’ll see the router power light flashing, indicating it is rebooting. Wait a couple of minutes until the lights are back to their normal state, and then try hitting the admin page for the new flashed firmware at 192.168.1.1

(Page views: 96)

Does the leadership shakeup at Microsoft mean their Phone business in finally dead?

Microsoft have struggled forever to get a foot in the mobile device market, with a trail of failed products and mis-steps over the past years. Who even remembers Project Pink (here), the Kin One and Kin Two, or the time they bought Danger and then had a server failure and lost all their user’s data?

With Microsoft announcing recently that it’s haemoaging cash on it’s mobile business, and that Stephen Elop, the ex-Nokia chief and lead of the Mobile Devices Group, is out the door in the recent exec shakeup, you have to wonder just how much focus Microsoft is going to put on it’s promise of Windows 10 to be the OS to run on all device types. Maybe all devices as long as it’s not a Nokia phone, or all devices but not phone hardware coming from Microsoft. Which at this point this probably means any phone at all – without Nokia Windows devices, what devices are left?

I doubt anyone’s upset that we won’t see Microsoft phones running Windows 10, but it is sad that at this point, Microsoft’s failed acquisition of Nokia most likely means that Nokia, as a brand and as the phone, is now dead.

(Page views: 56)

AngularJS and Google Maps – dynamic marker updates

I have a need to dynamically create and display markers on a Google Map. Statically declaring a single or an array of markers seems pretty easy, but updating an array of markers so they are displayed and removed over time seems more tricky using the available AngularJS libraries for Google Maps.

The two libraries I have looked at are:

Both offer AngularJS directives to insert a Google Maps into an existing page. Let’s take a quick look at each approach.

Angular Google Maps

With Angular Google Maps, use the provided directives to insert the map and an array of markers:

<ui-gmap-google-map center='map.center' zoom='map.zoom'>
  <ui-gmap-markers models="markers" coords="'self'" modelsbyref="false"/>
</ui-gmap-google-map>

In my Controller I’ve added a map object to $scope with values for center and zoom:

$scope.map = {center: {latitude: 37.7699298, longitude: -122.4469157}, zoom: 12};

… and to add the initial array of markers (random markers in SF):

var marker1 = {id: 1, latitude: 37.7699298, longitude: -122.40};
var marker2 = {id: 2, latitude: 37.7699298, longitude: -122.45};
var marker3 = {id: 3, latitude: 37.7699298, longitude: -122.46};
$scope.markers = [];
$scope.markers[0] = marker1;
$scope.markers[1] = marker2;
$scope.markers[2] = marker3;

Since the markers array in $scope is reference by the ui-gmap-markers element, setting the markers array to [] deletes the markers from the map, and adding them back re-adds them back to the map. The property ‘coords’ is the name of the property on the object passed to models that contains the objects with the latitude/longitude properties for each marker. modelsByRef=”false” seems to add support for watching changes to the model.

ngMap

The ngMap approach is very similar. To add the map to a page with a repeating list of markers:

<map style="height:100%" center="37.7699298, -122.4469157" zoom="11">
  <marker ng-repeat="pos in positions" position="{{pos.lat}}, {{pos.lng}}"></marker>
</map>

To create the markers, create an array of markers with lat and lng properties, similarly to Angular Google Maps:

var marker1 = {lat: 37.769, lng: -122.44};
$scope.positions = [];
$scope.positions[0] = marker1;
//etc

Summary

Since my app needs to dynamically add and remove markers for display to the Google Map, this was my primary requirement for selecting one of the libraries. I struggled to get this working initially with Angular Google Maps, but seemed to work straight out of the box with ngMap. Most of my struggles though may have been related to my misunderstanding of how $scope works in AngularJS (which I’m still learning), so maybe at some point I should go back and re-evaluate both of these again once I have a better understanding of AngularJS.

I put together a sample app that uses both of the libraries, which you can find on GitHub here: https://github.com/kevinhooke/AngularJSGoogleMapsExamples

Also, my final usage for ngMap you can see in action in my app, SpotViz, which is available here: http://www.spotviz.info/ . It allow Amateur Radio operators to playback an animated display of received station locations over time from log files from a digital mode application called WSJT-X.

 

(Page views: 87)

OpenShift 2.0 Hot Deploy option

I’m not sure why I haven’t tried this earlier, but by default, when you git push your updates to OpenShift Online, it stops all your cartridges, builds, deploys and then restarts everything, which can take a few minutes.

OpenShift 2.0 supports a hot deploy option to minimize the amount of time that your app is down – details are in the docs here.

(Page views: 84)

Hibernate OGM / JAX-RS / JAX-WS redeployment issue on WildFly8.2: java.lang.NoSuchMethodException: org.objectweb.asm.MethodWriter.visitLabel

I’ve been struggling with failing redeploys on WildFly8.2 while I’m developing my app. If the app is deployed, on first server start it starts up fine, but then if I redeploy some code changes I get this NoSuchMethodException in the asm library, suggesting I’ve got some conflict of versions of the asm library used by my app:

Caused by: java.lang.NoSuchMethodException: org.objectweb.asm.MethodWriter.visitLabel(org.objectweb.asm.Label)
 at java.lang.Class.getMethod(Class.java:1773) [rt.jar:1.8.0_20]
 at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:85)
 ... 28 more

Luckily I came across this post with the same error, putting me on the right direction about the possibility of my app being packaged with a conflicting version of asm. Looking at a ‘mvn dependency:tree’ on my app, I could see asm being pulled in from my use of Hibernate OGM and Jersey as transitive dependencies.

Despite trying to add excludes to not get asm included in the packaging of my app, I eventually gave up and decided to just remove my luckily minimal use of Hibernate OGM. I think the issue was caused my OGM’s deployment of modules onto the WildFly server, one of which was asm. After I had removed OGM from my app, removed the modules, I was back to speedy redeploys of my app.

I’m sure there’s a way to get OGM to deploy happily, or maybe I had just ran across an asm version conflict with other libraries my app is using (Jersey?), but I don’t have time right now to deal with it. Another project for another day :-)

(Page views: 109)

Windows 10 Users “34 per cent more likely to be strongly satisfied with the filtered Taskbar”

Let that statement sink in for a minute – in Windows 10 Insider Preview builds, users have indicated they are:

"34 per cent more likely to be strongly satisfied with the filtered Taskbar"

… and based on that not-so-convincing statistic it’s been decided that the taskbar for a virtual desktop will only show apps running on that desktop (presumably hiding others that are running on other desktops at the time time?).

Gabe Aul at Microsoft describes in this post the latest features in the Windows 10 preview build and how feedback from preview build users is helping Microsoft decide what new features will make it into Windows 10, and which won’t.

And there you have it. Apparently the design of the Ribbon Bar in the latest Office versions was also designed the same way, based on observed/recorded usage patterns of ‘actual users’. If you think the Ribbon Bar is actually a good design then I won’t waste my time arguing with you, but most would probably agree from a usability point of view it’s a horribly cluttered, confused mess of somewhat related options. The Ribbon Bar reminds me of a set of cluttered drawers that are where you stuff your junk that you don’t have anywhere better to put. Each drawer has vaguely related things in it, but good luck trying to find something specific – you open a drawer and spend 10 minutes digging around in there trying to find what you’re looking for. Similarly for the Ribbon Bar – good luck finding that one specific feature.

So at some point if your’re lucky enough (?) to have Windows 10, you might wonder exactly how Microsoft arrived at a decision for why a certain feature is a certain way. And you can be assured that it was designed that way because 34% of preview build users (by a long way as far from a typical user as you can get) decided they were ‘most likely to be strongly satisfied’ if it was that way.

(Page views: 95)

Local javac path issues on older OpenShift WildFly8.2 based project

I have an app that I created a few months back on OpenShit based on the WildFly 8.2 cartridge. Locally in Eclipse the project builds and compiles fine, but executing mvn directly or in Netbeans (which also builds using your mvn pom.xml), it fails with an error regarding a path to javac:

-------------------------------------------------------------
COMPILATION ERROR : 
-------------------------------------------------------------
Failure executing javac, but could not parse the error:
/bin/sh: ${env.OPENSHIFT_WILDFLY_DIR}usr/lib/jvm/jdk1.8.0_05/bin/javac: bad substitution
1 error

This is obviously setup for building specifically in the OpenShift environment with this property defining the path to javac:

<maven.compiler.executable>${env.OPENSHIFT_WILDFLY_DIR}usr/lib/jvm/jdk1.8.0_05/bin/javac</maven.compiler.executable>

There’s a few posts and discussions about this (e.g. here and I suspect this is related), but I’m guessing the version of the pom.xml I have is older and been changed recently. I created a new OpenShift WildFly based project to compare the created pom.xml, and these two properties are no longer in the pom.xml file:

<maven.compiler.executable>${env.OPENSHIFT_WILDFLY_DIR}usr/lib/jvm/jdk1.8.0_05/bin/javac</maven.compiler.executable>
<maven.compiler.fork>true</maven.compiler.fork>

Removing them fixes my local builds, and pushing the code to OpenShift still seems to build ok too.

(Page views: 112)

Mounting Linux ext partitions on OS X

I wanted to check some files on an SD Card formatted in ext that I had used on my Pi and wanted to check if I had left some files in the home dir before I reimaged it. OS X doesn’t support ext formatted drives by default, but you add support using OSXFuse.

  • Install Fuse for OS X
  • Install the ext plugin for Fuse
  • Find the partition you want to mount with: diskutil list
  • Make a mount point – not sure on Mac OS X where is the best place, but I added /mnt/sdcard
  • Mount with:

    sudo fuse-ext2 /dev/disk1s2 /mnt/sdcard

  • (replace with the /dev/ to your device)

I’m not sure if it’s best practice on the Mac to mount with sudo, but this worked for me for what I needed to do. Fuse mounts on ext are r/o by default, but there is experimental r/w support that can be enabled, check the docs.

Done!

(Page views: 118)