// 使用ws模块 const { monitorEventLoopDelay } = require('perf_hooks'); const WebSocket = require('ws'); // npm i stickpackage // npm i ws var ws = new WebSocket("ws://jiangyi.site:11111/"); let stringsArray = [ // 获取(可批量) "get:heart_beat=?;time=?;version=?;work_status=?;fire_status=?;fault_status=?", "get:humidity=?;temperature=?;cur_photosen0=?;photosen0=?", "get:net=?;event_num=?;warning_num=?", // 设置(可批量) // "set:extra_time=180;standing_time=10;interval_time=600", // "set:photosen0=6000,6000,6000,6000", // "set:net=WIFI24,12345678,qq.com,1883,user,123456;event_num=1000;warning_num=1000", // 操作(单独) // "set:time=1727107200", // "set:reset=1", // "set:erase_bit=7", ]; let strings_i = 0; function bin2String(array) { return String.fromCharCode.apply(String, array); } function calculateChecksum16bit(code) { let sum = 0; for (let i = 0; i < code.length; i++) { sum += (code[i])&0xff; // console.log("sum:"+ sum +",i:"+ code[i] ); } // 将结果转换为16位二进制字符串 return sum&0xffff; } function bufferToHex (buffer) { return [...new Uint8Array (buffer)] .map (b => b.toString (16).padStart (2, "0")) .join (" "); } function stringToByteArray(str) { const encoder = new TextEncoder(); // 创建TextEncoder实例 const bytes = encoder.encode(str); // 将字符串转换为字节序列 return bytes; // 返回字节数组 } //小端模式 function BytesToIntLittleEndian(bytes){ var val = 0; for (var i = bytes.length - 1; i >= 0; i--) { val += bytes[i]; if (i != 0) { val = val << 8; } } return val; } //小端模式 //number 要转换的整形数值 //length 要转成什么byte数组,规定数组的长度 //如uint16,则lenght=2表示两个字节,转成的byte数组长度是length=2 //如uint32,则lenght=2表示两个字节,转成的byte数组长度是length=4 function IntToBytesLittleEndian(number, length){ var bytes = []; var i = 0; do { bytes[i++] = number & (255); number = number>>8; } while ( i < length ) return bytes; } //大端模式 function BytesToIntBigEndian(bytes){ var val = 0; for (var i = 0; i < bytes.length; ++i) { val += bytes[i]; if (i < bytes.length-1) { val = val << 8; } } return val; } //大端模式 //number 要转换的整形数值 //length 要转成什么byte数组,规定数组的长度 //如uint16,则lenght=2表示两个字节,转成的byte数组长度是length=2 //如uint32,则lenght=2表示两个字节,转成的byte数组长度是length=4 function IntToBytesBigEndian(number, length){ var bytes = []; var i = length; do { bytes[--i] = number & (255); number = number>>8; } while (i) return bytes; } function Uint8ArrayToString(fileData){ var dataString = ""; for (var i = 0; i < fileData.length; i++) { dataString += String.fromCharCode(fileData[i]); } return dataString } function stringToUint8Array(str){ var arr = []; for (var i = 0, j = str.length; i < j; ++i) { arr.push(str.charCodeAt(i)); } var tmpUint8Array = new Uint8Array(arr); return tmpUint8Array } function intToHex(number, minLength) { return number.toString(16).padStart(minLength, '0'); } function hexToString(hex) { var string = ''; for (var i = 0; i < hex.length; i += 2) { string += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); } return string; } // 封包 function pack_send(str) { console.log("封包前:"+str); body = str; let data_len = body.length & 0xffff; let data_check = calculateChecksum16bit(stringToByteArray(body)) & 0xffff; // console.log("len:"+intToHex(data_len,4)); // console.log("check:"+intToHex(data_check,4)); const headBuf = Buffer.from([0x59, 0x4c, 0x3c, (data_len>>8)&0xff, (data_len)&0xff, (data_check>>8)&0xff, (data_check)&0xff]); const bodyBuf = Buffer.from(body); let pack_date = Buffer.concat([headBuf, bodyBuf]); ws.send(pack_date); // console.log("headBuf:"+bufferToHex(headBuf)); // console.log("bodyBuf:"+bufferToHex(bodyBuf)); console.log("封包后:"+bufferToHex(pack_date)); } function handler_recv(out){ console.log("解析:" + out); str = String(out); let arr = str.split("="); if(arr.length == 2){ let key = arr[0] let val = arr[1] if(key == "heart_beat"){ let arr2 = val.split(","); if(arr2.length == 6){ year = arr2[0]; mon = arr2[1]; day = arr2[2]; hour = arr2[3]; min = arr2[4]; sec = arr2[5]; console.log("heart_beat:20"+year+"-"+mon+"-"+day+" "+hour+":"+min+":"+sec); } } } } // 解包 let RecvBuf = ""; function unpack_recv(data) { datArray = stringToByteArray(data); console.log("接收 " + data.length +": "+ bufferToHex(datArray)); // data添加到全局RecvBuf if(RecvBuf == ""){ RecvBuf = data; }else{ RecvBuf += data; } if(RecvBuf.length < 7){ return; } // console.log(Buffer.from(RecvBuf.slice(0, 7)).toString('hex')); //找包头 let index = -1; for (i = 0; i < RecvBuf.length-3; i++) { if(RecvBuf.slice(i, i+3) == "YL>"){ index = i; break; } } if(index == -1){ console.log("未找到到包头"); return; } console.log("已查到包头, index:"+ index ); // 如果不满足,断包了 if(index+7 > RecvBuf.length){ console.log("检查长度1失败"); return; } console.log("检查长度1正常" ); // console.log(RecvBuf.slice(index+3, index+5)); let data_len = BytesToIntBigEndian(RecvBuf.slice(index+3, index+5)); // console.log("data_len:"+ data_len ); // 检查实际长度 if(index+7+data_len > RecvBuf.length || data_len == 0){ console.log("检查长度2失败, data_len:" + data_len + "recv_len:" + RecvBuf.length ); return; } console.log("检查长度2正常" ); // 检查校验码 // console.log("5:" + RecvBuf[index+5] +", 6:"+ RecvBuf[index+6] ); let recv_check = BytesToIntBigEndian(RecvBuf.slice(index+5, index+7)); let cal_check = calculateChecksum16bit(RecvBuf.slice(index+7,index+7+data_len)); if(recv_check != cal_check){ console.log("校验码失败, recv_check:" + recv_check +", cal_check:"+ cal_check ); return; } console.log("校验码成功" ); //解析数据 // let start = index+7; // let stop = index+7+data_len; // console.log("start:" + start +", stop:"+ stop ); let out = RecvBuf.slice(index+7,index+7+data_len); // 处理out数据 handler_recv(out); // 留下剩余数据:正常情况下长度=0:无剩余数据 let old_len = data.length; RecvBuf = RecvBuf.slice(index+7+data_len); console.log("剩余数据:" + RecvBuf); } // 设置一个每5000毫秒执行一次的定时器 setInterval(function() { array = stringsArray[strings_i]; if(array.length >= 500){ console.log("长度太大,请减少数据长度"); return; } pack_send(array); strings_i++; if(strings_i >= stringsArray.length){ strings_i = 0; } }, 5000); ws.onopen = function(evt) { console.log("Connection open ..."); }; ws.onmessage = function(evt) { unpack_recv(evt.data); //string }; ws.onclose = function(evt) { console.log("Connection closed."); };