github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/mappers/modbus_mapper/src/index.js (about) 1 const async = require('async'); 2 const log4js = require('log4js'); 3 const mqtt = require('mqtt'); 4 const path = require('path'); 5 const util = require('util'); 6 7 const common = require('./common'); 8 const constant = require('./constant'); 9 const DeviceTwin = require('./devicetwin'); 10 const Modbus = require('./modbus'); 11 const WatchFiles = require('./watchfile'); 12 13 //default logger options 14 log4js.configure({ 15 appenders: { 16 out: { type: 'stdout' }, 17 }, 18 categories: { 19 default: { appenders: ['out'], level: 'info' } 20 } 21 }); 22 logger = log4js.getLogger('appenders'); 23 24 let options = { 25 port: 1883, 26 host: '127.0.0.1', 27 dpl_name: 'dpl/deviceProfile.json' 28 }; 29 30 let mqtt_client, mqtt_client2, msg, mqtt_options, dt, devIns, devMod, devPro, modVistr; 31 let ActualVal = new Map(); 32 33 async.series([ 34 //load conf.json 35 function(callback) { 36 WatchFiles.loadConfig('conf/conf.json', (err, configs)=>{ 37 if (err) { 38 logger.error('failed to load config, err: ', err); 39 } else { 40 options = { 41 port: configs.mqtt_port, 42 host: configs.mqtt_ip, 43 dpl_name: configs.dpl_name 44 }; 45 callback(err); 46 } 47 }); 48 }, 49 50 //load dpl first time 51 function(callback) { 52 WatchFiles.loadDpl(options.dpl_name, (devInsMap, devModMap, devProMap, modVistrMap)=>{ 53 devIns = devInsMap; 54 devMod = devModMap; 55 devPro = devProMap; 56 modVistr = modVistrMap; 57 callback(); 58 }); 59 }, 60 61 //first get twinget build map 62 function(callback) { 63 mqtt_options = { 64 port: options.port, 65 host: options.host, 66 }; 67 mqtt_client = mqtt.connect(mqtt_options); 68 dt = new DeviceTwin(mqtt_client); 69 mqtt_client.on('connect', ()=>{ 70 logger.info('connetced to edge mqtt with topic twinGet'); 71 mqtt_client.subscribe(constant.twinGetResTopic); 72 for (let instance of devIns) { 73 dt.getActuals(instance[0]); 74 } 75 }); 76 callback(); 77 }, 78 79 //deal with twin get msg and set expected value into device 80 function(callback) { 81 mqtt_client.on('message', (topic, message)=>{ 82 try { 83 var msgGet = JSON.parse(message.toString()); 84 } catch (err) { 85 logger.error('unmarshal error'); 86 return; 87 } 88 let resources = topic.toString().split('/'); 89 let deviceID = resources[3]; 90 let dt = new DeviceTwin(mqtt_client); 91 let devProtocol, devInstance; 92 if (devPro.has(deviceID) && devIns.has(deviceID)) { 93 devProtocol = devPro.get(deviceID); 94 devInstance = devIns.get(deviceID); 95 } else { 96 logger.error('match visitor failed'); 97 } 98 logger.info('recieve twinGet msg, set properties actual value map'); 99 if (resources.length === 7 && resources[5] === 'get' && msgGet != null && msgGet.code != 404 && typeof(devProtocol) != 'undefined' && typeof(devInstance) != 'undefined') { 100 dt.setActuals(msgGet, (PropActuals)=>{ 101 for (let actual of PropActuals) { 102 ActualVal.set(util.format('%s-%s', deviceID, actual[0]), actual[1]); 103 } 104 }); 105 dt.setExpecteds(msgGet, (PropExpecteds)=>{ 106 for (let expected of PropExpecteds) { 107 modbusProtocolTransfer(devProtocol.protocol, (transferedProtocol)=>{ 108 if (modVistr.has(util.format('%s-%s-%s', devInstance.model, expected[0], transferedProtocol))) { 109 let visitor = modVistr.get(util.format('%s-%s-%s', devInstance.model, expected[0], transferedProtocol)); 110 dealDeltaMsg(msgGet, expected[0], visitor, devProtocol, expected[1]); 111 } 112 }); 113 } 114 }); 115 } 116 }); 117 callback(); 118 }, 119 120 // start mqtt sub delta topic 121 function(callback) { 122 mqtt_options = { 123 port: options.port, 124 host: options.host, 125 }; 126 mqtt_client2 = mqtt.connect(mqtt_options); 127 mqtt_client2.on('connect', ()=>{ 128 logger.info('connetced to edge mqtt with topic twinDelta'); 129 mqtt_client2.subscribe(constant.twinDeltaTopic); 130 }); 131 callback(); 132 }, 133 134 // on receive msg of delta topic 135 function(callback) { 136 logger.info('start to wait for devicetwin update'); 137 mqtt_client2.on('message', (topic, message)=>{ 138 try { 139 msg = JSON.parse(message.toString()); 140 } catch (err) { 141 logger.error('unmarshal error'); 142 callback(err); 143 return; 144 } 145 146 //match visitors 147 let resources = topic.toString().split('/'); 148 let deviceID = resources[3]; 149 let devProtocol, devInstance; 150 if (devPro.has(deviceID) && devIns.has(deviceID)) { 151 devProtocol = devPro.get(deviceID); 152 devInstance = devIns.get(deviceID); 153 } else { 154 logger.error('match visitor failed'); 155 } 156 157 try { 158 if (resources.length === 7 && resources[6] === 'delta' && typeof(devProtocol) != 'undefined' && typeof(devInstance) != 'undefined') { 159 logger.info('recieved twinDelta msg'); 160 Object.keys(msg.delta).forEach(function(key){ 161 modbusProtocolTransfer(devProtocol.protocol, (transferedProtocol)=>{ 162 if (modVistr.has(util.format('%s-%s-%s', devInstance.model, key, transferedProtocol))) { 163 let visitor = modVistr.get(util.format('%s-%s-%s', devInstance.model, key, transferedProtocol)); 164 DeviceTwin.syncExpected(msg, key, (value)=>{ 165 dealDeltaMsg(msg, key, visitor, devProtocol, value); 166 }); 167 } 168 }); 169 }); 170 } 171 } catch (err) { 172 logger.error('failed to change devicetwin of device[%s], err: ', deviceID, err); 173 } 174 }); 175 } 176 ],function(err) { 177 if (err) { 178 logger.error(err); 179 } else { 180 logger.info('changed devicetwin successfully'); 181 } 182 }); 183 184 let mqtt_client3; 185 logger.info('start to watch dpl config'); 186 WatchFiles.watchChange(path.join(__dirname, 'dpl'), ()=>{ 187 async.series([ 188 function(callback) { 189 WatchFiles.loadDpl(options.dpl_name, (devInsMap, devModMap, devProMap, modVistrMap)=>{ 190 devIns = devInsMap; 191 devMod = devModMap; 192 devPro = devProMap; 193 modVistr = modVistrMap; 194 callback(); 195 }); 196 }, 197 198 function(callback) { 199 mqtt_options = { 200 port: options.port, 201 host: options.host, 202 }; 203 mqtt_client3 = mqtt.connect(mqtt_options); 204 let dt = new DeviceTwin(mqtt_client3); 205 mqtt_client3.on('connect', ()=>{ 206 logger.info('connetced to edge mqtt with topic twinGet'); 207 mqtt_client.subscribe(constant.twinGetResTopic); 208 for (let instance of devIns) { // let change from var 209 dt.getActuals(instance[0]); 210 } 211 }); 212 callback(); 213 }, 214 215 function(callback) { 216 mqtt_client3.on('message', (topic, message)=>{ 217 try { 218 var msgGet = JSON.parse(message.toString()); 219 } catch (err) { 220 logger.error('unmarshal error'); 221 return; 222 } 223 let resources = topic.toString().split('/'); 224 let deviceID = resources[3]; 225 let devProtocol, devInstance; 226 if (devPro.has(deviceID) && devIns.has(deviceID)) { 227 devProtocol = devPro.get(deviceID); 228 devInstance = devIns.get(deviceID); 229 } else { 230 logger.error('match visitor failed'); 231 } 232 233 let dt = new DeviceTwin(mqtt_client3); 234 if (resources.length === 7 && resources[5] === 'get' && msgGet != null && msgGet.code != 404 && typeof(devProtocol) != 'undefined' && typeof(devInstance) != 'undefined') { 235 logger.info('received twinGet message'); 236 dt.setExpecteds(msgGet, (PropExpecteds)=>{ 237 for (let expected of PropExpecteds) { 238 dt.compareActuals(expected[1], ActualVal.get(util.format('%s-%s', deviceID, expected[0])),(changed)=>{ 239 modbusProtocolTransfer(devProtocol.protocol, (transferedProtocol)=>{ 240 if (changed && modVistr.has(util.format('%s-%s-%s', devInstance.model, expected[0], transferedProtocol))) { 241 let visitor = modVistr.get(util.format('%s-%s-%s', devInstance.model, expected[0], transferedProtocol)); 242 dealDeltaMsg(msgGet, expected[0], visitor, devProtocol, expected[1]); 243 } 244 }); 245 }); 246 } 247 }); 248 } 249 }); 250 callback(); 251 } 252 ],function(err) { 253 if (err) { 254 logger.error('failed to load changed dpl config, err: ', err); 255 } else { 256 logger.info('load changed dpl config successfully'); 257 } 258 }); 259 }); 260 261 logger.info('start to check devicetwin state'); 262 setInterval(()=>{ 263 let dt = new DeviceTwin(mqtt_client); 264 logger.info('chechking devicetwin state'); 265 for (let instance of devIns) { 266 if (devPro.has(instance[0])) { 267 let protocol = devPro.get(instance[0]); 268 let actuals = new Map(); 269 syncDeviceTwin(dt, instance[0], protocol, actuals); 270 } 271 } 272 }, 2000); 273 274 // syncDeviceTwin check each property of each device accroding to the dpl configuration 275 function syncDeviceTwin(dt, key, protocol, actuals) { 276 async.eachSeries(devMod.get(key).properties, (property, callback)=>{ 277 let visitor; 278 if (typeof(protocol) != 'undefined') { 279 modbusProtocolTransfer(protocol.protocol, (transferedProtocol)=>{ 280 if (devIns.has(key) && modVistr.has(util.format('%s-%s-%s', devIns.get(key).model, property.name, transferedProtocol))) { 281 visitor = modVistr.get(util.format('%s-%s-%s', devIns.get(key).model, property.name, transferedProtocol)); 282 } else { 283 logger.error('failed to match visitor'); 284 } 285 }); 286 } 287 if (typeof(protocol) != 'undefined' && typeof(visitor) != 'undefined') { 288 let modbus = new Modbus(protocol, visitor); 289 modbus.ModbusUpdate((err, data)=>{ 290 if (err) { 291 logger.error('failed to update devicetwin[%s] of device[%s], err: ', property.name, key, err); 292 } else { 293 dt.transferType(visitor, property, data, (transData)=>{ 294 if (transData != null) { 295 actuals.set(property.name, String(transData)); 296 dt.dealUpdate(transData, property, key, ActualVal); 297 } 298 }); 299 callback(); 300 } 301 }); 302 } 303 },()=>{ 304 dt.UpdateDirectActuals(devIns, key, actuals); 305 }); 306 } 307 308 // dealDeltaMsg deal with the devicetwin delta msg 309 function dealDeltaMsg(msg, key, visitor, protocol, value) { 310 let modbus = new Modbus(protocol, visitor); 311 modbus.ModbusDelta(msg.twin[key].metadata.type, value, (err, data)=>{ 312 if (err) { 313 logger.error('failed to modify register, err: ', err) 314 } else { 315 logger.info('modify register %s successfully', JSON.stringify(data)); 316 } 317 }) 318 } 319 320 function modbusProtocolTransfer(protocol, callback) { 321 let transferedProtocol; 322 if (protocol === 'modbus-rtu' || protocol === 'modbus-tcp') { 323 transferedProtocol = 'modbus'; 324 } else { 325 transferedProtocol = protocol; 326 } 327 callback(transferedProtocol) 328 }