dorita980-node18 – Blame information for rev 2

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,
2 office 29 reconnectPeriod: 10000,
1 office 30 secureOptions: constants.SSL_OP_LEGACY_SERVER_CONNECT
31 };
32  
33 const client = mqtt.connect(url, options);
34  
35 client.on('error', function (e) {
2 office 36 console.log(`Cannot connect to Roomba: ${e}`);
1 office 37 });
38  
39 client.on('connect', function () {
40 missionInterval = setInterval(() => {
41 if (robotState.cleanMissionStatus) {
42 client.emit('mission', filterProps(['cleanMissionStatus', 'pose', 'bin']));
43 }
44 }, emitIntervalTime);
45 });
46  
47 client.on('close', function () {
48 clearInterval(missionInterval);
49 });
50  
51 client.on('packetreceive', function (packet) {
52 if (packet.payload) {
53 try {
54 const msg = JSON.parse(packet.payload.toString());
55 robotState = Object.assign(robotState, msg.state.reported);
56 client.emit('update', msg);
57 client.emit('state', robotState);
58 if (robotState.cap) {
59 cap = {};
60 cap = Object.assign(cap, robotState.cap);
61 }
62 } catch (e) {}
63 }
64 });
65  
66 function _apiCall (topic, command, additionalArgs) {
67 return new Promise((resolve, reject) => {
68 let cmd = {command: command, time: Date.now() / 1000 | 0, initiator: 'localApp'};
69 if (topic === 'delta') {
70 cmd = {'state': command};
71 }
72 if (additionalArgs) {
73 cmd = Object.assign(cmd, additionalArgs);
74 }
75 client.publish(topic, JSON.stringify(cmd), function (e) {
76 if (e) return reject(e);
77 resolve({ok: null}); // for retro compatibility
78 });
79 });
80 }
81  
82 function hasAllProps (obj, properties) {
83 for (var p in properties) {
84 if (posibleCap.indexOf(properties[p]) > -1 && cap && Object.keys(cap).indexOf(properties[p]) === -1) {
85 obj[properties[p]] = undefined; // asking for a non available capability, just set to undefined
86 }
87 if (!obj.hasOwnProperty(properties[p])) {
88 return false;
89 }
90 }
91 return true;
92 }
93  
94 function filterProps (properties) {
95 let ret = {};
96 if (properties.length === 1) return robotState[properties[0]];
97 for (var p in properties) {
98 ret[properties[p]] = robotState[properties[p]];
99 }
100 return ret;
101 }
102  
103 function waitPreferences (decode, waitFor, returnOnlyThat) {
104 waitFor = (typeof waitFor === 'string') ? [waitFor] : waitFor;
105 return new Promise((resolve) => {
106 var checkInterval = setInterval(() => {
107 if (hasAllProps(robotState, waitFor)) {
108 clearInterval(checkInterval);
109 resolve(returnOnlyThat ? filterProps(waitFor) : robotState);
110 }
111 }, 100);
112 });
113 }
114  
115 return Object.assign(client, {
116 getTime: () => waitPreferences(false, ['utctime'], true),
117 getBbrun: () => waitPreferences(false, ['bbrun'], true),
118 getLangs: () => waitPreferences(false, ['langs'], true),
119 getSys: () => waitPreferences(false, ['bbrstinfo', 'cap', 'sku', 'batteryType', 'soundVer', 'uiSwVer', 'navSwVer', 'wifiSwVer', 'mobilityVer', 'bootloaderVer', 'umiVer', 'softwareVer', 'audio', 'bin'], true),
120 getWirelessLastStatus: () => waitPreferences(false, ['wifistat', 'wlcfg'], true),
121 getWeek: () => waitPreferences(false, ['cleanSchedule'], true),
122 getPreferences: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'cleanSchedule', 'name', 'vacHigh', 'signal'], false),
123 getRobotState: (fields) => waitPreferences(false, fields, false),
124 getMission: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'bin', 'batPct'], true),
125 getBasicMission: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'bin', 'batPct'], true),
126 getWirelessConfig: () => waitPreferences(false, ['wlcfg', 'netinfo'], true),
127 getWirelessStatus: () => waitPreferences(false, ['wifistat', 'netinfo'], true),
128 getCloudConfig: () => waitPreferences(false, ['cloudEnv'], true),
129 getSKU: () => waitPreferences(false, ['sku'], true),
130 start: () => _apiCall('cmd', 'start'),
131 clean: () => _apiCall('cmd', 'clean'),
132 cleanRoom: (args) => _apiCall('cmd', 'start', args),
133 pause: () => _apiCall('cmd', 'pause'),
134 stop: () => _apiCall('cmd', 'stop'),
135 resume: () => _apiCall('cmd', 'resume'),
136 dock: () => _apiCall('cmd', 'dock'),
137 find: () => _apiCall('cmd', 'find'),
138 evac: () => _apiCall('cmd', 'evac'),
139 train: () => _apiCall('cmd', 'train'),
140 setWeek: (args) => _apiCall('delta', {cleanSchedule: args}),
141 setPreferences: (args) => _apiCall('delta', args),
142 setCarpetBoostAuto: () => _apiCall('delta', {'carpetBoost': true, 'vacHigh': false}),
143 setCarpetBoostPerformance: () => _apiCall('delta', {'carpetBoost': false, 'vacHigh': true}),
144 setCarpetBoostEco: () => _apiCall('delta', {'carpetBoost': false, 'vacHigh': false}),
145 setEdgeCleanOn: () => _apiCall('delta', {'openOnly': false}),
146 setEdgeCleanOff: () => _apiCall('delta', {'openOnly': true}),
147 setCleaningPassesAuto: () => _apiCall('delta', {'noAutoPasses': false, twoPass: false}),
148 setCleaningPassesOne: () => _apiCall('delta', {'noAutoPasses': true, twoPass: false}),
149 setCleaningPassesTwo: () => _apiCall('delta', {'noAutoPasses': true, twoPass: true}),
150 setAlwaysFinishOn: () => _apiCall('delta', {'binPause': false}),
151 setAlwaysFinishOff: () => _apiCall('delta', {'binPause': true})
152 });
153 };
154  
155 module.exports = dorita980;