fix(gateay): fix all nodes and output node
also start setColor of the gateway
This commit is contained in:
@@ -4,6 +4,7 @@ import * as crypto from 'crypto';
|
||||
import {GatewayServer} from "./GatewayServer";
|
||||
import {GatewayMessage, GatewaySubdevice, Magnet, Motion, Switch, Weather} from "./";
|
||||
import * as MessageData from "./GatewayMessageData";
|
||||
import {Color} from "../utils/Color";
|
||||
|
||||
export class Gateway extends events.EventEmitter {
|
||||
static iv: Buffer = Buffer.from([0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58, 0x56, 0x2e]);
|
||||
@@ -16,8 +17,10 @@ export class Gateway extends events.EventEmitter {
|
||||
}
|
||||
|
||||
get key(): string {
|
||||
if (!this.lastToken || !this.password) return null;
|
||||
|
||||
var cipher = crypto.createCipheriv('aes-128-cbc', this.password, Gateway.iv);
|
||||
var key = cipher.update(this.lastToken, "ascii", "hex");
|
||||
var key = cipher.update(Buffer.from(this.lastToken), "ascii", "hex");
|
||||
cipher.final('hex');
|
||||
|
||||
return key;
|
||||
@@ -27,12 +30,13 @@ export class Gateway extends events.EventEmitter {
|
||||
if (msg.data) {
|
||||
if (msg.model === "gateway" && msg.sid === this.sid && msg.token) {
|
||||
this.lastToken = msg.token;
|
||||
this.setLight(100, {red: 255, green: 0, blue: 0});
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.isGetIdListAck()) {
|
||||
(<MessageData.GatewayMessageGetIdListData> msg.data).forEach((sid) => {
|
||||
this.sendRead({cmd: "read", sid: sid});
|
||||
this.send({cmd: "read", sid: sid});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,17 +66,34 @@ export class Gateway extends events.EventEmitter {
|
||||
return !!this._subdevices[sid];
|
||||
}
|
||||
|
||||
setLight() {
|
||||
|
||||
setLight(brightness, rgb) {
|
||||
this.send({
|
||||
cmd: "write",
|
||||
data: {
|
||||
rgb: Color.toValue(rgb.red, rgb.green, rgb.blue, brightness),
|
||||
sid: this.sid
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
playSound() {
|
||||
|
||||
}
|
||||
|
||||
sendRead(message: any) {
|
||||
message.sid = message.sid || this.sid;
|
||||
GatewayServer.getInstance().sendToGateway(this.sid, message);
|
||||
send(message: any) {
|
||||
let msg = Object.assign({}, message.payload || message);
|
||||
if (msg.cmd) {
|
||||
msg.sid = message.sid || this.sid;
|
||||
if (msg.gateway) {
|
||||
delete msg.gateway;
|
||||
}
|
||||
|
||||
if (msg.cmd === "write") {
|
||||
msg.data.key = this.key;
|
||||
}
|
||||
|
||||
GatewayServer.getInstance().sendToGateway(this.sid, msg);
|
||||
}
|
||||
}
|
||||
|
||||
get subdevices(): { [sid: string]: GatewaySubdevice } {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Red, NodeProperties } from "node-red";
|
||||
import { Constants } from "../constants";
|
||||
import {Red, NodeProperties} from "node-red";
|
||||
import {Constants} from "../constants";
|
||||
|
||||
export default (RED:Red) => {
|
||||
export default (RED: Red) => {
|
||||
class All {
|
||||
protected gateway: any;
|
||||
protected onlyModels: string[];
|
||||
@@ -15,40 +15,50 @@ export default (RED:Red) => {
|
||||
return cleanOnlyModels;
|
||||
}
|
||||
|
||||
constructor(props:NodeProperties) {
|
||||
constructor(props: NodeProperties) {
|
||||
RED.nodes.createNode(<any> this, props);
|
||||
this.gateway = RED.nodes.getNode((<any> props).gateway);
|
||||
this.onlyModels = All.getOnlyModelsValue((<any> props).onlyModels || []);
|
||||
this.excludedSids = (<any> props).excludedSids;
|
||||
|
||||
this.setMessageListener();
|
||||
}
|
||||
|
||||
protected setMessageListener() {
|
||||
(<any> this).on('input', (msg) => {
|
||||
if (this.gateway) {
|
||||
// Filter input
|
||||
if(msg.payload && msg.payload.model && msg.payload.sid) {
|
||||
if(!this.isDeviceValid(msg.payload)) {
|
||||
if (msg.payload && msg.payload.model && msg.payload.sid) {
|
||||
if (!this.isDeviceValid(msg.payload)) {
|
||||
msg = null;
|
||||
}
|
||||
(<any> this).send(msg);
|
||||
}
|
||||
// Prepare for request
|
||||
else {
|
||||
msg.payload = this.gateway.deviceList.filter((device) => this.isDeviceValid(device));
|
||||
Object.keys(this.gateway.deviceList || {})
|
||||
.filter((sid) => this.isDeviceValid(sid))
|
||||
.forEach((sid) => {
|
||||
let curMsg = Object.assign({}, msg);
|
||||
curMsg.sid = sid;
|
||||
curMsg.gateway = this.gateway;
|
||||
(<any> this).send(curMsg);
|
||||
});
|
||||
}
|
||||
(<any> this).send(msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isDeviceValid(device) {
|
||||
if((!this.onlyModels || this.onlyModels.length == 0) && (!this.excludedSids || this.excludedSids.length == 0)) {
|
||||
isDeviceValid(sid) {
|
||||
if ((!this.onlyModels || this.onlyModels.length == 0) && (!this.excludedSids || this.excludedSids.length == 0)) {
|
||||
return true;
|
||||
}
|
||||
let device = this.gateway.deviceList[sid];
|
||||
// Is excluded
|
||||
if((this.excludedSids && this.excludedSids.length != 0) && this.excludedSids.indexOf(device.sid) >= 0) {
|
||||
if ((this.excludedSids && this.excludedSids.length != 0) && this.excludedSids.indexOf(sid) >= 0) {
|
||||
return false;
|
||||
}
|
||||
if((this.onlyModels && this.onlyModels.length != 0) && this.onlyModels.indexOf(device.model) >= 0) {
|
||||
if ((this.onlyModels && this.onlyModels.length != 0) && this.onlyModels.indexOf(device.internalModel) >= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,14 @@ export default (RED:Red, type:string) => {
|
||||
this.sid = (<any> props).sid;
|
||||
|
||||
(<any> this).status({fill:"grey", shape:"ring", text:"battery - na"});
|
||||
|
||||
this.setMessageListener();
|
||||
}
|
||||
|
||||
protected setMessageListener() {
|
||||
if (this.gateway) {
|
||||
(<any> this).on('input', (msg) => {
|
||||
let payload = msg.payload;
|
||||
|
||||
|
||||
// Input from gateway
|
||||
if (payload.sid) {
|
||||
if (payload.sid == this.sid) {
|
||||
@@ -25,7 +28,7 @@ export default (RED:Red, type:string) => {
|
||||
fill: "green", shape: "dot",
|
||||
text: "battery - " + batteryLevel + "%"
|
||||
};
|
||||
|
||||
|
||||
if (batteryLevel < 10) {
|
||||
status.fill = "red";
|
||||
} else if (batteryLevel < 45) {
|
||||
|
||||
@@ -16,17 +16,24 @@ export interface IGatewayConfiguratorNode extends Node {
|
||||
on(event: "subdevice-update", listener: (subdevice: GatewaySubdevice) => void): any;
|
||||
}
|
||||
|
||||
interface GatewayConfiguratorSubDevice {
|
||||
name: string;
|
||||
internalModel: string;
|
||||
}
|
||||
|
||||
export default (RED: Red) => {
|
||||
class GatewayConfigurator {
|
||||
sid: string;
|
||||
key: string;
|
||||
deviceList: { [sid: string]: GatewayConfiguratorSubDevice };
|
||||
_gateway: Gateway;
|
||||
|
||||
constructor(props: NodeProperties) {
|
||||
RED.nodes.createNode(<any> this, props);
|
||||
let {sid, key} = <any> props;
|
||||
let {sid, key, deviceList} = <any> props;
|
||||
this.sid = sid;
|
||||
this.key = key;
|
||||
this.deviceList = deviceList;
|
||||
let server = GatewayServer.getInstance();
|
||||
if (this.sid) {
|
||||
this.setGateway();
|
||||
|
||||
@@ -36,51 +36,6 @@ export default (RED: Red) => {
|
||||
protected gatewayOffline() {
|
||||
(<any>this).status({fill: "red", shape: "ring", text: "offline"});
|
||||
}
|
||||
|
||||
/*setGateway(gateway:LumiAqara.Gateway) {
|
||||
this.gateway = gateway;
|
||||
this.gateway.setPassword(this.gatewayConf.password);
|
||||
(<any>this).status({fill:"blue", shape:"dot", text: "online"});
|
||||
|
||||
this.gateway.on('offline', () => {
|
||||
this.gateway = null;
|
||||
(<any>this).status({fill:"red", shape:"ring", text: "offline"});
|
||||
});
|
||||
|
||||
this.gateway.on('subdevice', (device) => {
|
||||
device.sid = device.getSid();
|
||||
device.type = device.getType();
|
||||
device.data = {
|
||||
voltage: device.getBatteryVoltage(),
|
||||
batteryLevel: device.getBatteryPercentage()
|
||||
};
|
||||
switch (device.type) {
|
||||
case 'magnet':
|
||||
device.data.status = device.isOpen() ? 'open' : 'close';
|
||||
break;
|
||||
case 'switch':
|
||||
device.on('click', () => {
|
||||
// Saaad
|
||||
});
|
||||
break;
|
||||
case 'motion':
|
||||
break;
|
||||
case 'sensor':
|
||||
device.data.temperature = device.getTemperature();
|
||||
device.data.humidity = device.getHumidity();
|
||||
device.data.pressure = device.getPressure();
|
||||
break;
|
||||
case 'leak':
|
||||
break;
|
||||
case 'cube':
|
||||
break;
|
||||
};
|
||||
|
||||
(<any>this).send({
|
||||
payload: device
|
||||
});
|
||||
});
|
||||
}*/
|
||||
}
|
||||
|
||||
RED.nodes.registerType(`${Constants.NODES_PREFIX}-gateway in`, <any> GatewayIn);
|
||||
|
||||
@@ -1,44 +1,19 @@
|
||||
import { Red, NodeProperties } from "node-red";
|
||||
import { Constants } from "../constants";
|
||||
import {Gateway} from "../../devices/Gateway";
|
||||
import {Red, NodeProperties} from "node-red";
|
||||
import {Constants} from "../constants";
|
||||
|
||||
export interface IGatewayOutNode extends Node {
|
||||
gatewayConf:any;
|
||||
gateway: Gateway;
|
||||
}
|
||||
|
||||
export default (RED:Red) => {
|
||||
export default (RED: Red) => {
|
||||
class GatewayOut {
|
||||
protected gatewayConf: any;
|
||||
|
||||
constructor(props: NodeProperties) {
|
||||
RED.nodes.createNode(<any> this, props);
|
||||
this.gatewayConf = RED.nodes.getNode((<any> props).gateway);
|
||||
|
||||
(<any>this).status({fill: "red", shape: "ring", text: "offline"});
|
||||
|
||||
if (this.gatewayConf.gateway) {
|
||||
(<any>this).status({fill: "blue", shape: "dot", text: "online"});
|
||||
}
|
||||
|
||||
this.gatewayConf.on('gateway-online', () => {
|
||||
(<any>this).status({fill: "blue", shape: "dot", text: "online"});
|
||||
});
|
||||
|
||||
this.gatewayConf.on('gateway-offline', () => {
|
||||
(<any>this).status({fill: "red", shape: "ring", text: "offline"});
|
||||
});
|
||||
this.setMessageListener();
|
||||
}
|
||||
|
||||
protected setMessageListener() {
|
||||
/*(<any> this).on("input", (msg) => {
|
||||
if (msg.hasOwnProperty("payload") && this.gateway) {
|
||||
if(msg.payload.cmd === "write" && !msg.payload.data.key && this.gateway && this.gateway.sid && this.gateway._key) {
|
||||
msg.payload.data.key = this.gateway._key;
|
||||
}
|
||||
this.gateway._sendUnicast(JSON.stringify(msg.payload));
|
||||
(<any> this).on("input", (msg) => {
|
||||
if (msg.hasOwnProperty("payload") && msg.hasOwnProperty("gateway")) {
|
||||
msg.gateway.gateway.send(msg);
|
||||
}
|
||||
});*/
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
src/utils/Color.ts
Normal file
25
src/utils/Color.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export class Color {
|
||||
static toValue(red, green, blue, brightness) {
|
||||
return (brightness !== undefined ? 256 * 256 * 256 * brightness : 0) + (256 * 256 * red) + (256 * green) + blue;
|
||||
}
|
||||
|
||||
static fromValue(rgb) {
|
||||
var blue = rgb % 256;
|
||||
rgb = Math.max(rgb - blue, 0);
|
||||
|
||||
var green = rgb % (256 * 256);
|
||||
rgb = Math.max(rgb - green, 0);
|
||||
green /= 256;
|
||||
|
||||
var red = rgb % (256 * 256 * 256);
|
||||
rgb = Math.max(rgb - red, 0);
|
||||
red /= 256 * 256;
|
||||
|
||||
var brightness = rgb / (256 * 256 * 256);
|
||||
|
||||
return {
|
||||
brightness: brightness,
|
||||
color: {red: red, green: green, blue: blue}
|
||||
};
|
||||
}
|
||||
}
|
||||
1
src/utils/index.ts
Normal file
1
src/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Color';
|
||||
Reference in New Issue
Block a user