UNPKG

node-red-contrib-voice-assistant

Version:

一个小度-小爱-猫精音箱控制NODE-RED自定义设备的节点

197 lines (181 loc) 6.99 kB
const { default: MqttClient } = require('./lib/comm/mqtt'); const { default: Halink } = require('./lib/service/haService'); const { default: CustomService } = require('./lib/service/customService'); const { default: HandleAttribute } = require('./lib/handleAttr'); module.exports = function (RED) { 'use strict'; var getmac = require('getmac'); var reg = new RegExp(':', 'g'); var models = []; function XiaoDuSerConfig(n) { RED.nodes.createNode(this, n); if (this.credentials) { this.username = this.credentials.username; this.password = this.credentials.password; } models = this.models = []; this.localmac = getmac.default().replace(reg, ''); if (!this.username || !this.password) { return; } //生成处理类 this.handleAttribute = new HandleAttribute(this.models); this.mqttClient = new MqttClient(this.username, this.password); this.mqttClient.subTopic('sys/user/get/' + this.username + '/#'); this.mqttClient.subTopic('sys/user/get/ha/' + this.username); this.mqttClient.pubTopic = 'sys/user/update/' + this.username; this.mqttClient.connect(); this.mqttClient.onData = (err, msg) => { //console.log(err) //公用接收 if (err) return; if (msg.message) { const { payload } = msg.message; if (payload.type === 'getProps') { payload.data = this.handleAttribute.getProps(payload.data); this.mqttClient.publish(payload); } else if (payload.type === 'getDevices') { payload.data = []; this.models.forEach((it) => { if (it.enable) payload.data.push(it); }); this.mqttClient.publish(payload); } } }; this.on('close', (done) => { this.models = models = []; this.mqttClient.close(done); done && done(); }); //网页获取设备 RED.httpAdmin.get('/GetVoiceDeviceList', (req, res) => { res.json({ data: models }); }); } RED.nodes.registerType('ServiceConfig', XiaoDuSerConfig, { credentials: { username: { type: 'text' }, password: { type: 'password' }, }, }); function XiaoAiIn(n) { RED.nodes.createNode(this, n); const configNode = RED.nodes.getNode(n.broker); var node = this; if (!configNode) { node.status({ fill: 'red', shape: 'dot', text: '服务未配置' }); return; } node.customService = new CustomService(n.devtype, configNode); const model = node.customService.createDevModel(n.name); model && configNode.models.push(model); //生成设备 node.customService.onSetProps = function (msgs) { console.log('msgs', msgs); node.send({ devid: msgs.id, payload: { name: msgs.name, value: msgs.value } }); return; //设置消息 /* msgs.forEach((element) => { node.send(element); }); */ }; node.customService.onStatus = function (err, msg) { if (err) { node.status({ fill: 'red', shape: 'dot', text: err }); return; } if (msg.reconnect) { node.status({ fill: 'yellow', shape: 'dot', text: '云服务重连中' }); return; } if (msg.connect) { node.status({ fill: 'green', shape: 'dot', text: '云服务连接成功' }); } }; } RED.nodes.registerType('cmd in', XiaoAiIn); function XiaoAiOut(n) { RED.nodes.createNode(this, n); const configNode = RED.nodes.getNode(n.broker); var node = this; if (configNode) { //const customService = new CustomService('', configNode); node.on('input', function (msg) { try { configNode.handleAttribute.saveCustomState(msg); } catch {} }); } } RED.nodes.registerType('state out', XiaoAiOut); function HassLink(n) { RED.nodes.createNode(this, n); this.brokerConn = RED.nodes.getNode(n.broker); this.devData = n.devdata; let hasslink; if (this.brokerConn) { hasslink = new Halink(this, n.address, n.token); } this.on('close', () => { if (hasslink) hasslink.haClient.close(); }); } RED.nodes.registerType('hass link', HassLink); /* frpc */ function run(node) { node.frpClient.setup(node).then((err) => { if (err) { setTimeout(() => { run(node); }, 10000); return node.status({ fill: 'red', shape: 'dot', text: err.msg }); } node.frpClient.start(function (info) { if (!info.code) { console.log(info.msg); } else { const status = { fill: 'green', shape: 'dot', text: 'frp连接成功' }; if (info.code === 244) { node.status(status); } else { delete info.code; node.send({ payload: info }); } } }); }); } function Frpc(n) { RED.nodes.createNode(this, n); this.brokerConn = RED.nodes.getNode(n.broker); this.options = n.options; const node = this; for(let i=0;i<this.options.length;i++){ if(this.options[i].url === '' || this.options[i].port === ''){ this.status({ fill: 'red', shape: 'dot', text: '映射参数未配置' }); return; } this.options[i].port = parseInt(this.options[i].port); } if (this.brokerConn ) { const { default: FrpClient } = require('./lib/frpc'); node.frpClient = new FrpClient(); node.brokerConn.mqttClient.onData = function (err, data) { if (err) return; const msg = data.message; if (!msg) return; if (!msg.topic) return; const type = msg.topic.split('/').length === 5 ? msg.topic.split('/')[4] : null; if (!type) return; if (type !== 'frpConfig') return; node.frpClient.authObj = msg.payload; }; run(node); } this.on('close', (done) => { this.status({ fill: 'red', shape: 'dot', text: 'frp未连接' }); this.frpClient.close(done); }); } RED.nodes.registerType('frpc', Frpc); };