github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/mappers/modbus_mapper/src/modbus.js (about) 1 const ModbusRTU = require('modbus-serial'); 2 const Buffer = require('buffer').Buffer; 3 const async = require('async'); 4 const common = require('./common'); 5 6 class Modbus { 7 constructor(protocol, visitor){ 8 this.protocol = protocol; 9 this.visitor = visitor; 10 this.client = new ModbusRTU(); 11 } 12 13 // connect to device with modbus protocol 14 connect(callback) { 15 let protocol = this.protocol; 16 let client = this.client; 17 switch(protocol.protocol) { 18 case 'modbus-tcp': 19 client.connectTCP(protocol.protocol_config.ip, { port: parseInt(protocol.protocol_config.port) }, ()=>{ 20 client.setTimeout(500); 21 client.setID(parseInt(protocol.protocol_config.slaveID)); 22 callback(client); 23 }); 24 break; 25 case 'modbus-rtu': 26 async.series([ 27 function(callback) { 28 setTimeout(function () { 29 callback(null, null); 30 }, 100); 31 }, 32 function (callback) { 33 client.connectRTUBuffered(protocol.protocol_config.serialPort, { baudRate: parseInt(protocol.protocol_config.baudRate) }, ()=>{ 34 client.setTimeout(500); 35 client.setID(parseInt(protocol.protocol_config.slaveID)); 36 callback(null, client); 37 }); 38 }], (err, res) => {callback(res[1]); 39 }); 40 break; 41 default: 42 logger.info('unknwon modbus_type ', protocol.protocol); 43 break; 44 } 45 } 46 47 // WriteAction write the value into device registers 48 WriteAction(value, callback) { 49 let visitor = this.visitor; 50 let client = this.client; 51 switch(visitor.visitorConfig.register){ 52 case 'CoilRegister': 53 client.writeCoils(parseInt(visitor.visitorConfig.index), value, (err, data)=>{ 54 client.close(); 55 callback(err, data); 56 }); 57 break; 58 case 'HoldingRegister': 59 client.writeRegisters(parseInt(visitor.visitorConfig.index), value, (err, data)=>{ 60 client.close(); 61 callback(err, data); 62 }); 63 break; 64 default: 65 client.close(); 66 logger.info('write action is not allowed on register type ', visitor.visitorConfig.register) 67 callback('unkown action', null); 68 break; 69 } 70 } 71 72 // PreWriteAction transfer data before writing data to register 73 PreWriteAction(type, value, callback) { 74 let visitor = this.visitor; 75 let transData; 76 async.waterfall([ 77 function(callback) { 78 switch(type) { 79 case 'int': 80 case 'float': 81 value = parseInt(value); 82 if (visitor.visitorConfig.register === 'CoilRegister') { 83 transData = (value).toString(2).split('').map(function(s) { return parseInt(s); }); 84 } else if (visitor.visitorConfig.register === 'HoldingRegister') { 85 common.IntToByteArray(value, (byteArr)=>{ 86 if (byteArr.length < visitor.visitorConfig.offset) { 87 let zeroArr = new Array(visitor.visitorConfig.offset -byteArr.length).fill(0); 88 byteArr = zeroArr.concat(byteArr); 89 transData = byteArr; 90 } else { 91 transData = byteArr; 92 } 93 }); 94 } else { 95 transData = null; 96 } 97 callback(null, transData); 98 break; 99 case 'string': { 100 let buf = new Buffer.from(value); 101 transData = buf.toJSON().data; 102 callback(null, transData); 103 break; 104 } 105 case 'boolean': 106 if (value === 'true') { 107 transData = [1]; 108 } else if (value === 'false') { 109 transData = [0]; 110 } else { 111 transData = null; 112 } 113 callback(null, transData); 114 break; 115 default: 116 transData = null; 117 callback(null, transData); 118 break; 119 } 120 }, 121 function(transData, callback) { 122 if (visitor.visitorConfig.isRegisterSwap && transData != null) { 123 common.switchRegister(transData, (switchedData)=>{ 124 callback(null, switchedData); 125 }); 126 } else { 127 callback(null, transData); 128 } 129 }, 130 function(internalData, callback) { 131 if (visitor.visitorConfig.isSwap && internalData != null && (visitor.visitorConfig.register === 'HoldingRegisters' || visitor.visitorConfig.register === 'CoilsRegisters')) { 132 common.switchByte(internalData, (switchedData)=>{ 133 callback(null, switchedData); 134 }); 135 } else { 136 callback(null, internalData); 137 } 138 }], function(err, transData) { 139 callback(transData); 140 } 141 ); 142 } 143 144 // ReadAction read register data from device 145 ReadAction(callback) { 146 let visitor = this.visitor; 147 let client = this.client; 148 switch (visitor.visitorConfig.register) { 149 case 'CoilRegister': 150 client.readCoils(parseInt(visitor.visitorConfig.index), parseInt(visitor.visitorConfig.offset), (err, data)=>{ 151 client.close(); 152 callback(err, err?data:[data.data[0]]); 153 }); 154 break; 155 case 'DiscreteInputRegister': 156 client.readDiscreteInputs(parseInt(visitor.visitorConfig.index), parseInt(visitor.visitorConfig.offset), (err, data)=>{ 157 client.close(); 158 callback(err, err?data:[data.data[0]]); 159 }); 160 break; 161 case 'HoldingRegister': 162 client.readHoldingRegisters(parseInt(visitor.visitorConfig.index), parseInt(visitor.visitorConfig.offset), (err, data)=>{ 163 client.close(); 164 callback(err, err?data:data.data); 165 }); 166 break; 167 case 'InputRegister': 168 client.readInputRegisters(parseInt(visitor.visitorConfig.index), parseInt(visitor.visitorConfig.offset), (err, data)=>{ 169 client.close(); 170 callback(err, err?data:data.data); 171 }); 172 break; 173 default: 174 client.close(); 175 logger.info('read action is not allowed on register type ', visitor.visitorConfig.register) 176 callback('unknown Registers type', null); 177 break; 178 } 179 } 180 181 // ModbusDelta deal with the delta message to modify the register 182 ModbusDelta(type, value, callback) { 183 this.connect(()=>{ 184 this.PreWriteAction(type, value, (transData)=>{ 185 if (transData != null) { 186 this.WriteAction(transData, (err, data)=>{ 187 callback(err, data); 188 }); 189 } 190 }); 191 }); 192 } 193 194 // ModbusUpdate deal with the update message to read the register 195 ModbusUpdate(callback) { 196 this.connect(()=>{ 197 this.ReadAction((err, data)=>{ 198 callback(err, data); 199 }); 200 }); 201 } 202 } 203 204 module.exports = Modbus;