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  }