LG201: IoT Cloud Server -
Client Development

Microcontroller Client

The test sketch, I’ve loaded on to my ESP32’s is a bit rough around the edges, it simply handshakes the device, then loops through sending simulated (badly) Temperature and Humidity data on an endless loop.

A combination of this functionality and the far more refined Sketch from the previous module will be the starting point for the devices I create in the next module that will communicate through this service.

I can’t wait to clean this up!

JavaScript Client

The Console widget on the WebApp uses a JavaScript WebSocket Client. It takes information about the logged-in customer to secure the connection.

As I continue developing this system, I will create a more complex JavaScript client that communicate securely with the system from external domains, using a combination of HTTP Posts and Web Sockets.


        var uri = "wss://" + window.location.host + "/ws?id=@device.DeviceUID";

        function connect() {
            socket = new WebSocket(uri);
            socket.onopen = function (event) {
                console.log("opened connection to " + uri);
                appendItem(list, "opened connection to " + uri);


            };

            socket.onclose = function (event) {
                console.log("closed connection from " + uri);
                appendItem(list, "closed connection from " + uri);
                appendItem(list, event.code + ' ' + event.reason);
            };

            socket.onmessage = function (event) {
                appendItem(list, event.data);
                console.log(event.data);



                //var object = JSON.parse(event.data);
                //alert(object.ErrorRequest);
            };
            socket.onerror = function (event) {
                appendItem(list, "error - " + JSON.stringify(event));
                console.log("error: " + event);
            };
        }

        connect();



        var list = document.getElementById("messages");
        var button = document.getElementById("socketButton");

        button.addEventListener("click", function () {

            var input = document.getElementById("Handshake");
            sendMessage(input.value.replace(/[\n\r]/g, ''));

            //input.value = "";
        });

        function sendMessage(message) {
            console.log("Sending: " + message);
            socket.send(message);
        }

        function appendItem(list, message) {
            var item = document.createElement("li");
            var now = new Date(Date.now());
            var formatted = now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
            item.appendChild(document.createTextNode(formatted + " - " + message));
            list.appendChild(item);

            var objDiv = $('.terminalWindow');
            if (objDiv.length > 0) {
                objDiv[0].scrollTop = objDiv[0].scrollHeight;
            }

            if ($('#messages li').length > 10) {

             $('#messages').children().first().remove();

            }

        }

                function getDevices() {
                    $.get("/ajax/devices/", function (data) {

                        $("#getDevices").html(data);

                    });
                }

                setInterval(getDevices, 3000);

.Net Core Client

This is a tidy little piece of code and will prove very powerful in linking external data with this system. It may also form the basis of automated clients that run in WebJobs on Azure.

I’m going to be using this in my next module to translate messages from another WebSocket Server and echo them to Devices on this system. I get the feeling I’m going to be using this a lot!

Restful API

I could create a separate WebApp for the API and just give it access to the Class Library, that might well make sense. But if you remember my user story “He needs to turn some services off so he can afford to take his girlfriend to dinner”, you'll understand I don’t want to pay for any more servers.

My financial saviour is once again the Pipeline Middleware, not only can we deal with Web Sockets and the Administration of them on the same server we can pass requests to RazorPages and also to API Controllers, we just need to make sure we don’t map the same route to both endpoints.

app.UseRouting();

app.UseEndpoints(endpoints =>
   {
      endpoints.MapControllers();

      endpoints.MapRazorPages();
   });

The Temperature and Humidity widgets on the WebApp use the Restful API, they use JavaScript Functions that make Ajax calls to the service every three seconds.

API Client

One of the Device types I mentioned earlier, was API Client, this addition to the system allows us to make Synchronous calls to the asynchronous Web Socket Server. This can be achieved by using the WhenAny command in C# to wait for anyone of two commands to finish.

bool result = await (await Task.WhenAny(SocketCommand(message, deviceId), NoResponse(8000)));

The first command creates a WebSocket connection, sends a message, and awaits a reply. The second command just waits a set amount of time, whichever completes first ends the ‘await’. This effectively gives the system a set amount of time to return a message, enabling us to post commands from other systems. This is how I will integrate voice commands from Amazon Alexa with devices on this system.

And for my next trick…

WebSocket Clients can be written in almost any programming language and run in varied environments. This work has been a great start and has helped me test and develop the system. The next logical step is to create a library of downloadable clients accompanied by integration instructions.

But the scope must end somewhere!