shelly-sdk
Version:
Shelly SDK for Node.js with Types definition
174 lines • 5.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Shelly = void 0;
const axios_1 = require("axios");
const settings_1 = require("./marshalling/settings");
const status_1 = require("./marshalling/status");
const nanoid_1 = require("nanoid");
const netmask_1 = require("netmask");
const SHELLY_DEFAULT_PORT = 80;
const sendCommand = async (params) => {
const { ip, path, port, command, value } = params;
const timeout = params.timeout || 1000;
let url = `http://${ip}:${port}/${path}`;
if (command) {
url += `?${command}=${value}`;
}
const response = await (0, axios_1.default)({
method: 'GET',
url,
headers: {
'Content-Type': 'application/json',
'x-requested-with': 'XMLHttpRequest',
},
timeout,
});
if (response.status === 200) {
return response.data;
}
else {
throw new Error(`HTTP ${response.status}`);
}
};
const updateDevice = async (params) => {
const { ip, port, path, body } = params;
const response = await (0, axios_1.default)({
method: 'POST',
url: `http://${ip}:${port}/${path}`,
headers: {
'Content-Type': 'application/json',
'x-requested-with': 'XMLHttpRequest',
},
data: body,
});
if (response.status === 200) {
return response.data;
}
else {
throw new Error(`HTTP ${response.status}`);
}
};
class Shelly {
constructor(config) {
this.config = Object.assign({}, { port: SHELLY_DEFAULT_PORT, id: (0, nanoid_1.nanoid)() }, config);
}
static async scanNetwork(baseIp, port = SHELLY_DEFAULT_PORT, timeout = 30000) {
const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
const [networkAddress, subnetMask] = baseIp.split('/');
if (!ipRegex.test(networkAddress)) {
throw new Error('Invalid IP address');
}
if (!subnetMask) {
throw new Error('Invalid subnet mask');
}
const block = new netmask_1.Netmask(baseIp);
const devices = [];
const scanIp = async (ip) => {
try {
const deviceInfo = await sendCommand({
ip,
port,
path: 'settings',
timeout,
});
if (deviceInfo.device) {
const config = {
name: deviceInfo.name,
type: deviceInfo.device.type,
id: deviceInfo.device.hostname,
ip,
port,
};
devices.push(config);
return config;
}
else {
return undefined;
}
}
catch (e) {
return undefined;
}
};
const addresses = [];
block.forEach((ip) => {
addresses.push(ip);
});
const promises = addresses.map(async (ip) => {
return scanIp(ip);
});
await Promise.all(promises);
return devices.filter(r => r !== undefined);
}
static async instantiateDevices(configList) {
const devices = configList.map(config => {
return new Shelly(config);
});
const promises = devices.map(device => {
return device.init();
});
await Promise.all(promises);
return devices;
}
async init() {
await this.settings();
await this.status();
return this;
}
getConfig() {
return this.config;
}
async settings() {
const res = await sendCommand({
ip: this.config.ip,
port: this.config.port,
path: 'settings',
});
this._settings = (0, settings_1.unmarshallRemoteSettings)(res);
return this._settings;
}
async status() {
const res = await sendCommand({
ip: this.config.ip,
port: this.config.port,
path: 'status',
});
this._status = (0, status_1.unmarshallStatus)(res);
return this._status;
}
async switchOff() {
return this.switch(false);
}
async switchOn() {
return this.switch(true);
}
async switch(state) {
return sendCommand({
ip: this.config.ip,
port: this.config.port,
path: 'relay/0',
command: 'turn',
value: state ? 'on' : 'off',
});
}
async update(settings) {
return updateDevice({
ip: this.config.ip,
port: this.config.port,
path: 'settings',
body: settings,
});
}
toString() {
return `${this.config.name} (${this.config.id})`;
}
serialize() {
return {
...this.config,
settings: this._settings,
status: this._status,
};
}
}
exports.Shelly = Shelly;
//# sourceMappingURL=shelly.js.map