Showing posts with label html5. Show all posts
Showing posts with label html5. Show all posts

Tuesday, December 1, 2015

Events events events...

Hi there,

As some of you might know I love the Internet of Things and so I have a couple of sensors around that measures different kind of data. I'm also a big fan of MQTT because it makes things so easy and with it's publish and subscribe model it seems to be a natural fit for a lot of IoT projects.

When playing with my own stuff on my server and on my home network I'm totally fine with using MQTT for all of my IoT related communications. 

BUT...if you ever spoke at conference venues like hotels you will find out that they are very strict with their network...means usually the ports you need for your MQTT communication are not open :(
Or if you work in a company with very strict rules you might have the same problem with the port availability.
For this years JavaOne I was playing around with an Application Container Cloud Service where I again had the same problem...only port 80/443 have been available for all communications.

So I remembered a conversation that I had with David Delabassee at JavaOne Brazil this year in June. He mentioned SSE (Server Sent Events) and that it might be a possible solution for these kind of problems. 

Hey hipsters...sure you can use WebSockets...BUT you might run into problems with Proxy Servers. And using WebSockets is not always needed. In my case I would like to visualize data that is coming from either a sensor or an IoT gateway. Usually I don't need to send data to these devices and even if I have to send data it will be rare.
So for such a use case SSE is a perfect fit because it is a unidirectional event stream from the server to the client.

My idea was to write some code that subscribes to MQTT topics on a given broker and forwards them to connected clients via SSE. Sounds easy...and it is easy :)

To be able to subscribe to specific topics I needed a simple REST endpoint in my code that accepts POST calls from the client. The POST endpoint takes the topic and the qos (Quality of Service) for the subscription as parameters.
The program will add the client with the subscribed topic to a map and everytime a new MQTT message arrives on the broker the message will be pushed to all subscribed SSE clients.

The following image hopefully explains what I had on my mind...

Image


As you can see on the image above you need at least a MQTT broker and a server that runs either Java SE or node.js or both :)

So I've implemented my little MQTT to SSE application in node and Java SE. Yes you read it right...Java SE...no Java EE :)
Don't get me wrong, Java EE is fine for a lot of things but if you just need something like I do here, it's just overkill and things like Spring Boot do better.

On Java EE it's also not that easy to make use of MQTT but on Java SE it's very easy if you use libraries like Eclipse Paho, FuseSource etc.

