@agierens/meshed-node-client

yarn add @agierens/meshed-node-client

Usage no npm install needed!

<script type="module">
  import agierensMeshedNodeClient from 'https://cdn.skypack.dev/@agierens/meshed-node-client';
</script>

README

Meshed Node Client

Installation

yarn add @agierens/meshed-node-client

Manual Client setup

If you plan to have configuration setup manually by your application, you can do something like the following:

import { Device } from '@agierens/meshed-node-client';

class YourDevice extends Device {
  name = "The name of your device";
  description = "A description for your device";

  constructor(host:string, clientId: string, ownerId: string, interval: number) {
    super(host, clientId, ownerId, interval);
  }

  async getStatuses() {
    return [{
            // This is the unique status id
            id: 'out-temp',

            // The name of the status.
            name: "Outdoor Temperature Sensor",

            // The description of the status.
            description: "Measures the outdoor temperature near the shed.",

            // Inc this as you add more statuses (This is not done automaticly for a reason)
            channel: 1, 

            // This will be used by the widget to render the prefix if nessessary
            prefix: undefined,

            // This is a string and always will be a string. Can be any data type as a string
            value: (Math.floor(Math.random() * (1000 - 100) + 100) / 100).toFixed(2), 

            // This will be used by the widget to render the suffix if nessessary
            suffix: '°C' 
      }];
  }
}

const host = "192.168.1.14";
const clientId = "936eb10d-1401-4152-a3b3-bbf1940303ee";
const ownerId = "dc9e0bb8-b3c8-4243-8844-6119e00cea59";

const device = new YourDevice(host, clientId, ownerId);
device.connect();

Configuration Server Setup

If you'd like to use the built in configuration server (display a webpage page to allow configuring the device) you can use the following:

import { Device, startConfigServer } from '@agierens/meshed-node-client';

class YourDevice extends Device {
  name = "The name of your device";
  description = "A description for your device";

  constructor(host:string, clientId: string, ownerId: string, interval?: number) {
    super(host, clientId, ownerId, interval || 3000);
  }
}

  async getStatuses() {
    return [{
            // This is the unique status id
            id: 'out-temp',

            // The name of the status.
            name: "Outdoor Temperature Sensor",

            // The description of the status.
            description: "Measures the outdoor temperature near the shed.",

            // Inc this as you add more statuses (This is not done automaticly for a reason)
            channel: 1, 

            // This will be used by the widget to render the prefix if nessessary
            prefix: undefined,

            // This is a string and always will be a string. Can be any data type as a string
            value: (Math.floor(Math.random() * (1000 - 100) + 100) / 100).toFixed(2), 

            // This will be used by the widget to render the suffix if nessessary
            suffix: '°C'
      }];
  }
}

// Note, this will automatically "connect" the device once the configuration variables are set correctly.
// A file called "config.json" is created at the root to store these variables.
startConfigServer(
  {
    host: { type: "text", required: true },
    clientId: { type: "text", required: true },
    ownerId: { type: "text" , required: true },
    interval: { type: "number", defaultValue: 1000 }
  },
  // Proper typing based on the above config will occur eg:
  // c: { host: string; clientId: string; ownerId: string; interval: number | undefined; }
  c => new YourDevice(c.host, c.clientId, c.ownerId, c.interval),
  3000, // The port for the server to start on
);

Configuration Server Fields

Field Types

Currently there are two kinds of config fields:

{ type: "text" } // outputs to string

and

{ type: "number" } // outputs to number

The field on the configuration web page will display a relevant input to capture the data.

Required

You can add required to the config field to ensure that the field must be entered before submitting as follows:

{ type: "number", required: true } // outputs to string

Note, the default (without {required: true}) will not stop you from leaving the field blank, and the resulting config value can be undefined.

For example:

{ fieldName: {type: "number"} } would output values { fieldName: number | undefined }.

Default Value

You can add defaultValue to populate a default value:

{ type: "number", defaultValue: 123 }

Configuration Server Logs

The configuration server has a built in way to show and record logs from both the configuration server and an external log source, using winston. These can be seen on on the config html page.

By default, logs are output to config-server.log, and only output from the configuration server are logged.

if you would like to log information from your host application as well, you can add an external logger that the configuration server will use and display:

import { Device, startConfigServer } from '@agierens/meshed-node-client';
import logger, { configure, transports, format } from "winston";

// Configuring the default logger here from winston, but you can also
// createLogger and pass it into the config server
configure({
  level: "info",
  transports: [
    new transports.File({
      filename: "app.log", // changing where logs are stored
      format: format.combine(format.timestamp(), format.json()),
    }),
    new transports.Console({
      format: format.combine(
        format.colorize(),
        format.timestamp(),
        format.simple()
      ),
    }),
  ],
});

class YourDevice extends Device {
// ... as above

startConfigServer(
  {
    host: { type: "text", required: true },
    clientId: { type: "text", required: true },
    ownerId: { type: "text" , required: true },
    interval: { type: "number", defaultValue: 1000 }
  },
  c => new YourDevice(c.host, c.clientId, c.ownerId, c.interval),
  3000,
  logger // Pass your logger in here, the config server will log based on your configurations above.
);