ibctminer
Version:
```js const IntMiner = require('./src'); const Debug = require('./src/log')(); const fs = require('fs'); const COMP = '[SIPC]';
830 lines (748 loc) • 29.3 kB
JavaScript
const Delimiter = require('@serialport/parser-delimiter');
const Debug = require('../log')();
var SerialPort = require('serialport');
//const minerconfig = require('./config/minerconfig')
const EventEmitter = require('events');
var waitUntil = require('wait-until');
var crc32 = require('crc32');
const COMP = '[SN]';
const hwTarget = Buffer.from([0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
const PV = 0x10;
const PV20 = 0x20;
const TypeSetBootMode = 0xA3;
const TypeUpdateFW = 0xAA;
const TypeQueryInfo = 0xA4;
const TypeProductTest = 0xAB;
const TypeSetLED = 0xA6;
const TypeSendWork = 0xA1;
const TypeSetHWParams = 0xA2;
const TypeReboot = 0xAC;
const TypeRecvNonce = 0x51;
const TypeRecvState = 0X52;
const TypeRecvBootMode = 0x53;
const TypeRecvInfo = 0x54;
const TypeRecvFWState = 0x5A;
const TypeRecvTestResult = 0x5B;
const pktHeader = Buffer.from([0xA5, 0x3C, 0x96]);
const pktEnder = Buffer.from([0x69, 0xC3, 0x5A]);
const typeOffset = 0;
const sncfg = {
model: "simplenode",
algo: "scrypt",
varity: 0x30,
targetFreq: 700, //MHz
targetVoltage: 750, //mv
targetTemp: 65,
warnTemp: 115,
offTemp: 125
};
function version_compare(version1, version2)
{
let v1 = version1.split('.');
let v2 = version2.split('.');
let r0 = parseInt(v1[0]);
let r1 = parseInt(v1[1]);
let r2 = parseInt(v1[2]);
let s = r0 * 100 + r1 * 10 + r2;
r0 = parseInt(v2[0]);
r1 = parseInt(v2[1]);
r2 = parseInt(v2[2]);
let d = r0 * 100 + r1 * 10 + r2;
if (s === d)
return 0;
else if (s < d)
return 1;
else
return 2;
}
class simplenode extends EventEmitter {
constructor({devPath, algo, varity}) {
super();
var _this = this;
_this.algo = algo;
_this.devPath = devPath;
_this.MinerShouldStop = false;
_this.inited = false;
_this.txTimeoutCnt = 0;
_this.work = {
jobID: 0,
target: 0,
snonce: 0
};
_this.info = {
firmwareVer: 'V0.0.1',
modelName: 'simplenode',
sn:'unknown',
hashRation: 0
};
_this.firmware = {
retryCnt : 2,
FWPageSize : 512,
curState : 0,
curID : 0
}
_this.submitNonce = null;
_this.jobsDone = 0;
_this.status = {
chips:0,
temp:0,
voltage:0,
freq:0,
varity:0x30,
cores:0,
goodcores:0,
scanbits:0,
scantime:0,
tempwarn:0
};
_this.port = new SerialPort(_this.devPath, {
baudRate: 115200,
dataBits:8,
stopBits:1,
parity:'none',
rtscts:false
}, function (err) {
if (err) {
// _this.emit("error", "打开串口失败");
Debug.IbctLogErr('[SN]:',_this.devPath, '打开串口失败: ', err.message);
return;
}
});
Debug.IbctLogErr('[SN]:',_this.devPath, '打开串口成功 ');
const parser = _this.port.pipe(new Delimiter({ delimiter: pktEnder}));
parser.on('data', function(data) {
_this.snParseNotify(_this, data);
});
_this.on("error", function(err) {
Debug.IbctLogDbg(COMP, err);
})
_this.on("warning", function(err) {
Debug.IbctLogDbg(COMP, err);
})
}
snParseNotify(_this, data) {
//Debug.IbctLogInfo('[SN]:',_this.devPath, 'Recv Pkt', data.toString('hex'));
var location = data.indexOf(pktHeader);
if(location === -1) {
Debug.IbctLogErr('[SN]:',_this.devPath, 'Recv Invalid PKT', data);
return;
}
var typeLocation = location + pktHeader.length + typeOffset;
switch(data[typeLocation]) {
case TypeRecvNonce:
var jobID = data[9];
//var chipID = data[10];
//var coreID = data[11];
var lowNonce = data.readUInt32LE(12); //nonce
var nonce = Buffer.alloc(8);
nonce.writeUInt32BE(_this.work.highNonce, 0);
nonce.writeUInt32BE(lowNonce, 4);
if(jobID !== _this.work.jobID) {
Debug.IbctLogDbg('[SN]:',_this.devPath, 'Find Stale ', jobID, _this.work.jobID, nonce.toString('hex'));
} else {
// nonce.copy(_this.work.data, 72);
//Debug.IbctLogDbg('[SN]:',_this.devPath, 'Find Nonce ', nonce.toString('hex'));
//Debug.IbctLogDbg('[SimpleNode]:','Work Data', _this.work.data.toString('hex'));
//var result = myalgo.genHash(_this.work.data, 80, 0x30);
//Debug.IbctLogInfo('[SimpleNode]:','result', result.toString(16));
if(_this.submitNonce)
_this.submitNonce(null, nonce);
}
break;
case TypeRecvInfo:
_this.recvInfoPkt = true;
//Debug.IbctLogDbg('[SN]:',_this.devPath, 'RecvInfoPkt::', data.toString('hex'));
_this.info.modelName = data.toString('utf8', 10, 10 + data[9]);
_this.info.firmwareVer = data.toString('utf8', 27, 27 + data[26]);
_this.info.sn = data.toString('utf8', 36, 36 + data[35]);
_this.info.hashRation = data.readUInt16LE(69);
Debug.IbctLogDbg(_this.info);
break;
case TypeRecvFWState:
_this.recvFWStatePkt = true;
_this.firmware.curID = data.readUInt32LE(9);
_this.firmware.curState = data[13];
break;
case TypeRecvBootMode:
_this.recvBootModePkt = true;
break;
case TypeRecvState:
_this.recvStatePkt = true;
_this.recvQueryStatePkt = true;
//Debug.IbctLogInfo('[SN]:',_this.devPath, 'RecvState pkt::', data.toString('hex'));
_this.status.chips = data[9];
_this.status.cores = data[10];
_this.status.goodcores = data[11];
_this.status.scanbits = data[12];
_this.status.scantime = data.readUInt16LE(13) * 100; //ms
_this.status.voltage = data.readUInt16LE(15); //mV
_this.status.freq = data.readUInt16LE(17); //MHz
_this.status.varity = data.readUInt32LE(19);
_this.status.temp = data[23];
_this.status.hwreboot = data[24];
if (data[typeLocation+1] === PV20)
_this.status.tempwarn = data[25];
else
_this.status.tempwarn = 0;
break;
case TypeRecvTestResult:
_this.recvPTInfoPkt = true;
break;
default:
Debug.IbctLogErr('[SN]:',_this.devPath, 'Recv Unsupported PKT Type', data[location + typeOffset])
break;
}
return;
}
snSendPkt (pkt) {
var _this = this;
var offset = 0;
var length = 0;
Object.keys(pkt).forEach(function(key) {
if(Buffer.isBuffer(pkt[key])) {
length += pkt[key].length;
}
});
var msg = Buffer.alloc(length);
Object.keys(pkt).forEach(function(key) {
if(Buffer.isBuffer(pkt[key])) {
pkt[key].copy(msg, offset);
offset += pkt[key].length;
}
});
// Debug.IbctLogDbg('[SN]:',_this.devPath, 'Send pkt', msg.toString('hex'));
_this.port.write(msg, function(err) {
if (err) {
Debug.IbctLogErr('[SN]:', _this.devPath, 'Error on write: ', err.message)
}
_this.port.drain(function(err) {
if (err) {
Debug.IbctLogErr('[SN]:', _this.devPath, 'Error on Drain: ', _this.devPath, err.message)
}
})
})
}
snGetState(_this) {
var pktQueryStatus = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSetHWParams]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x7, 0x0 ,0x0 ,0x0]),
flag:Buffer.from([0x52]),
ender:Buffer.from(pktEnder)
};
_this.recvQueryStatePkt = false;
_this.snSendPkt(pktQueryStatus);
/*TODO Wait response here*/
return true;
}
async snGetStaticInfo(modelName) {
var _this = this;
var pktQueryInfo = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeQueryInfo]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x6, 0x0 ,0x0 ,0x0]),
ender:Buffer.from(pktEnder)
};
_this.recvInfoPkt = false;
_this.snSendPkt(pktQueryInfo);
return new Promise(function (resolve, reject) {
waitUntil()
.interval(50)
.times(10)
.condition(function() {
return _this.recvInfoPkt
})
.done(function(result) {
if(result === false) {
Debug.IbctLogErr('[SN]:',_this.devPath, '获取矿机信息出错');
resolve(1);
} else {
if(modelName === _this.info.modelName) {
resolve(0);
} else {
resolve(1);
}
}
})
});
}
snSetBootMode() {
var _this = this;
var pktSetBootMode = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSetBootMode]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x7, 0x0 ,0x0 ,0x0]),
ender:Buffer.from(pktEnder)
};
_this.recvBootModePkt = false;
_this.snSendPkt(pktSetBootMode);
}
snBurnFWInit() {
var _this = this;
var pktSetBootMode = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSetBootMode]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x6, 0x0 ,0x0 ,0x0]),
ender:Buffer.from(pktEnder)
};
_this.recvBootModePkt = false;
_this.snSendPkt(pktSetBootMode);
return new Promise(function (resolve, reject) {
waitUntil()
.interval(20)
.times(50)
.condition(function() {
return _this.recvBootModePkt
})
.done(function(result) {
if(result === false) {
resolve(1);
} else {
resolve(0);
}
})
})
}
snSetHWParams(varity, freq, voltage) {
var _this = this;
var pktSetParam = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSetHWParams]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x10, 0x00, 0x00, 0x00]),
flag:Buffer.from([0xA2]),
voltage: Buffer.alloc(2),
freq:Buffer.alloc(2),
varity:Buffer.alloc(4),
targettemp:Buffer.from([80]),
ender:Buffer.from(pktEnder)
};
pktSetParam.varity.writeUInt32LE(varity, 0);
pktSetParam.freq.writeUInt16LE(freq, 0);
pktSetParam.voltage.writeUInt16LE(voltage, 0);
_this.recvStatePkt = false;
_this.snSendPkt(pktSetParam);
/*TODO Wait response here*/
return true;
}
snSetHWParamsAndWait(varity, freq, voltage) {
var _this = this;
var pktSetParam = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSetHWParams]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x10, 0x00, 0x00, 0x00]),
flag:Buffer.from([0xA2]),
voltage: Buffer.alloc(2),
freq:Buffer.alloc(2),
varity:Buffer.alloc(4),
targettemp:Buffer.from([80]),
ender:Buffer.from(pktEnder)
};
pktSetParam.varity.writeUInt32LE(varity, 0);
pktSetParam.freq.writeUInt16LE(freq, 0);
pktSetParam.voltage.writeUInt16LE(voltage, 0);
_this.recvStatePkt = false;
_this.snSendPkt(pktSetParam);
return new Promise(function (resolve, reject) {
waitUntil()
.interval(20)
.times(50)
.condition(function() {
return _this.recvStatePkt
})
.done(function(result) {
if(result === false) {
Debug.IbctLogErr('[SN]:',_this.devPath, '设置矿机参数出错');
resolve(1);
} else {
resolve(0);
}
})
})
}
async snWriteJob(jobID, target, data) {
var _this = this;
var pktSendJob = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSendWork]),
version: Buffer.from([PV]),
pktlen: Buffer.alloc(4),
target:Buffer.alloc(4),
startNonce: Buffer.from([0,0,0,0,0,0,0,0]),
endNonce:Buffer.from([0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff]),
jobNum: Buffer.from([1]),
jobID: Buffer.alloc(1),
jobData:Buffer.alloc(80),
ender:Buffer.from(pktEnder)
};
pktSendJob.pktlen.writeUInt32LE(108, 0); //pktlen
pktSendJob.target.writeUInt32LE(target, 0);
//pktSendJob.startNonce.writeUInt32LE(0, 0);
//pktSendJob.startNonce.writeUInt32LE(0, 4);
//pktSendJob.endNonce.writeUInt32LE(0xffffffff, 0);
//pktSendJob.endNonce.writeUInt32LE(0xffffffff, 4);
pktSendJob.jobID[0] = jobID;
data.copy(pktSendJob.jobData, 0);
_this.snSendPkt(pktSendJob);
return true;
}
snSendFWPktAndWait(cnt, FWPKT) {
var _this = this;
_this.recvFWStatePkt = false;
_this.firmware.curState = 0;
_this.firmware.curID = 0;
_this.snSendPkt(FWPKT);
return new Promise(function (resolve, reject) {
waitUntil()
.interval(20)
.times(50)
.condition(function() {
return _this.recvFWStatePkt
})
.done(function(result) {
if(result === false) {
reject(new Error(__('烧录连接超时')));
} else if(_this.firmware.curState === 0x02) {
if(cnt < _this.firmware.retryCnt){
resolve(1);
} else {
reject(new Error(__('串口出错')));
}
} else {
resolve(0);
}
})
})
}
async stopScanWork() {
var _this = this;
Debug.IbctLogInfo('[SN]:', _this.devPath, 'stopScanWork ...');
_this.work.jobID = 0;
_this.MinerShouldStop = true;
}
async scanWork(Job, callback) {
var _this = this;
Debug.IbctLogInfo('[SN]:', _this.devPath, 'scanWork Begin ...');
if (!_this.inited) {
callback(null, null);
return;
}
if(_this.status.scantime === 0) {
_this.status.scantime = 300000; //10s default
}
if(Buffer.compare(hwTarget, Job.target) > 0) {
for(var i = 0; hwTarget[i]===0; i++);
_this.work.target = (i<<24) | (hwTarget[i] << 16) | (hwTarget[i + 1] << 8) | hwTarget[i + 2];
Job.hwTarget = hwTarget;
} else {
for(var i = 0; Job.target[i]===0; i++);
_this.work.target = (i<<24) | (Job.target[i] << 16) | (Job.target[i + 1] << 8) | Job.target[i + 2];
Job.hwTarget =Job.target;
}
_this.work.highNonce = parseInt((Job.snonce) / 0x100000000) >>> 0;
_this.work.payload = Buffer.alloc(80);
_this.work.data = Buffer.from(Job.data);
Job.data.writeUInt32BE( _this.work.highNonce, 72);
var part1 = Buffer.alloc(32);
var part2 = Buffer.alloc(32);
var part3 = Buffer.alloc(16);
Job.data.copy(part1, 0, 0, 32);
Job.data.copy(part2, 0, 32, 64);
Job.data.copy(part3, 0, 64, 80);
var part11 = Buffer.from(part1);
var part22 = Buffer.from(part2);
var part33 = Buffer.from(part3);
for(var i = 0; i < 8; i++){
part1.writeUInt32LE(part11.readUInt32LE((7- i) *4), i * 4);
part2.writeUInt32LE(part22.readUInt32LE((7- i) *4), i * 4);
}
for(var i = 0; i < 4; i++){
part3.writeUInt32LE(part33.readUInt32LE((3- i) *4), i * 4);
}
part1.copy(_this.work.payload, 0);
part2.copy(_this.work.payload, 32);
part3.copy(_this.work.payload, 64);
_this.submitNonce = callback;
_this.MinerShouldStop = false;
_this.jobsDone++;
_this.work.jobID++;
if(_this.work.jobID === 16) _this.work.jobID = 1;
/*
Debug.IbctLogInfo('[SN]:', _this.devPath, 'Work Target:', _this.work.target.toString(16),
'Work highNonce:', _this.work.highNonce.toString(16),
'Work jobID:', _this.work.jobID);
*/
_this.snWriteJob(_this.work.jobID, _this.work.target, _this.work.payload);
var interval = 50; //ms
var times = (60000 - 500) / interval;
waitUntil()
.interval(interval)
.times(times)
.condition(function() {
return _this.MinerShouldStop
})
.done(function(result) {
Debug.IbctLogInfo('[SN]:', _this.devPath, 'ScanWork Exit', result ? "(NewJob)...": "(ScanTime Out)...");
callback(null, null);
});
}
async setDevice(varity, freq, voltage) {
var _this = this;
_this.snSetHWParams(varity, freq, voltage);
}
getInfo() {
var _this = this;
return _this.info;
}
getState() {
var _this = this;
return _this.status;
}
async detect(modelName) {
var _this = this;
Debug.IbctLogErr('[SN]:', _this.devPath, 'simpleNode detect...');
return await _this.snGetStaticInfo(modelName);
}
async init(params) {
var _this = this;
Debug.IbctLogErr('[SN]:', _this.devPath, 'simpleNode init...');
if(_this.firmware.updating === true){
Debug.IbctLogErr('[SN]:',_this.devPath, 'Still Updating');
return 1;
}
if( _this.inited === true){
Debug.IbctLogErr('[SN]:',_this.devPath, 'Already Inited. return now');
return 0;
}
//_this.snSetHWParams(sncfg.varity, sncfg.targetFreq, sncfg.targetVoltage);
var ret = await _this.snSetHWParamsAndWait(sncfg.varity, sncfg.targetFreq, sncfg.targetVoltage);
if (ret)
return ret;
if (_this.intervalObj) {
clearInterval(_this.intervalObj);
_this.intervalObj = null;
}
_this.intervalObj = setInterval(function() {
Debug.IbctLogErr('[SN]:',_this.devPath, 'Temp', _this.status.temp, 'Tempwarn', _this.status.tempwarn, 'Freq', _this.status.freq, 'Jobs', _this.jobsDone);
_this.snGetState(_this);
waitUntil()
.interval(50)
.times(10)
.condition(function() {
return _this.recvQueryStatePkt
})
.done(function(result) {
if(result === false) {
_this.txTimeoutCnt++;
Debug.IbctLogErr('[SN]:',_this.devPath, 'snGetState Timeout ', _this.txTimeoutCnt);
if(_this.txTimeoutCnt > 10) {
_this.emit("error", __('获得矿机状态超时'));
_this.txTimeoutCnt = 0;
}
} else {
_this.txTimeoutCnt = 0;
if((_this.status.temp > sncfg.offTemp) || (_this.status.tempwarn)) {
_this.emit("error", __('矿机高温关机'));
} else if(_this.status.temp > sncfg.warnTemp && _this.status.temp < sncfg.offTemp) {
_this.emit("warning", __('矿机高温警报'));
}
}
});
}, 5000);
_this.inited = true;
return 0;
}
async stop(enable) {
var _this = this;
Debug.IbctLogErr('[SN]:', _this.devPath, 'simpleNode', enable ? 'remove...' : 'stop...');
if (!enable) {
await _this.snSetHWParamsAndWait(0, 0, 0);
}
_this.inited = false;
_this.txTimeoutCnt = 0;
_this.freq = 0;
_this.voltage = 0;
_this.work.jobID = 0;
_this.jobsDone = 0;
_this.MinerShouldStop = true;
if (_this.intervalObj) {
clearInterval(_this.intervalObj);
_this.intervalObj = null;
}
if (enable) {
await _this.port.flush(function (err) {
_this.port.close(function(err) {
if(err)
Debug.IbctLogDbg('[SN]:',err.message);
});
});
}
}
async burnFirmware(firmware, callback) {
var _this = this;
if(_this.firmware.updating === true) {
callback(__('升级中,请等待'));
return;
}
if(_this.inited === true) {
callback(__('挖矿中,请先暂停挖矿'));
return;
}
var ret = await _this.snGetStaticInfo(_this.info.modelName);
if (ret === 1) {
callback(__('无法获取当前版本号'));
return;
}
ret = version_compare(_this.info.firmwareVer, '0.0.7');
if (ret === 1)
_this.firmware.FWPageSize = 512;
else
_this.firmware.FWPageSize = 256;
var init = await _this.snBurnFWInit();
if(init === 0) {
_this.firmware.updating = true;
} else {
_this.firmware.updating = false;
callback(__('烧入固件初始化失败'));
return;
}
var fwLen = firmware.length;
var totalPktNum = Math.ceil(firmware.length / _this.firmware.FWPageSize)
var id = 0;
Debug.IbctLogErr('[SN]:', _this.devPath, 'BurnFW, CurVersion:', _this.info.firmwareVer, 'FW lenth' , fwLen , "PKTnum", totalPktNum);
try {
while(fwLen > 0) {
var currentLen = (fwLen > _this.firmware.FWPageSize) ? _this.firmware.FWPageSize : fwLen;
var curStart = firmware.length - fwLen;
var curEnd = curStart + currentLen;
var pktUpdateFW = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeUpdateFW]),
version: Buffer.from([PV]),
pktLen: Buffer.alloc(4),
pktID:Buffer.alloc(4),
pageSize:Buffer.alloc(4),
curLen:Buffer.alloc(4),
flag:Buffer.alloc(1),
crc32: Buffer.alloc(4),
fwData:Buffer.alloc(currentLen),
ender:Buffer.from(pktEnder)
};
pktUpdateFW.curLen.writeUInt32LE(currentLen, 0);
pktUpdateFW.pktID.writeUInt32LE(id, 0);
pktUpdateFW.pageSize.writeUInt32LE(_this.firmware.FWPageSize, 0);
pktUpdateFW.pktLen.writeUInt32LE(23 + currentLen);
firmware.copy(pktUpdateFW.fwData, 0, curStart, curEnd);
fwLen -= currentLen;
if(fwLen) {
pktUpdateFW.flag[0] = 0x00;
} else {
pktUpdateFW.flag[0] = 0x01;//last
}
var msg = Buffer.alloc(23 + currentLen);
//console.log('3====>', curStart, curEnd, currentLen, fwLen);
pktUpdateFW.type.copy(msg, 0);
pktUpdateFW.version.copy(msg, 1);
pktUpdateFW.pktLen.copy(msg, 2);
pktUpdateFW.pktID.copy(msg, 6);
pktUpdateFW.pageSize.copy(msg, 10);
pktUpdateFW.curLen.copy(msg, 14);
pktUpdateFW.flag.copy(msg, 18);
pktUpdateFW.crc32.copy(msg, 19);
pktUpdateFW.fwData.copy(msg, 23);
var crcValue = parseInt(crc32(msg), 16);
pktUpdateFW.crc32.writeUInt32LE(crcValue, 0);
for(var i = 0; i < _this.firmware.retryCnt; i++) {
var success = await _this.snSendFWPktAndWait(i + 1, pktUpdateFW);
if(success === 0)
break;
}
if(fwLen === 0) {
_this.firmware.updating = false;
}
callback(null, ((id + 1) / totalPktNum).toFixed(3));
id++;
}
}
catch(err) {
Debug.IbctLogErr('[SN]:', _this.devPath, 'Updat firmware failed ' + err.message);
_this.firmware.updating = false;
callback(err.message);
}
}
async rebootDev() {
Debug.IbctLogErr('[SN]: Set', this.devPath, 'reboot');
var _this = this;
var pktReboot = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeReboot]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0x6, 0x0 ,0x0 ,0x0]),
ender:Buffer.from(pktEnder)
};
await _this.stop(true)
_this.snSendPkt(pktReboot);
}
setLed(Enable) {
Debug.IbctLogErr('[SN]: Set', this.devPath, 'Led to', Enable ? 'ON' : 'OFF');
var _this = this;
var ledFlag = Enable === true ? 1 : 0;
var pktSetLED = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeSetLED]),
version: Buffer.from([PV]),
pktlen: Buffer.from([0xb, 0x0 ,0x0 ,0x0]),
Flag:Buffer.from([ledFlag]),
led:Buffer.from([0xE8, 0x3, 0xC8, 0x0]), //ON 1s OFF:200ms
ender:Buffer.from(pktEnder)
};
_this.snSendPkt(pktSetLED);
}
async burnSNInfo(ptinfo) {
var _this = this
Debug.IbctLogErr('[SN]', _this.devPath, 'Burn Sn Num..', ptinfo)
var pktPTInfo = {
header: Buffer.from(pktHeader),
type: Buffer.from([TypeProductTest]),
version: Buffer.from([PV]),
pktlen: Buffer.from([70, 0x0, 0x0, 0x0]),
SNInfo: Buffer.alloc(32),
HashInfo: Buffer.alloc(32),
ender: Buffer.from(pktEnder)
}
if (ptinfo.sn) {
var sn = Buffer.from(ptinfo.sn)
pktPTInfo.SNInfo[0] = sn.length
sn.copy(pktPTInfo.SNInfo, 1)
} else {
pktPTInfo.SNInfo[0] = 0
}
_this.recvPTInfoPkt = false;
_this.snSendPkt(pktPTInfo)
return new Promise(function (resolve, reject) {
waitUntil()
.interval(50)
.times(10)
.condition(function () {
return _this.recvPTInfoPkt
})
.done(function (result) {
if (result === false) {
Debug.IbctLogErr('[SN]:', _this.devPath, 'Burn SN num failed..')
resolve(__('写入SN序列号失败'))
} else {
resolve(null)
}
})
})
}
}
module.exports = function getSimplenode(options = {}) {
return new simplenode(options);
}