Kategorien
HTML5 Javascript Programming Languages

Building a simple battery status indicator with the W3C Battery API and HTML5 Canvas

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.

Class diagramm W3C Battery Status API

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 &#91;' + data.chargingTime + '&#93;');
        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 &#91;' + data.dischargingTime + '&#93;');
        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');
    }&#91;/sourcecode&#93;<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.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

vier + siebzehn =