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.
);