@chrispyduck/homie-sensors
Version:
Sensor library intended for ues with homie-device
327 lines • 16 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var ArrisSurfboardStatus_1;
Object.defineProperty(exports, "__esModule", { value: true });
const homie_device_1 = require("@chrispyduck/homie-device");
const ISensor_1 = require("../ISensor");
const lodash_1 = require("lodash");
const jsdom_1 = __importDefault(require("jsdom"));
const events_1 = require("events");
let ArrisSurfboardStatus = ArrisSurfboardStatus_1 = class ArrisSurfboardStatus extends events_1.EventEmitter {
constructor(config) {
super();
this.homieRegistration = null;
this.read = async () => {
var _a, _b, _c, _d;
const dom = await jsdom_1.default.JSDOM.fromURL(this.config.url);
const tables = dom.window.document.querySelectorAll("table");
if (tables.length !== 3)
throw new Error(`Expected 3 tables but found ${tables.length}`);
const metrics = {
startupProcedureStatus: this.extractSummary(tables[0].getElementsByTagName("tr")),
downstreamChannels: this.extractDownstreamChannels(tables[1].getElementsByTagName("tr")),
upstreamChannels: this.extractUpstreamChannels(tables[2].getElementsByTagName("tr")),
};
if (this.homieRegistration) {
this.homieRegistration.state.connectivityState.publishValue((_a = metrics.startupProcedureStatus.connectivityState) !== null && _a !== void 0 ? _a : "Unknown");
this.homieRegistration.state.configurationFile.publishValue((_b = metrics.startupProcedureStatus.configurationFileStatus) !== null && _b !== void 0 ? _b : "Unknown");
this.homieRegistration.state.bootState.publishValue((_c = metrics.startupProcedureStatus.bootState) !== null && _c !== void 0 ? _c : "Unknown");
this.homieRegistration.state.net.publishValue(metrics.startupProcedureStatus.networkAccess === "Allowed");
this.homieRegistration.state.security.publishValue((_d = metrics.startupProcedureStatus.securityStatus) !== null && _d !== void 0 ? _d : "Unknown");
for (let i = 0; i < metrics.downstreamChannels.length; i++) {
this.homieRegistration.downstreamChannels.id.publishValue(metrics.downstreamChannels[i].id, i);
this.homieRegistration.downstreamChannels.lockStatus.publishValue(metrics.downstreamChannels[i].lockStatus, i);
this.homieRegistration.downstreamChannels.frequency.publishValue(metrics.downstreamChannels[i].frequency, i);
this.homieRegistration.downstreamChannels.modulation.publishValue(metrics.downstreamChannels[i].modulation, i);
this.homieRegistration.downstreamChannels.power.publishValue(metrics.downstreamChannels[i].power, i);
this.homieRegistration.downstreamChannels.snr.publishValue(metrics.downstreamChannels[i].snr, i);
this.homieRegistration.downstreamChannels.correctedFrames.publishValue(metrics.downstreamChannels[i].corrected, i);
this.homieRegistration.downstreamChannels.uncorrectableFrames.publishValue(metrics.downstreamChannels[i].uncorrectable);
}
for (let i = 0; i < metrics.upstreamChannels.length; i++) {
this.homieRegistration.upstreamChannels.id.publishValue(metrics.upstreamChannels[i].id, i);
this.homieRegistration.upstreamChannels.lockStatus.publishValue(metrics.upstreamChannels[i].lockStatus, i);
this.homieRegistration.upstreamChannels.frequency.publishValue(metrics.upstreamChannels[i].frequency, i);
this.homieRegistration.upstreamChannels.width.publishValue(metrics.upstreamChannels[i].width, i);
this.homieRegistration.upstreamChannels.channelType.publishValue(metrics.upstreamChannels[i].channelType, i);
this.homieRegistration.upstreamChannels.power.publishValue(metrics.upstreamChannels[i].power, i);
}
}
return metrics;
};
this.extractSummary = (rows) => {
const result = {};
for (let i = 2; i < rows.length; i++) {
const caption = rows[i].children[0].innerHTML;
const status = rows[i].children[1].innerHTML;
const comment = rows[i].children[2].innerHTML;
switch (caption) {
case "Acquire Downstream Channel": {
result.downstreamChannelFrequency = Number.parseInt(status) / 1000 / 1000;
result.downstreamChannelStatus = comment;
break;
}
case "Connectivity State": {
result.connectivityState = status;
break;
}
case "Boot State": {
result.bootState = status;
break;
}
case "Configuration File": {
result.configurationFileStatus = status;
break;
}
case "Security": {
result.securityStatus = status;
break;
}
case "DOCSIS Network Access Enabled": {
result.networkAccess = status;
break;
}
}
}
return result;
};
this.extractDownstreamChannels = (rows) => {
const result = [];
for (let i = 2; i < rows.length; i++) {
const channelID = Number.parseInt(rows[i].children[0].innerHTML);
if (channelID > 0) {
const cellValues = Array
.from(rows[i].children)
.map(cell => cell.innerHTML);
const channel = {
id: channelID,
lockStatus: cellValues[1],
modulation: cellValues[2],
frequency: Number.parseInt(cellValues[3]) / 1000 / 1000,
power: Number.parseFloat(cellValues[4]),
snr: Number.parseFloat(cellValues[5]),
corrected: Number.parseInt(cellValues[6]),
uncorrectable: Number.parseInt(cellValues[7]),
};
result.push(channel);
}
}
return result.sort((a, b) => a.id - b.id);
};
this.extractUpstreamChannels = (rows) => {
const result = [];
for (let i = 2; i < rows.length; i++) {
const channelNum = Number.parseInt(rows[i].children[0].innerHTML);
if (channelNum > 0) {
const cellValues = Array
.from(rows[i].children)
.map(cell => cell.innerHTML);
const channel = {
id: Number.parseInt(cellValues[1]),
lockStatus: cellValues[2],
channelType: cellValues[3],
frequency: Number.parseInt(cellValues[4]) / 1000 / 1000,
width: Number.parseFloat(cellValues[5]) / 1000 / 1000,
power: Number.parseFloat(cellValues[6]),
};
result.push(channel);
}
}
return result.sort((a, b) => a.id - b.id);
};
this.config = lodash_1.merge({}, ArrisSurfboardStatus_1.DefaultConfiguration, config);
}
register(device) {
const stateNode = device.node(Object.assign(Object.assign({}, this.config.node), { name: `${this.config.node.name}-state`, friendlyName: `${this.config.node.friendlyName} - State`, isRange: false }));
const state = {
node: stateNode,
connectivityState: stateNode.addProperty({
name: "connectivity",
friendlyName: "Connectivity State",
dataType: homie_device_1.PropertyDataType.string,
settable: false,
retained: true,
}),
bootState: stateNode.addProperty({
name: "bootState",
friendlyName: "Boot State",
dataType: homie_device_1.PropertyDataType.string,
settable: false,
retained: true,
}),
configurationFile: stateNode.addProperty({
name: "configurationFile",
friendlyName: "Configuration File Status",
dataType: homie_device_1.PropertyDataType.string,
settable: false,
retained: true,
}),
security: stateNode.addProperty({
name: "security",
friendlyName: "Security State",
dataType: homie_device_1.PropertyDataType.string,
settable: false,
retained: true,
}),
net: stateNode.addProperty({
name: "net",
friendlyName: "DOCSIS Network Access Enabled",
dataType: homie_device_1.PropertyDataType.boolean,
settable: false,
retained: true,
}),
};
const downstreamNode = device.node(Object.assign(Object.assign({}, this.config.node), { name: `${this.config.node.name}-downstream`, friendlyName: `${this.config.node.friendlyName} - Downstream`, isRange: true, startRange: 0, endRange: this.config.downstreamChannels - 1 }));
const downstreamChannels = {
node: downstreamNode,
id: downstreamNode.addProperty({
name: "id",
friendlyName: "Channel ID",
dataType: homie_device_1.PropertyDataType.integer,
settable: false,
retained: true
}),
lockStatus: downstreamNode.addProperty({
name: "lockStatus",
friendlyName: "Lock Status",
dataType: homie_device_1.PropertyDataType.enum,
format: "Locked,Not Locked",
settable: false,
retained: true
}),
modulation: downstreamNode.addProperty({
name: "modulation",
friendlyName: "Modulation",
dataType: homie_device_1.PropertyDataType.string,
settable: false,
retained: true
}),
frequency: downstreamNode.addProperty({
name: "frequency",
friendlyName: "Frequency",
dataType: homie_device_1.PropertyDataType.float,
unit: "MHz",
settable: false,
retained: true
}),
power: downstreamNode.addProperty({
name: "power",
friendlyName: "Power",
dataType: homie_device_1.PropertyDataType.float,
unit: "dBmV",
settable: false,
retained: true
}),
snr: downstreamNode.addProperty({
name: "snr",
friendlyName: "Signal to Noise Ratio",
dataType: homie_device_1.PropertyDataType.float,
unit: "dB",
settable: false,
retained: true
}),
correctedFrames: downstreamNode.addProperty({
name: "correctedFrames",
friendlyName: "Corrected Frames",
dataType: homie_device_1.PropertyDataType.integer,
settable: false,
retained: true
}),
uncorrectableFrames: downstreamNode.addProperty({
name: "uncorrectableFrames",
friendlyName: "Uncorrectable Frames",
dataType: homie_device_1.PropertyDataType.integer,
settable: false,
retained: true
}),
};
const upstreamNode = device.node(Object.assign(Object.assign({}, this.config.node), { name: `${this.config.node.name}-upstream`, friendlyName: `${this.config.node.friendlyName} - Upstream`, isRange: true, startRange: 0, endRange: this.config.upstreamChannels - 1 }));
const upstreamChannels = {
node: upstreamNode,
id: upstreamNode.addProperty({
name: "id",
friendlyName: "Channel ID",
dataType: homie_device_1.PropertyDataType.integer,
settable: false,
retained: true
}),
lockStatus: upstreamNode.addProperty({
name: "lockStatus",
friendlyName: "Lock Status",
dataType: homie_device_1.PropertyDataType.enum,
format: "Locked,Not Locked",
settable: false,
retained: true
}),
channelType: upstreamNode.addProperty({
name: "usChannelType",
friendlyName: "US Channel Type",
dataType: homie_device_1.PropertyDataType.string,
settable: false,
retained: true
}),
frequency: upstreamNode.addProperty({
name: "frequency",
friendlyName: "Frequency",
dataType: homie_device_1.PropertyDataType.float,
unit: "MHz",
settable: false,
retained: true
}),
width: upstreamNode.addProperty({
name: "width",
friendlyName: "Width",
dataType: homie_device_1.PropertyDataType.float,
unit: "Hz",
settable: false,
retained: true
}),
power: upstreamNode.addProperty({
name: "power",
friendlyName: "Power",
dataType: homie_device_1.PropertyDataType.float,
unit: "dBmV",
settable: false,
retained: true
}),
};
this.homieRegistration = {
state,
downstreamChannels,
upstreamChannels,
};
}
init() {
return Promise.resolve();
}
};
ArrisSurfboardStatus.DefaultConfiguration = {
type: "net",
netType: "arris-surfboard-scraper",
node: {
name: "arris-surfboard",
friendlyName: "Arris Surfboard Cable Modem",
type: "Cable Modem",
isRange: false,
},
downstreamChannels: 33,
upstreamChannels: 3,
url: "http://192.168.100.1",
};
ArrisSurfboardStatus = ArrisSurfboardStatus_1 = __decorate([
ISensor_1.staticImplements(),
__metadata("design:paramtypes", [Object])
], ArrisSurfboardStatus);
exports.default = ArrisSurfboardStatus;
//# sourceMappingURL=ArrisSurfboard.js.map