Search code examples
angularsocketssocket.ionode-reduibuilder

Node Red has a UiBuilder, but I want to listen to it from another app, using socket.io-client, fails to est connection


My client wants to have an OPs Engineer run the Node Red side of the house, but all operations support staff are to use a Single Page App (and never ever touch Node Red), so part of me was thinking that a sample uibuilder page will create a socket, but if I have an Angular app exist and that socket too exists, I can get all the data I need without hacking together code. As they keep extending the use cases, the ui builder is switching from simple screen components to lists, forms, loaders, etc in 1 endpoint, with layer, lots of inline classes, and no organization.

I have a sample UiBuilder for NodeRed called "launch" which when working through some samples has a socket I can listen to. I thought that it would be useful if I could create a different app, which also listens to this socket. For every Message received, if it doesn't exist in a list, it will add it to the list and hen from there we will start user stories.

I figured to implement socket in an Angular App, through a service I created. I created a simple client-server relationship with some demos found online, but I am now trying to link it to the Node Red uibuilder launch which exists.

I thought it was going to be as simple as updating the URL or path but that seems to not work.

Here is a sample file I was working with:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import * as io from 'socket.io-client'
import { environment } from 'src/environments/environment';
import * as Rx from 'rxjs/Rx';
export class SocketioService {
  private _socket;
  constructor(){}
  setupSocketConnection(){ 
    this._socket = io.connect(environment.SOCKET_ENDPOINT);
    let observable = new Observable( observer => {
      this.socket.on('msg', (data:string) => {
        console.log("INFO DUMP", data);
        observer.next(data)
      })
      return () => { this.socket.disconnect(); }
    })
    
    let observer = {
      next: (data: Object) => {
        console.log("In Emit.")
        this.socket.emit('msg', JSON.stringify(data));
      }
    }
    return Rx.Subject.create(observer, observable);
  }
}

and my env variable was: https://localhost:1800/uibuilder/vendor/socket.io/ because when looking up the network requests to the sample /launch i created, it looked like it was referencing here.

This is the demo i was using. https://tutorialedge.net/typescript/angular/angular-socket-io-tutorial/ to create something with angular8.

One other thing i was also noticing is that IntelliSense seems to not like my implementation of the line: this._socket = io.connect(...); saying "An accessor cannot be declared in an ambient context." Specifically: "Property 'connect' does not exist on type 'typeof import(.....node_modules/socket.io-client/build/index'"

I was thinking there might be some sort of handshake I need to mange to verify the socket, but it seems to never get that far.

Personal details:

  • Angular 8
  • Packages:
  • rxjs
  • rsjx-compat
  • socket.io
  • socket.io-client
  • @types/socket.io-client

My real purpose here is to just see a sample socket console dump, so there is no real front end, just a default Angular App running on :4200.

I don't think that the app itself would work under the uibuilder folders, as much as would just be deployed elsewhere and establish this connection.


Solution

  • You can create an Angular SPA using uibuilder.

    uibuilder will extend the Node-RED web service to serve up your SPA and any additional front-end libraries that you choose to install.

    In addition, it creates a websocket connection between Node-RED and your SPA.

    So you don't need any other external web or websocket resources, uibuilder manages all of that for you.


    Having said that, it is possible to run a uibuilder front-end app from a different webserver if you really need to. It isn't particularly well tested and it does require you to add some configuration manually. In this case, uibuilder will still create the websocket connection and manage it for you.