client.js 7.1 KB

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