Saturday, October 15, 2016

MQTT - Paho AWS IOT Websockets example using Typescript, Javascript and C# and DotNet Core:


Sources:
https://eclipse.org/paho/clients/js/

Using the mqttSample, written in Javascript.
https://github.com/awslabs/aws-iot-examples

My GitHub Repository containing the code
https://github.com/julfeng/MqttTestApp

The location where the typescript conversion was kept below:




I'm writing an app to display device data as a stream to graph on a dashboard. I looked for an example for typescript and there wasn't any to be found as of yet. So, I converted the MQTT sample above (Item #2) to serve my purposes. I certainly hope someone besides me finds this useful.

Some of the problems I had while converting the app to typescript:
  1. The main component would not redraw when new list items were added to the log. to solve this problem, I added ApplicationRef and called the tick method.
  2. I used a javascript library for mqtt. In order to use this in Javascript you must declare a variable with the same name as the library object you are using as any. Typescript will magically recognize this variable as the imported type.
  3. To use the mqtt libraries, you must put script tags in your home page to load them.
  4. callbacks in the javascript library don't recognize the "this" pointer of the typescript class. You must call bind(this) after each callback method implemented in your class that is being called by the javascript library.


1. The main Component for the app is listed below:

import { Component, OnInit, OnDestroy, ApplicationRef } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import {LogService} from '../messages/logService';
import {RcvMessage} from '../messages/rcvMessage';
import {ConnectOptions} from '../iOT/connectOptions';
import {ClientControllerCache} from '../iOT/clientControllerCache';
import {ClientController} from '../iOT/clientController';
import {MQTTClient} from '../iOT/mqttClient';
@Component({
    moduleId: module.id,
    templateUrl: 'aws.component.html'
})
export class AWSComponent implements OnInit, OnDestroy {
    pageTitle: string = 'AWS Test App';
    endpoint: string;
    regionName: string;
    clientId: string;
    accessKey: string;
    secretKey: string;
    clients: ClientControllerCache;
    logs: LogService;
    connectOptions: ConnectOptions;
    constructor(private route: ActivatedRoute,
        private router: Router,
        private appRef: ApplicationRef) {
        
        
        this.endpoint = 'a327xxxxxxxxxxxxxx.iot.us-east-1.amazonaws.com';//substitute your endpoint you made in the AWS Console.
        this.regionName = 'us-east-1';
        this.accessKey = '';
        this.secretKey = '';
        this.clientId = 'AnyClientName';

    }

    ngOnInit(): void {
        this.logs = new LogService();
        this.logs.onTick = () => { this.appRef.tick() };
        //this.logs.log('hello');
        this.connectOptions = new ConnectOptions(this.endpoint, this.regionName, this.accessKey, this.secretKey, this.clientId);
        this.clients = new ClientControllerCache(this.logs);
    }

    ngOnDestroy() {

    }

    subscribe(clientController: ClientController): void {
        if (clientController)
            clientController.subscribe();
    }
    
    createClient(): void {
        var client = this.clients.getClient(this.connectOptions);
        if (!client.connected) {
            client.connect();
            
        }
        //this.appRef.tick();
        //alert('client created' + this.clientId);
    }

    removeClient(clientCtr) : void{
        this.clients.removeClient(clientCtr);
    }

    clearLog(): void {
        this.logs.clear();
    }

    onBack(): void {
        this.router.navigate(['/home']);
    }
}

2 and 3. Using a javascript library in typescript:

import {ConnectOptions} from './connectOptions';
import {SigV4Utils} from './sigV4Utils';
declare var Paho: any; // Magic
declare var moment: any;
export class MQTTClient {
...
}

Also in the /Views/Home/Index.html (the main page) I have script tags for the javascript libraries.
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="~/lib/moment/min/moment.min.js"></script>
    <script src="~/lib/paho-mqtt-js/mqttws31.js"></script>
    <script src="~/lib/cryptojslib/rollups/sha256.js"></script>
    <script src="~/lib/cryptojslib/rollups/hmac-sha256.js"></script>

4. Callbacks used in the javascript that are defined in typescript class:
import {LogService} from '../messages/logService';
import {MQTTClient } from './mqttClient';
import {RcvMessage} from '../messages/rcvMessage';
export class ClientController {
    client: MQTTClient;
    topicName: string;
    message: string;
    logService: LogService;
    msgs: RcvMessage[];
    id: string;
    constructor(client: MQTTClient, logs: LogService) {
        this.client = client;
        this.msgs = [];

        this.topicName = 'DashDemoUnit/Data';
        this.logService = logs;

        this.client.on('connectionLost', this.onConnectionLost.bind(this));
        this.client.on('messageArrived', this.onMessageArrived.bind(this));
        this.client.on('connected', this.onConnected.bind(this));
        this.client.on('subscribeFailed', this.onSubscribeFailed.bind(this));
        this.client.on('subscribeSucess', this.onSubscribeSuccess.bind(this));
        this.client.on('publishFailed', this.onPublishFailed.bind(this));
....
    }
Conclusion: Please feel free to browse the app on git hub and play with it. Navigate to the tab AWS Test and try it out. you will need an account on AWS with the IOT setup.

Tuesday, March 15, 2016



Had a busy week this week so far, my fun angel co-pilot flight to Central Illinois was cancelled due to weather, but, instead, I rehearsed for Easter on Sunday for a few hours, I play violin in the orchestra. 

Went to JJ Keller yesterday for Technology Days, where the whole team of developers come and meet to discuss current new technologies, and self-improvement tips. We had Raj, from Microsoft, come and explain some of Azure, cloud stuff (which was very interesting to me). It was exhilarating to talk to him some about the new DocumentDb storage for JSON data, (the Microsoft version of MongoDb).