client.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // 使用ws模块
  2. const { monitorEventLoopDelay } = require('perf_hooks');
  3. const WebSocket = require('ws');
  4. // npm i stickpackage
  5. // npm i ws
  6. var ws = new WebSocket("ws://jiangyi.site:11111/");
  7. let stringsArray = [
  8. // 获取(可批量)
  9. "get:heart_beat=?;time=?;version=?;work_status=?;fire_status=?;fault_status=?",
  10. "get:humidity=?;temperature=?;cur_photosen0=?;photosen0=?",
  11. "get:net=?;event_num=?;warning_num=?",
  12. // 设置(可批量)
  13. // "set:extra_time=180;standing_time=10;interval_time=600",
  14. // "set:photosen0=6000,6000,6000,6000",
  15. // "set:net=WIFI24,12345678,qq.com,1883,user,123456;event_num=1000;warning_num=1000",
  16. // 操作(单独)
  17. // "set:time=1727107200",
  18. // "set:reset=1",
  19. // "set:erase_bit=7",
  20. ];
  21. let strings_i = 0;
  22. function bin2String(array) {
  23. return String.fromCharCode.apply(String, array);
  24. }
  25. function calculateChecksum16bit(code) {
  26. let sum = 0;
  27. for (let i = 0; i < code.length; i++) {
  28. sum += (code[i])&0xff;
  29. // console.log("sum:"+ sum +",i:"+ code[i] );
  30. }
  31. // 将结果转换为16位二进制字符串
  32. return sum&0xffff;
  33. }
  34. function bufferToHex (buffer) {
  35. return [...new Uint8Array (buffer)]
  36. .map (b => b.toString (16).padStart (2, "0"))
  37. .join (" ");
  38. }
  39. function stringToByteArray(str) {
  40. const encoder = new TextEncoder(); // 创建TextEncoder实例
  41. const bytes = encoder.encode(str); // 将字符串转换为字节序列
  42. return bytes; // 返回字节数组
  43. }
  44. //小端模式
  45. function BytesToIntLittleEndian(bytes){
  46. var val = 0;
  47. for (var i = bytes.length - 1; i >= 0; i--) {
  48. val += bytes[i];
  49. if (i != 0) {
  50. val = val << 8;
  51. }
  52. }
  53. return val;
  54. }
  55. //小端模式
  56. //number 要转换的整形数值
  57. //length 要转成什么byte数组,规定数组的长度
  58. //如uint16,则lenght=2表示两个字节,转成的byte数组长度是length=2
  59. //如uint32,则lenght=2表示两个字节,转成的byte数组长度是length=4
  60. function IntToBytesLittleEndian(number, length){
  61. var bytes = [];
  62. var i = 0;
  63. do {
  64. bytes[i++] = number & (255);
  65. number = number>>8;
  66. } while ( i < length )
  67. return bytes;
  68. }
  69. //大端模式
  70. function BytesToIntBigEndian(bytes){
  71. var val = 0;
  72. for (var i = 0; i < bytes.length; ++i) {
  73. val += bytes[i];
  74. if (i < bytes.length-1) {
  75. val = val << 8;
  76. }
  77. }
  78. return val;
  79. }
  80. //大端模式
  81. //number 要转换的整形数值
  82. //length 要转成什么byte数组,规定数组的长度
  83. //如uint16,则lenght=2表示两个字节,转成的byte数组长度是length=2
  84. //如uint32,则lenght=2表示两个字节,转成的byte数组长度是length=4
  85. function IntToBytesBigEndian(number, length){
  86. var bytes = [];
  87. var i = length;
  88. do {
  89. bytes[--i] = number & (255);
  90. number = number>>8;
  91. } while (i)
  92. return bytes;
  93. }
  94. function Uint8ArrayToString(fileData){
  95. var dataString = "";
  96. for (var i = 0; i < fileData.length; i++) {
  97. dataString += String.fromCharCode(fileData[i]);
  98. }
  99. return dataString
  100. }
  101. function stringToUint8Array(str){
  102. var arr = [];
  103. for (var i = 0, j = str.length; i < j; ++i) {
  104. arr.push(str.charCodeAt(i));
  105. }
  106. var tmpUint8Array = new Uint8Array(arr);
  107. return tmpUint8Array
  108. }
  109. function intToHex(number, minLength) {
  110. return number.toString(16).padStart(minLength, '0');
  111. }
  112. function hexToString(hex) {
  113. var string = '';
  114. for (var i = 0; i < hex.length; i += 2) {
  115. string += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
  116. }
  117. return string;
  118. }
  119. // 封包
  120. function pack_send(str) {
  121. console.log("封包前:"+str);
  122. body = str;
  123. let data_len = body.length & 0xffff;
  124. let data_check = calculateChecksum16bit(stringToByteArray(body)) & 0xffff;
  125. // console.log("len:"+intToHex(data_len,4));
  126. // console.log("check:"+intToHex(data_check,4));
  127. const headBuf = Buffer.from([0x59, 0x4c, 0x3c, (data_len>>8)&0xff, (data_len)&0xff, (data_check>>8)&0xff, (data_check)&0xff]);
  128. const bodyBuf = Buffer.from(body);
  129. let pack_date = Buffer.concat([headBuf, bodyBuf]);
  130. ws.send(pack_date);
  131. // console.log("headBuf:"+bufferToHex(headBuf));
  132. // console.log("bodyBuf:"+bufferToHex(bodyBuf));
  133. console.log("封包后:"+bufferToHex(pack_date));
  134. }
  135. function handler_recv(out){
  136. console.log("解析:" + out);
  137. str = String(out);
  138. let arr = str.split("=");
  139. if(arr.length == 2){
  140. let key = arr[0]
  141. let val = arr[1]
  142. if(key == "heart_beat"){
  143. let arr2 = val.split(",");
  144. if(arr2.length == 6){
  145. year = arr2[0];
  146. mon = arr2[1];
  147. day = arr2[2];
  148. hour = arr2[3];
  149. min = arr2[4];
  150. sec = arr2[5];
  151. console.log("heart_beat:20"+year+"-"+mon+"-"+day+" "+hour+":"+min+":"+sec);
  152. }
  153. }
  154. }
  155. }
  156. // 解包
  157. let RecvBuf = "";
  158. function unpack_recv(data) {
  159. datArray = stringToByteArray(data);
  160. console.log("接收 " + data.length +": "+ bufferToHex(datArray));
  161. // data添加到全局RecvBuf
  162. if(RecvBuf == ""){
  163. RecvBuf = data;
  164. }else{
  165. RecvBuf += data;
  166. }
  167. if(RecvBuf.length < 7){
  168. return;
  169. }
  170. // console.log(Buffer.from(RecvBuf.slice(0, 7)).toString('hex'));
  171. //找包头
  172. let index = -1;
  173. for (i = 0; i < RecvBuf.length-3; i++) {
  174. if(RecvBuf.slice(i, i+3) == "YL>"){
  175. index = i;
  176. break;
  177. }
  178. }
  179. if(index == -1){
  180. console.log("未找到到包头");
  181. return;
  182. }
  183. console.log("已查到包头, index:"+ index );
  184. // 如果不满足,断包了
  185. if(index+7 > RecvBuf.length){
  186. console.log("检查长度1失败");
  187. return;
  188. }
  189. console.log("检查长度1正常" );
  190. // console.log(RecvBuf.slice(index+3, index+5));
  191. let data_len = BytesToIntBigEndian(RecvBuf.slice(index+3, index+5));
  192. // console.log("data_len:"+ data_len );
  193. // 检查实际长度
  194. if(index+7+data_len > RecvBuf.length || data_len == 0){
  195. console.log("检查长度2失败, data_len:" + data_len + "recv_len:" + RecvBuf.length );
  196. return;
  197. }
  198. console.log("检查长度2正常" );
  199. // 检查校验码
  200. // console.log("5:" + RecvBuf[index+5] +", 6:"+ RecvBuf[index+6] );
  201. let recv_check = BytesToIntBigEndian(RecvBuf.slice(index+5, index+7));
  202. let cal_check = calculateChecksum16bit(RecvBuf.slice(index+7,index+7+data_len));
  203. if(recv_check != cal_check){
  204. console.log("校验码失败, recv_check:" + recv_check +", cal_check:"+ cal_check );
  205. return;
  206. }
  207. console.log("校验码成功" );
  208. //解析数据
  209. // let start = index+7;
  210. // let stop = index+7+data_len;
  211. // console.log("start:" + start +", stop:"+ stop );
  212. let out = RecvBuf.slice(index+7,index+7+data_len);
  213. // 处理out数据
  214. handler_recv(out);
  215. // 留下剩余数据:正常情况下长度=0:无剩余数据
  216. let old_len = data.length;
  217. RecvBuf = RecvBuf.slice(index+7+data_len);
  218. console.log("剩余数据:" + RecvBuf);
  219. }
  220. // 设置一个每5000毫秒执行一次的定时器
  221. setInterval(function() {
  222. array = stringsArray[strings_i];
  223. if(array.length >= 500){
  224. console.log("长度太大,请减少数据长度");
  225. return;
  226. }
  227. pack_send(array);
  228. strings_i++;
  229. if(strings_i >= stringsArray.length){
  230. strings_i = 0;
  231. }
  232. }, 5000);
  233. ws.onopen = function(evt) {
  234. console.log("Connection open ...");
  235. };
  236. ws.onmessage = function(evt) {
  237. unpack_recv(evt.data); //string
  238. };
  239. ws.onclose = function(evt) {
  240. console.log("Connection closed.");
  241. };