Indoor temperature gauge, Part 1: The Interface


Yesterday, while browsing the Smashing Magazine website, I came upon a pretty interesting article called “Hardware Hacking With JavaScript” which discusses the topic how to get started building your own IoT device infrastructure using JavaScript.

I gained inspiration from the article and decided to (simplify their solution, try and) use JavaScript for communication with an Arduino microcontroller unit playing as a server in my local network, providing the current indoor temperature (via an additional temperature sensor) to create a simple temperature gauge. This task, actually, includes two major steps – creating the interface which communicates with the Arduino, on the one hand, and creating the server-side code running on the Arduino, on the other hand. So, in this article we will build the interface in terms of design and functionality, while the Arduino-server code and the server communication logic for the interface will be explained in an upcoming article.

Okay, let’s start. What do we need to do?

Since the interface is actually required to fulfill a single task – “ping” the Arduino server at a certain period of time and display the returned temperature value – we can afford spending some more milliseconds for loading JavaScript libraries. What I mean is in such a use-case the initial load time is not crucial. So, with that said, we can make use of jQuery and, more specifically, its mechanisms for DOM manipulation and AJAX request performance (the latter being out of the scope of the current article).

Then, the backbone of our interface is going to be a single HTML file where, inside the <head>, we will place a <script> tag to inject jQuery:
<script src="https://code.jquery.com/jquery-2.2.4.min.js" type="text/javascript"></script>

Fine! jQuery is now present on our client side, but what else do we want? The guys at Smashing Magazine have come up with a pretty cool idea of reflecting the current temperature on the main color of the interface and we naturally want to implement this feature as well. It is cool that the background will become red if the temperature goes above, let’s say, 28 degree Centigrade and then go ice blue if the temperature goes beyond zero, isn’t it? For this adaptation ability and to make the design look beautiful, besides jQuery we also need the Lato Google font. So, the next thing we do inside the <head> of our markup is refer the Lato font like so:
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">

Perfect, our external dependencies are resolved! Now we get to the markup itself. Well, it’s pretty simple and straightforward: we need a tag to hold the text “Temperature: 28° C” (the exact degree will be dynamically updated each time the server is invoked), where the degree value needs to be placed in a nested tag denoted specially for it. Then, inside the <body> tag, we need to place the following:
<h1 class="temperature"><span id="temperature-value">29</span>&deg;C</h1>

As you see, we have given the <h1> holder the class temperature, while the temperature value holder element has the ID temperature-value. We are going to use these class and ID to invoke the UI elements further in our JavaScript logic.
Later on, an interface has to be beautiful, right? Considering pretty, we have the so-far-mentioned color-adaptive background (and the JavaScript code which we will cover below is going to fulfill that), as well as a modern UI font is also available for our aims. We need to add some styles, though. First, we will style the <body>, giving it a default background color (in the hue/saturation/lightness format), a transition animation property so that, when new temperature value arrives from the back-end, the color is changed slightly and, on top of everything else, we will disable user select (the user won’t be able to highlight any text on the whole page, thus making the interface behave like a real gauge).

