dorita980-node18 – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 'use strict';
2  
3 const mqtt = require('mqtt');
4 const { constants } = require('crypto');
5  
6 var dorita980 = function localV2 (user, password, host, emitIntervalTime) {
7 if (!user) throw new Error('robotID is required.');
8 if (!password) throw new Error('password is required.');
9 if (!host) throw new Error('host is required.');
10  
11 const posibleCap = ['pose', 'ota', 'multiPass', 'carpetBoost', 'pp', 'binFullDetect', 'langOta', 'maps', 'edge', 'eco', 'svcConf'];
12 emitIntervalTime = emitIntervalTime || 800;
13 var robotState = {};
14 var cap = null;
15 var missionInterval;
16  
17 const url = 'tls://' + host;
18  
19 var options = {
20 port: 8883,
21 clientId: user,
22 rejectUnauthorized: false,
23 protocolId: 'MQTT',
24 protocolVersion: 4,
25 ciphers: process.env.ROBOT_CIPHERS || 'AES128-SHA256',
26 clean: false,
27 username: user,
28 password: password,
29 secureOptions: constants.SSL_OP_LEGACY_SERVER_CONNECT
30 };
31  
32 const client = mqtt.connect(url, options);
33  
34 client.on('error', function (e) {
35 throw e;
36 });
37  
38 client.on('connect', function () {
39 missionInterval = setInterval(() => {
40 if (robotState.cleanMissionStatus) {
41 client.emit('mission', filterProps(['cleanMissionStatus', 'pose', 'bin']));
42 }
43 }, emitIntervalTime);
44 });
45  
46 client.on('close', function () {
47 clearInterval(missionInterval);
48 });
49  
50 client.on('packetreceive', function (packet) {
51 if (packet.payload) {
52 try {
53 const msg = JSON.parse(packet.payload.toString());
54 robotState = Object.assign(robotState, msg.state.reported);
55 client.emit('update', msg);
56 client.emit('state', robotState);
57 if (robotState.cap) {
58 cap = {};
59 cap = Object.assign(cap, robotState.cap);
60 }
61 } catch (e) {}
62 }
63 });
64  
65 function _apiCall (topic, command, additionalArgs) {
66 return new Promise((resolve, reject) => {
67 let cmd = {command: command, time: Date.now() / 1000 | 0, initiator: 'localApp'};
68 if (topic === 'delta') {
69 cmd = {'state': command};
70 }
71 if (additionalArgs) {
72 cmd = Object.assign(cmd, additionalArgs);
73 }
74 client.publish(topic, JSON.stringify(cmd), function (e) {
75 if (e) return reject(e);
76 resolve({ok: null}); // for retro compatibility
77 });
78 });
79 }
80  
81 function hasAllProps (obj, properties) {
82 for (var p in properties) {
83 if (posibleCap.indexOf(properties[p]) > -1 && cap && Object.keys(cap).indexOf(properties[p]) === -1) {
84 obj[properties[p]] = undefined; // asking for a non available capability, just set to undefined
85 }
86 if (!obj.hasOwnProperty(properties[p])) {
87 return false;
88 }
89 }
90 return true;
91 }
92  
93 function filterProps (properties) {
94 let ret = {};
95 if (properties.length === 1) return robotState[properties[0]];
96 for (var p in properties) {
97 ret[properties[p]] = robotState[properties[p]];
98 }
99 return ret;
100 }
101  
102 function waitPreferences (decode, waitFor, returnOnlyThat) {
103 waitFor = (typeof waitFor === 'string') ? [waitFor] : waitFor;
104 return new Promise((resolve) => {
105 var checkInterval = setInterval(() => {
106 if (hasAllProps(robotState, waitFor)) {
107 clearInterval(checkInterval);
108 resolve(returnOnlyThat ? filterProps(waitFor) : robotState);
109 }
110 }, 100);
111 });
112 }
113  
114 return Object.assign(client, {
115 getTime: () => waitPreferences(false, ['utctime'], true),
116 getBbrun: () => waitPreferences(false, ['bbrun'], true),
117 getLangs: () => waitPreferences(false, ['langs'], true),
118 getSys: () => waitPreferences(false, ['bbrstinfo', 'cap', 'sku', 'batteryType', 'soundVer', 'uiSwVer', 'navSwVer', 'wifiSwVer', 'mobilityVer', 'bootloaderVer', 'umiVer', 'softwareVer', 'audio', 'bin'], true),
119 getWirelessLastStatus: () => waitPreferences(false, ['wifistat', 'wlcfg'], true),
120 getWeek: () => waitPreferences(false, ['cleanSchedule'], true),
121 getPreferences: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'cleanSchedule', 'name', 'vacHigh', 'signal'], false),
122 getRobotState: (fields) => waitPreferences(false, fields, false),
123 getMission: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'bin', 'batPct'], true),
124 getBasicMission: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'bin', 'batPct'], true),
125 getWirelessConfig: () => waitPreferences(false, ['wlcfg', 'netinfo'], true),
126 getWirelessStatus: () => waitPreferences(false, ['wifistat', 'netinfo'], true),
127 getCloudConfig: () => waitPreferences(false, ['cloudEnv'], true),
128 getSKU: () => waitPreferences(false, ['sku'], true),
129 start: () => _apiCall('cmd', 'start'),
130 clean: () => _apiCall('cmd', 'clean'),
131 cleanRoom: (args) => _apiCall('cmd', 'start', args),
132 pause: () => _apiCall('cmd', 'pause'),
133 stop: () => _apiCall('cmd', 'stop'),
134 resume: () => _apiCall('cmd', 'resume'),
135 dock: () => _apiCall('cmd', 'dock'),
136 find: () => _apiCall('cmd', 'find'),
137 evac: () => _apiCall('cmd', 'evac'),
138 train: () => _apiCall('cmd', 'train'),
139 setWeek: (args) => _apiCall('delta', {cleanSchedule: args}),
140 setPreferences: (args) => _apiCall('delta', args),
141 setCarpetBoostAuto: () => _apiCall('delta', {'carpetBoost': true, 'vacHigh': false}),
142 setCarpetBoostPerformance: () => _apiCall('delta', {'carpetBoost': false, 'vacHigh': true}),
143 setCarpetBoostEco: () => _apiCall('delta', {'carpetBoost': false, 'vacHigh': false}),
144 setEdgeCleanOn: () => _apiCall('delta', {'openOnly': false}),
145 setEdgeCleanOff: () => _apiCall('delta', {'openOnly': true}),
146 setCleaningPassesAuto: () => _apiCall('delta', {'noAutoPasses': false, twoPass: false}),
147 setCleaningPassesOne: () => _apiCall('delta', {'noAutoPasses': true, twoPass: false}),
148 setCleaningPassesTwo: () => _apiCall('delta', {'noAutoPasses': true, twoPass: true}),
149 setAlwaysFinishOn: () => _apiCall('delta', {'binPause': false}),
150 setAlwaysFinishOff: () => _apiCall('delta', {'binPause': true})
151 });
152 };
153  
154 module.exports = dorita980;