client.js 6.8 KB

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