Friday, January 6, 2017

GEVCU Dashboard redesign

The old version of the web based GEVCU dashboard is a bit overloaded with gauges and its look&feel is not of the most modern types. So after seeing some nice gauges in a mobile app presented on evtv, I decided ours needs an overhaul. These were the requirements:

  • support dual dials on one gauge (or more)
  • support arcs from a start point to the tip of the dial
  • improved performance
The original gauge library was created by Mykhailo Stadnyk and it served us well. But we had to switch off animations (interpolations from one value to the next) in order to run it on tablets. This made the dials jump around a bit. One of the main reasons for this was that for every refresh the entire gauge was re-drawn from scratch. So a first change was to introduce layers. The gauge background (circle, numbers, ticks) are now only drawn once and the dials are each drawn on their own layer (canvas stacked above each other). Also the LCD like value displays are drawn onto a separate layer.
But still performance was pretty bad.. on a Macbook Pro, Firefox put the CPU load to 80-90% in a test set-up where all values were redrawn every 10ms. Increasing the interval to 35ms still gives decent animations and dropped to CPU load to about 60%. Better but still not good enough for my Samsung Note 10.1" 2014 tablet. The problem was that JavaScript runs single-threaded. So although the tablet uses a multi-core processor, it only used one to do everything. The solution was to introduce web-workers. They allow to perform background tasks in separate threads. By moving the web-socket communication and calculations to a separate worker and let the main thread do the drawing, we got a huge performance jump. The CPU load dropped to about 45% and the animations started to look better on the tablet. But I wasn't happy yet. Since the specs of web-workers say that a worker can spawn sub-workers, I wanted to go further and not just distribute the work between 2 threads (2 cores). So I decided to spawn a "handler" worker which acts as a coordinator. This handler then spawns a web-socket worker which processes the incoming data into a JSON object. And it also spawns a worker for each dial to be displayed in all the gauges. Each key/value pair received from the web-socket is then forwarded via the handler to the corresponding dial-worker. The result of the dial-worker is forwarded through the handler back to the main thread where the canvas is drawn with the pre-calculated values. This approach would take away the maximum amount of load from the main thread which is responsible for the DOM and drawing the canvas.
But it didn't work out that well. Well, it worked - but only in Firefox. As it turns out, Firefox and MS Edge are the only browsers at that time to implement the full specification of workers. The others (like Opera, Chrome, Android Browser) do only support workers to be created by the main thread. So  in order not to loose the work, I decided to put the handler into a PseudoWorker wrapper. It will still run in the main thread but can be accessed almost like a worker. So in case the other browser implementations catch-up, it's easy to switch.
The arcs was another thing.. to find out how to place the start points correctly was not so easy. Especially as I wanted to be able to have the gauges display one, two, three or more dials. And also be able to "turn around" a dial and not display the values clock-wise but counter-clock-wise with a switch. And of course the arcs also needed to support freely definable gradients. 
All in all, it worked out and now the performance on the tables is good. The dashboard even runs sufficiently well on a raspberry Pi3 with all values changing with every update (which is not realistic). But you'll have to use Android as OS and either Chrome or Opera. Firefox is too slow as are all browsers available on Raspbian. 
Here's a demo video (with faked values) of the new dashboard in action. You might notice the instpirations from Tesla and Volvo gauges but still, they're something different. Oh yes and the charging screen also received an overhaul. So although future versions of GEVU (6.x) will no longer support the ConnectOne ichip wifi, there are still a lot of us out there who got older versions.
Also notice the switches at the top. With them you can temporarely switch on/off regen, creep, EHPS and the heater. Especially on snowy roads it's nice to switch off regen without having to change the configuration of the throttle.


And here's a demo which displays all the possibilities of the new gauges (4 dials in one gauge and also display the highlights as in the old version):