Sometime ago I have been stumbled upon a demonstration of Firefox OS. There was said that most applications in Firefox OS are build from HTML5 and Javascript even the more hardware related ones like a battery indicator. Furthermore they pointed out that some of the Firefox OS API become available in Mozilla Firefox browser too. The Battery API is one of those – already available – APIs and it is becoming standardized by the W3C too. This was an inspiration to play around with the that API and build a simple web based battery status indicator relying on HTML5 Canvas, Javascript and the Battery API. You can view the result here.
The Battery API is quite simple and gives you read only access to some status properties as well as the opportunity to register some callback functions to react on certain events.
An instance could be easily obtained from the navigator object. For compatibility reasons the following code includes fall back variants for Webkit and older Mozilla implementations:
// initialize battery var battery = window.navigator.battery || window.navigator.mozBattery || window.navigator.webkitBattery;
35f83340853bf1c7e369c9d27e912832892861d8Having an instance of the battery we can set up the callbacks to update our indicator on certain events, whereas the following callbacks could be registered to perform certain actions on event occurrence. Here it will simply update the graphics and textual information on any change.
/* * Callback if the battery level changes * @param event */ battery.onlevelchange = _eventHandler; /* * Callback if the charging time changes * @param event */ battery.onchargingtimechange = _eventHandler; /* * Callback if the discharging time changes * @param event */ battery.ondischargingtimechange = _eventHandler; /* * Callback if the charging state changes * @param event */ battery.onchargingchange = _eventHandler; /** * Gereric event handler for delegating battery events to the update function * @param event */ function _eventHandler(event) { console.log('catched event [' + event.type + ']'); _update(event.currentTarget); }
For the initial setup it accesses the read only status properties of the battery object and passes them to the drawing method:
/** * Shows the battery widget based initialized with the current battery information. * @private */ function _show() { _update({ level: battery.level, // current battery level represented by a double 0.0 to 1.0 chargingTime: battery.chargingTime, // remaining time in seconds until completely charged dischargingTime: battery.dischargingTime, // remaining time in seconds until the battery is fully discharged charging: battery.charging // boolean flag if the battery is currently charged }); }
The drawing method is quit simple, for the sake of simplicity it takes an argument of the same structure like the battery object to process the current values. This enables the _update method to work with the same structure as obtained from the change events. The _update method clears the whole canvas before redrawing the graphics based on the new information.
/** * Clear and redraw graphics * @param data * @private */ function _update(data) { _clear(); // determine indicator color if (data.level < config.threshold.critical) { ctx.fillStyle = config.indicator.critical; } else if (data.level < config.threshold.warning) { ctx.fillStyle = config.indicator.warning; } else { ctx.fillStyle = config.indicator.normal; } //draw indicator ctx.fillRect(10, 10, data.level * 250, 50); // draw battery frame ctx.strokeStyle = 'black'; ctx.lineWidth = 3; ctx.strokeRect(10, 10, 250, 50); // print battery level ctx.font = '12pt Sans'; ctx.fillStyle = 'black'; ctx.fillText(Number(data.level * 100).toFixed(1) + '%', 100, 45, 150); ctx.font = '10pt Sans'; // charging time will be given in seconds console.log('Charging time [' + data.chargingTime + ']'); var ctxt = 'Battery is charging.'; if (data.chargingTime !== Infinity) { var conv = DateUtil.convertHM(data.chargingTime); ctxt = 'Time until fully loaded: ' + conv.hours + ':' + conv.minutes + ' .'; } ctx.fillText(ctxt, 10, 80, 240); // discharing time will be given in seconds console.log('Discharging time [' + data.dischargingTime + ']'); var dtxt = 'Connected to AC.'; if (data.dischargingTime !== Infinity) { var conv = DateUtil.convertHM(data.dischargingTime); dtxt = 'Time remaining: ' + conv.hours + ':' + conv.minutes + ' .'; } ctx.fillText(dtxt, 10, 100, 240); console.log('update finished'); }[/sourcecode]<div class="wp-git-embed" style="margin-bottom:10px; border:1px solid #CCC; text-align:right; width:99%; margin-top:-13px; font-size:11px; font-style:italic;"><span style="display:inline-block; padding:4px;">battery.html</span><a style="display:inline-block; padding:4px 6px;" href="https://bitbucket.org/0x0me/blog-battery-canvas/raw/35f83340853bf1c7e369c9d27e912832892861d8/battery.html?at=master" target="_blank">view raw</a><a style="display:inline-block; padding:4px 6px; float:left;" href="https://bitbucket.org/0x0me/blog-battery-canvas/src/35f83340853bf1c7e369c9d27e912832892861d8/battery.html?at=master" target="_blank">view file on <strong>Bitbucket</strong></a></div> The <em>_clear</em> method is a modified version of the stackoverflow question <a title="stackoverflow: How to clear the canvas for redrawing" href="http://stackoverflow.com/questions/2142535/how-to-clear-the-canvas-for-redrawing" target="_blank">"How to clear the canvas for redrawing"</a>: /** * clear canvas * @private */ function _clear() { ctx.save(); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.fillStyle = config.backgroundColor; ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.restore(); console.log('cleared'); }
According to the Mozilla Developer Network the Battery Status API is support in
Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|---|---|---|
not supported | 10.0 using mozBattery 16.0 |
not supported | not supported | not supported | unknown | not supported | 10.0 using mozBattery 16.0 |
not supported | not supported | not supported |
The complete source code is available from BitBucket.