If you are not afraid of using JavaScript node.js is also a really good fit for stuff like this (even if I'm not the best JavaScript programmer I was able to write this app).

For those of you that can't wait...here are the links to the repositories.

MQTT to REST/SSE bridge and Java SE SSE client:


So in principle the whole app has only two methods one to publish a message via REST POST and one to subscribe to a topic via SSE.

In addition I've also created a HTML page and a Java SE client that both publish and subscribe messages to the MQTT broker using REST POST and SSE.


Set it up...

1. Setup a MQTT broker
If you don't have a broker yourself you might want to setup a free version over at www.cloudmqtt.com
After you signed up for the free Cute Cat plan you will find the settings of your MQTT broker in the Control Panel under details. There should be something like this...


Image

Just note the Server, User, Password and Port



2. Configure and Start the REST service

The node.js version:
If you use the node.js app you will find a file named config.js in the project. In this config.js file please add the url, user, password and port of your MQTT broker or the broker you host at cloudmqtt. This should look similar to the following picture...


Image

In principle you are now ready to start and if you've put the right credentials for your broker in the config.js file you should now be able to start the mqtt2sse.js file by calling

node mqtt2sse.js

on the command line or you start it from your preferred IDE.

The Java SE version:
If you use the Java SE based version you should find a config.properties file in the project directory. 
Just put the data like url, port, user and password of your MQTT broker or the broker you host at cloudmqtt in this file. It should look similar to the following one...

Image

Now you are ready to start the file eu.hansolo.mqtt2sse.Main either in your preferred IDE or you can also build the project and start the created fat jar from the command line as follows...

java -Dserver.port=8080 -jar mqtt2sse-1.0.jar

The application will make use of Spring Boot for the REST service and will simply output incoming messages on the command line.



3. Publish and Subscribe some messages via HTML/JavaScript
In both projects you will find a test.html file which simply displays incoming messages and will publish messages with random data every 5 seconds.

It will subscribe to the MQTT topic: 

sensor/+

which means it will receive every of the following messages...

sensor/NNN

The + is a MQTT wildcard and you can find more information about MQTT and topics over at the awesome guys from dc-square (creators of hivemq), here is a the link.

The HTML/JavaScript client will also publish messages every 5 seconds to the MQTT topic:

sensor/HtmlClient

The data it will publish looks like this...

{
  'temperature' : 23.24234,
  'pressure' : 1002.12312,
  'humidity' : 65.23414
}

So if you start it you should see something like the following in your browser...


Image



4. Publish and Subscribe some messages via Java
This Java app makes use of the jersey libraries to subscribe to SSE and HttpURLConnection to make the REST POST calls. The functionality is the same as with the HTML/JavaScript client, means it subscribes the MQTT topic

sensor/+

and publishes data to the MQTT topic

sensor/JavaClient

So every 5 seconds it will publish a messgae to the MQTT topic above. If you start the app you should see something similar on the console...


Image

As you can see it's in principle the same as with the HTML/JavaScript client.


5. Manually publish messages via REST POST
Finally you could also use a REST client like the Chrome App Postman (get it here) to manually publish a MQTT message via REST. 
On the following screenshot you can see how it looks like...


Image

So you have to add one header as follows...


Image

Select POST as the method to use and the following url: 

http://localhost:8080/publish

Now go to the Body tab and select raw. To publish something on the MQTT topic

sensor/Postman

put the following in the textarea...

{
  "topic"   : "sensor/Postman",
  "msg"     : "{\"temperature\":23.0,\"pressure\":1005.2,\"humidity\":60.0}",
  "qos"     : 0,
  "retained": false

}

If you now press the Send button you should see the new message in the HTML/JavaScript and the Java Client like on the following pictures...


Image

You could also use all clients at the same time and should see something like this...


Image

Because each client is subscribed to the MQTT topic sensor/+ it will show messages that arrive from itself and each other client.


6. Publish/Subscribe the messages in a MQTT client
Of course one could also use MQTT directly to publish/subscribe. Therefor I can recommend using MQTT.FX from Jens Deters. This tools is written in JavaFX and so it will run on all platforms. 

So if you publish messages from MQTT.FX it could look like this...


Image

And if the Java SE client is running the messages will appear like you can see here...


Image

And because the Java SE client is sending messages every 5 seconds you will also see the messages in MQTT.FX if you subscribe to the MQTT topic sensor/+


Image


So as you can see with this MQTT <-> SSE bridge kind of code you could use MQTT via REST and SSE. This might not be the ultimate solution but for my use case it's a perfect fit and if you like it...feel free to fork it...

Here are the links to the repositories:

MQTT to REST/SSE bridge and Java SE SSE client:



That's it for today...keep coding... 

Thursday, July 28, 2011

HTML5...the web strikes back...

Last week i was in Berlin at GameDuell, where i gave a little talk about HTML5 and some of it's features. Because HTML5 has so many nice features i had to focus on some of them. I have added links to the presentation and the demo at the end of this post. Because i do not have much time this post will be about a combination of three HTML5 features...
  • Offline
  • WebSocket
  • Canvas
I created a little website that only contains one of the steelseries gauges and a textfield...so nothing special...but the trick here is that i add a HTML5 manifest file to the page so that it will be stored locally on the machine once you opened it. This means the page will also be available if there's no internet access.
That's really amazing because you could define which parts of your page should be available offline/cached (incl. scripts and css of course).
The manifest file of my demo page was really simple and looked like this...


    CACHE MANIFEST
    # rev 5
    /demo/canvas.html
    /demo/js/steelseries-min.js
    /demo/js/tween-min.js

Important to know is that the manifest file has to start with the words "CACHE MANIFEST" and if you would like to refresh the cache you have to modify the manifest file. Because it's versioned by it's bytes you could also add a simple comment (like i did "# rev 5") and change the comment which leads to a refresh of the cached parts of your page.


Ok, that's easy but why did i create this page...?


To explain this i need to explain the whole idea of the demo first. So i would like to be able to demonstrate a websocket connection and i would like to use the gauges of my steelseries library. So the library was meant to be used to visualize sensor data...so i only need a sensor right...? 
Why not use the sensors of my htc desire smartphone and use the gauge to visualize it...? 
To make this possible i need to put the computer with the browser (where the gauge is running) in the same network as the Android cellphone which is possible using an adhoc network. 


So these are the steps i need for the setup of the demo:
  1. Create a AdHoc network on my Macbook Pro
  2. Connect the HTC Desire to the AdHoc network
  3. Start a node.js server on the Macbook Pro that listens on the UDP port where the data will come in and forward the data via websocket
  4. Start a Kaazing Gateway that makes it possible to forward the websocket to specified addresses
After this setup is running i could start the software on the HTC Desire that sends the sensor data of the orientation sensor via udp to the IP address of the Macbook Pro and because they are in the same network, the node.js instance will receive the udp packages and forward them to a websocket that will be made available to localhost and another ip address by the Kaazing Gateway.
Now the real fun part of the demo was that i could add more computers to the AdHoc network of the Macbook Pro and visualize the sensor data of the cellphone on them too.
If you could follow so far you might now know why i had to cache the website with the gauge...yes...because in the moment i connect the other computers to the AdHoc network of the Macbook Pro they won't be able to load the page from the internet anymore...but from their cache they could... :-)
I created a little video to give you an idea of the functionality...





It's not the very best video but i was not sure how to give you an impression about the setup. So on the video you will see the following devices...
All devices running the same canvas.html website that was cached on the devices before i connected them to the AdHoc network of the Macbook Pro.


If you ask yourself how you could connect node.js to udp and forward the websocket via Kaazing Gateway i would strongly recommend to take a look at the blog of Matthias Wessendorfs blog (twitter: @mwessendorf), where he described how get this up and running.


The presentation was splitted into two parts, a pdf and a html5 page. Please find the links to the documents here...


    PDF presentation


    HTML5 presentation


Please keep that the WebSocket part of the html5 presentation won't work without the setup i described above. For the DeviceOrienation part i recommend a Macbook (Pro) in combination with Chrome to see something in motion.
In addition i have to mention that the webworker part will work best in Firefox5, in Chrome it seems to have problems (don't ask me why).


That's it so far for today...

Thursday, June 30, 2011

HTML5 Canvas update...

This is just a really short post to let you know about the modifications i made to the javascript version of the steelseries library.
Thanx to Mark Crossley who pushed me to add more features from the java version of the lib the current version of the javascript lib contains the following gauges.


Radials and RadialBargraphs...


Image




Linears and LinearBargraphs...


Image




DisplaySingle and DisplayMulti...


Image


The Level component...


Image


The compass component...


Image


The horizon component...


Image


And last but not least the LED component...


Image


The following features from the java version are available for the gauges too:

  • FrameDesign
  • BackgroundColor
  • PointerColor / ValueColor
  • PointerType
  • ForegroundType
  • KnobStyle
  • KnobType
  • Areas
  • Sections
  • LedColor
  • LcdColor
  • DigitalFont
And there's more to come...just stay tuned... :-)

You could find the latest version version of the lib always on the upper right part of the sidebar in this blog. At the same position you will find a link to the demo page that i'll update from time to time. Here's a current screenshot, click on the link below the image to start the demo.

Image
Click to see it in action...
Due to some improvements this demo will also work on a mobile like a HTC Desire or iPhone (even if it is a bit slow)...

So keep coding...

Tuesday, April 19, 2011

BiLinearGradient in HTML5 canvas...

This is just a short one for all HTML5 canvas lovers...
Because it was not a big deal and might be usefull for one or the other i created also a javascript version of the bilinear gradient paint that one could use in HTML5 canvas. To make it possible i added one class that represents a color in the way that one could get the rgba values from a given color and a class that represents the bilinear gradient paint itself.
The result looks like this...


Image
click here to see it live...
To see it live you just have to click the link below the image. Here is a small example on how to use the BiLinearGradient in JavaScript:


function init()
{


 

}

You have to place the above script in your html page <head> tag. If you don't know how to do that just take a look at the page sourcecode of the linked page below the image.


Here are the two files you need to create the bilinear color interpolation.


    RGBAColor.js


    BiLinearGradient.js


Enjoy coding...



Friday, April 1, 2011

SteelSeries JavaScript edition

Here we go again and it's again time for some canvas...
Those of you who followed this blog know that i started to port some of the components of the steelseries java library to html5 canvas. Because i'm not a javascript coder i had no idea how to build a library from these components and so i started playing around, trying this and that...
Finally i found a way that looks ok to me (but i might be wrong) and today i could present you the first version of the javascript version of the steelseries library (it only contains the Radial and RadialBargraph right now).

I tried to implement most of the features of the java version but right now there are still some feature missing.
Here is a list of the features that are supported by the javascript version:

GaugeType:

  • TYPE1
  • TYPE2
  • TYPE3
  • TYPE4


PointerType:

  • TYPE1
  • TYPE2
  • TYPE3
  • TYPE4
  • TYPE5
  • TYPE6
  • TYPE7
  • TYPE8

FrameDesign:

  • BLACK_METAL
  • METAL
  • SHINY_METAL
  • BRASS
  • STEEL
  • CHROME
  • GOLD


BackgroundColor:

  • DARK_GRAY
  • SATIN_GRAY
  • LIGHT_GRAY        
  • WHITE
  • BLACK
  • BEIGE
  • BROWN
  • RED
  • GREEN
  • BLUE


LcdColor:
  • BEIGE
  • BLUE
  • ORANGE
  • RED
  • YELLOW
  • WHITE
  • GRAY
  • BLACK
  • GREEN
  • BLUE2
  • BLUE_BLACK
  • BLUE_DARKBLUE
  • BLUE_GRAY
  • STANDARD
  • BLUE_BLUE
  • REDDARKRED


LedColor:
  • RED_LED
  • GREEN_LED
  • BLUE_LED
  • ORANGE_LED
  • YELLOW_LED
  • CYAN_LED
  • MAGENTA_LED


Color:
  • RED
  • GREEN
  • BLUE
  • ORANGE
  • YELLOW
  • CYAN        
  • MAGENTA
  • WHITE
  • GRAY
  • BLACK
  • RAITH
  • GREEN_LCD
  • JUG_GREEN


The Radial component also supports sections and areas. So there's no track right now (but it will come).

PREPARATION:
To make use of the library you have to add two files to your html page:

  • tween.js
  • steelseries.js

So a typical html5 page header will look like this...

e.g.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Test</title>
    <script type='text/javascript' src='js/tween.js'></script>
    <script type='text/javascript' src='js/steelseries.js'></script>
...

USAGE:
To use the library you need to add a <canvas> tag for each gauge to the <body> of the page.

e.g.
...
<body onload='init()'>
    <canvas id='canvas1' width='200' height='200'>
        No canvas in your browser...sorry...
    </canvas>
    <canvas id='canvas2' width='200' height='200'></canvas>
<canvas id='canvas3' width='200' height='200'></canvas>
</body>
...
Now we only have to add the init() method in the <head> of the page, where we create the canvas components. !!! OLD VERSION !!!
function init()
{
  // Define some sections
  var sections = Array(steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),
                       steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'), 
                       steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)'));
  
  // Define one area
  var areas = Array(steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)'));
            
  // Create one radial gauge
  var radial1 = new steelseries.Radial(
                    'canvas1',                              // the canvas element
                    steelseries.GaugeType.TYPE4,            // type of gauge
                    200,                                    // size of gauge
                    0,                                      // minimum value
                    100,                                    // maximum value
                    50,                                     // threshold
                    sections,                               // sections
                    areas,                                  // areas
                    'Test',                                 // title string
                    'Unit',                                 // unit string
                    steelseries.FrameDesign.METAL,          // frame design
                    steelseries.BackgroundColor.DARK_GRAY,  // background color
                    steelseries.PointerType.TYPE8,          // pointer type
                    steelseries.ColorDef.RED,               // pointer color
                    steelseries.LcdColor.STANDARD,          // lcd color
                    true,                                   // lcd visible
                    steelseries.LedColor.RED_LED,           // led color
                    true,                                   // led visible
                    false);                                 // play audio
  
  // Create a second radial gauge
  var radial2 = new steelseries.Radial(
                    'canvas2', 
                    steelseries.GaugeType.TYPE2, 
                    200, 
                    0, 
                    50, 
                    40, 
                    Array(steelseries.Section(0, 40, 'rgba(0, 255, 0, 0.3)')),
                    Array(steelseries.Section(40, 50, 'rgba(255, 0, 0, 0.5)')), 
                    'Test', 
                    'Unit', 
                    steelseries.FrameDesign.CHROME, 
                    steelseries.BackgroundColor.LIGHT_GRAY, 
                    steelseries.PointerType.TYPE2, 
                    steelseries.ColorDef.BLUE, 
                    steelseries.LcdColor.BLUE2, 
                    true, 
                    steelseries.LedColor.BLUE_LED, 
                    true, 
                    false);

  // Create a radial bargraph gauge
  var radial3 = new steelseries.RadialBargraph(
                    'canvas3',                               // the canvas element
                    steelseries.GaugeType.TYPE3,             // type of gauge
                    200,                                     // size of gauge
                    0,                                       // minimum value
                    100,                                     // maximum value
                    50,                                      // threshold
                    null,                                    // sections (not supported)
                    "Title",                                 // title string
                    "Unit",                                  // unit string
                    steelseries.FrameDesign.BLACK_METAL,     // frame design
                    steelseries.BackgroundColor.LIGHT_GRAY,  // background color 
                    steelseries.ColorDef.YELLOW,             // color of the bargraph led's
                    steelseries.LcdColor.YELLOW,             // lcd color
                    true,                                    // lcd visible
                    steelseries.LedColor.YELLOW_LED,         // led color
                    true);                                   // led visible

  // Let's set some values...
  radial1.setValueAnimated(70);
  radial2.setValueAnimated(41);
  radial3.setValueAnimated(70);
}

As you can see the drawback of the current design are the long constructors. I'm still not sure how to make these nicer but i'm working on that...


UPDATE:
Thanx to Andres Almiray who pointed me in the right direction i modified the constructor of the Radial and RadialBargraph component in the way that it now takes a hash as a set of parameters. This means you don't have to put in all the default parameters anymore which makes the initialization of the components look like this...
!!! NEW VERSION !!!


function init()
{
  // Define some sections
  var sections = Array(steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),
                       steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'), 
                       steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)'));
  
  // Define one area
  var areas = Array(steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)'));
            
  // Create one radial gauge
  var radial1 = new steelseries.Radial(
                    'canvas1', {
                    section: sections,                      
                    area: areas,                            
                    titleString: 'Test',                    
                    unitString: 'Unit',                     
                    pointerType: steelseries.PointerType.TYPE8
                    });                               

// Create a second radial gauge
  var radial2 = new steelseries.Radial(
                    'canvas2', {
                    gaugeType: steelseries.GaugeType.TYPE2,                     
                    maxValue: 50, 
                    threshold: 40, 
                    section: Array(steelseries.Section(0,40,'rgba(0,255,0,0.3)')),
                    area: Array(steelseries.Section(40,50,'rgba(255,0,0,0.5)')), 
                    titleString: 'Test', 
                    unitString: 'Unit', 
                    frameDesign: steelseries.FrameDesign.CHROME, 
                    backgroundColor: steelseries.BackgroundColor.LIGHT_GRAY, 
                    pointerType: steelseries.PointerType.TYPE2, 
                    pointerColor: steelseries.ColorDef.BLUE, 
                    lcdColor: steelseries.LcdColor.BLUE2,                     
                    ledColor: steelseries.LedColor.BLUE_LED, 
                    });

  // Create a radial bargraph gauge
  var radial3 = new steelseries.RadialBargraph(
                    'canvas3', {
                    gaugeType: steelseries.GaugeType.TYPE3,
                    titleString: "Title",                                
                    unitString: "Unit",          
                    frameDesign: steelseries.FrameDesign.BLACK_METAL,
                    backgroundColor: steelseries.BackgroundColor.LIGHT_GRAY,
                    valueColor: steelseries.ColorDef.YELLOW,
                    lcdColor: steelseries.LcdColor.YELLOW,
                    ledColor: steelseries.LedColor.YELLOW_LED,
                    });                                   

  // Let's set some values...
  radial1.setValueAnimated(70);
  radial2.setValueAnimated(41);
  radial3.setValueAnimated(70);
}


Guess that looks much better than before... :-)




If you put all these things together in one html page you should see something like this...


Image


If you are to lazy to play around you might want to click here to see it in action...


There are two versions of the library available right now, the uncompressed (101 kb) and compressed (61 kb) version. You could download the version clicking on one of the following links:


    uncompressed version:    steelseries.js


    compressed version:       steelseries-min.js


    animation library:           tween.js


Keep in mind that this project is work in progress and things might change in the future...


Enjoy the upcoming weekend and keep coding...