body {
    /* initial background color and transition property */
    background-color: hsl(0, 60%, 65%);
    transition: background-color 1s;

    /* disable user select for all browsers */
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

Then, we have to style our <h1> tag – the one and only data container throughout the interface. Considering its styles, there is nothing special and the styles are mainly for positioning and sizing. One of the interesting properties in particular is font-family: ‘Lato’, sans-serif; which denotes that we use our pretty font (and if it is not found, sans-serif will be used instead). The other interesting properties are content: attr(class) “:”; and text-transform:uppercase; (which are applied to the CSS pseudo-element appended before the <h1>). These properties make the mentioned pseudo element get the class of the <h1> tag (temperature), append a column to it (:) and make the whole text be represented by uppercase characters.

h1.temperature {
    margin: 60px;
    color: white;
    text-align: center;
    font-family: 'Lato', sans-serif;
    font-size: 120px;
    font-weight: 100;
}

h1.temperature:before{
    content: attr(class) ":";
    position: relative;
    top: -63px;
    left: 0;
    font-size: 24px;
    text-transform: uppercase;
}

The adaptive background logic

The background adaptation logic itself is implemented in a <script> tag put at the bottom of the <head> and consists of around 20 lines of code (half of them used for comments and JavaDoc), so we will cover every one of them.
First of all, the whole logic is placed inside a jQuery wrapper function, which means we can be assured that the JavaScript logic will fire after all DOM elements are loaded.

jQuery(function($) {
    //Our logic goes here
});
Cold temperature interface

The interface reacting to low temperature.

Hot temperature interface

The interface reacting to high temperature.

Further ahead, we have got a function called adaptBackgroundToTemperature() which, when invoked, first gets the temperature value from the #temperature-value tag (which will be constantly updated in the future), then applies the temperature value in a hue calculation formula and finally sets the resulting hue value in a hue-saturation-lightness CSS property for the background.

function adaptBackgroundToTemperature() {
    var temperature = $('#temperature-value').html();
    var hueValue = 200 - (parseInt(Math.floor(temperature)) * 5);
    $('body').css('background-color', 'hsl(' + hueValue + ', 60%, 65%)');
}
Medium temperature interface

The interface reacting to medium temperature. Browser developer console can be used to change the temperature value and see the background adapt, thanks to the DOMSubtreeModified browser event.

What we also have inside our jQuery wrapper function are events which call the adaptBackgroundToTemperature() function. In our case we have bound two events – general change of the inner HTML for the #temperature-value element and DOM modification change event for the same element (so that for testing purposes we can hit the F12 key and use the browser developer console to modify the value of the HTML element and see the background change). Here is how the whole snippet for background adaptation looks like:

<script type="text/javascript">
    //Begin when DOM is loaded
    jQuery(function($) {
        //OPTIONAL manual DOM change event (via the browser developer tools)
        $('#temperature-value').bind('DOMSubtreeModified',function(){
            adaptBackgroundToTemperature();
        });

        //General event
        $('#temperature-value').on('change',function(){
            adaptBackgroundToTemperature();
        });

        /**
        * Adapts the background color depending on the
        * temperature value using a simple formula
        * based on hue/saturation/lightness values
        * (cretids to https://www.smashingmagazine.com)
        */
        function adaptBackgroundToTemperature() {
            var temperature = $('#temperature-value').html();
            var hueValue = 200 - (parseInt(Math.floor(temperature)) * 5);
            $('body').css('background-color', 'hsl(' + hueValue + ', 60%, 65%)');
        }
    });
</script>

And below you can check out the whole interface code (a single HTML file):

<html>
    <head>
        <link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
        <style>
            body {
                /* initial background color and transition property */
                background-color: hsl(0, 60%, 65%);
                transition: background-color 1s;

                /* disable user select for all browsers */
                -webkit-touch-callout: none;
                -webkit-user-select: none;
                -khtml-user-select: none;
                -moz-user-select: none;
                -ms-user-select: none;
                user-select: none;
            }

            h1.temperature {
                margin: 60px;
                color: white;
                text-align: center;
                font-family: 'Lato', sans-serif;
                font-size: 120px;
                font-weight: 100;
            }

            h1.temperature:before{
                content: attr(class) ":";
                position: relative;
                top: -63px;
                left: 0;
                font-size: 24px;
                text-transform: uppercase;
            }
        </style>
        <script src="https://code.jquery.com/jquery-2.2.4.min.js" type="text/javascript"></script>
        <script type="text/javascript">
            //Begin when DOM is loaded
            jQuery(function($) {
                //Manual DOM change event (via the browser developer tools)
                $('#temperature-value').bind('DOMSubtreeModified',function(){
                    adaptBackgroundToTemperature();
                });

                //General event
                $('#temperature-value').on('change',function(){
                    adaptBackgroundToTemperature();
                });

                /**
                * Adapts the background color depending on the
                * temperature value using a simple formula
                * based on hue/saturation/lightness values
                * (cretids to https://www.smashingmagazine.com)
                */
                function adaptBackgroundToTemperature() {
                    var temperature = $('#temperature-value').html();
                    var hueValue = 200 - (parseInt(Math.floor(temperature)) * 5);
                    $('body').css('background-color', 'hsl(' + hueValue + ', 60%, 65%)');
                }
            });
        </script>
    </head>
    <body>
        <h1 class="temperature"><span id="temperature-value">29</span>&deg;C</h1>
    </body>
</html>

That’s it for now, you can try out the demo here by changing the #temperature-value tag’s inner HTML using the browser developer tools (push F12). The second article is coming soon, folks, so be patient.

Best,

Alex


Leave a comment

Your email address will not be published. Required fields are marked *