websocket快速操作工具
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

571 lines
17 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. <style>
  9. *,
  10. html,
  11. body {
  12. margin: 0;
  13. padding: 0;
  14. box-sizing: border-box;
  15. }
  16. li {
  17. list-style: none;
  18. }
  19. .container {
  20. display: flex;
  21. width: 100vw;
  22. align-items: center;
  23. box-sizing: border-box;
  24. justify-content: space-between;
  25. }
  26. .left_chat {
  27. border: solid 1px #000;
  28. height: 100vh;
  29. display: flex;
  30. box-sizing: border-box;
  31. flex-direction: column;
  32. padding: 24px;
  33. overflow: scroll;
  34. width: 400px;
  35. min-width: 400px;
  36. }
  37. .right_message {
  38. height: 100vh;
  39. box-sizing: border-box;
  40. flex: 1;
  41. }
  42. .btn {
  43. padding: 36px;
  44. font-size: 24px;
  45. margin-top: 24px;
  46. width: 100%;
  47. }
  48. .right_message {
  49. padding: 24px;
  50. border: solid 1px #000;
  51. display: flex;
  52. flex-direction: column;
  53. }
  54. .message_wrap {
  55. flex: 1;
  56. border: solid 1px #ddd;
  57. overflow: scroll;
  58. }
  59. .message {
  60. padding: 6px 8px;
  61. border-bottom: solid 1px #ddd;
  62. }
  63. .input_wrap {
  64. display: flex;
  65. align-items: center;
  66. /* margin-bottom: 20px; */
  67. }
  68. .input_wrap .ws_connnect {
  69. flex: 2;
  70. padding: 4px 0;
  71. margin-right: 20px;
  72. }
  73. .input_wrap .connect {
  74. flex: 1;
  75. }
  76. .order {
  77. display: grid;
  78. grid-template-columns: repeat(1, 1fr);
  79. column-gap: 20px;
  80. row-gap: 10px;
  81. margin-bottom: 20px;
  82. }
  83. .status {
  84. padding: 4px 0;
  85. border-bottom: solid 2px #ddd;
  86. margin-bottom: 10px;
  87. }
  88. .tabs {
  89. margin: 20px 0;
  90. }
  91. .tab-bar {
  92. display: flex;
  93. }
  94. .tab {
  95. padding: 10px 20px;
  96. border: 1px solid #ccc;
  97. border-bottom: none;
  98. cursor: pointer;
  99. }
  100. /* .active {
  101. border-bottom: 2px solid blue;
  102. } */
  103. .tab-panel {
  104. display: none;
  105. padding: 20px;
  106. border: 1px solid #ccc;
  107. }
  108. .active {
  109. display: block;
  110. }
  111. .common_order_input {
  112. display: flex;
  113. align-items: center;
  114. justify-content: space-evenly;
  115. padding: 0 20px;
  116. margin-bottom: 10px;
  117. }
  118. .common_order_input .single {
  119. display: flex;
  120. flex-direction: column;
  121. align-items: center;
  122. }
  123. .single .input {
  124. width: 100%;
  125. text-align: center;
  126. padding: 4px;
  127. }
  128. .common_btns {
  129. width: 100%;
  130. }
  131. .btn_c {
  132. width: 100%;
  133. padding: 4px 0;
  134. margin-bottom: 10px;
  135. }
  136. .report_c {
  137. border: solid 1px #ddd;
  138. padding: 10px;
  139. }
  140. .form_line {
  141. display: flex;
  142. align-items: center;
  143. width: 100%;
  144. margin-bottom: 10px;
  145. }
  146. .form_line .tit {
  147. margin-right: 6px;
  148. white-space: nowrap;
  149. }
  150. .form_line .info {
  151. width: 100%;
  152. text-align: center;
  153. padding: 4px 0;
  154. }
  155. .report_c .title {
  156. border-bottom: solid 1px #ddd;
  157. margin-bottom: 10px;
  158. }
  159. .mod-tab .tab_top {
  160. float: left;
  161. padding: 5px 20px;
  162. border-top: 1px solid #ccc;
  163. border-left: 1px solid #ccc;
  164. background-color: #ddd;
  165. }
  166. .header .tab_top:last-child {
  167. border-right: 1px solid #ccc;
  168. }
  169. .content {
  170. border: 1px solid #ccc;
  171. width: 100%;
  172. height: 100%;
  173. }
  174. .header::after {
  175. content: "";
  176. display: block;
  177. clear: both;
  178. }
  179. .mod-tab .header .active {
  180. background-color: #fff;
  181. }
  182. .mod-tab .content .panel {
  183. display: none;
  184. }
  185. .mod-tab .content .active {
  186. display: block;
  187. }
  188. </style>
  189. </head>
  190. <body>
  191. <div class="container">
  192. <div class="left_chat">
  193. <div class="input_wrap">
  194. <input type="text" class="ws_connnect" id="ws_connnect_input" />
  195. <button class="connect" onclick="connectWs()">连接</button>
  196. </div>
  197. <p class="status" id="status">当前状态: 未连接</p>
  198. <div class="mod-tab">
  199. <div class="header">
  200. <button class="tab_top active button1">基本控制</button>
  201. <button class="tab_top button2">电机控制</button>
  202. <button class="tab_top button3">舵机控制</button>
  203. </div>
  204. <div class="content">
  205. <div class="panel active">
  206. <div class="report_c">
  207. <p class="title">上报解析</p>
  208. <div class="form_line">
  209. <p class="tit">ADDRESS:</p>
  210. <input
  211. type="text"
  212. class="info"
  213. disabled
  214. id="report_address"
  215. />
  216. </div>
  217. <div class="form_line">
  218. <p class="tit">VALUE:</p>
  219. <input type="text" class="info" disabled id="report_val" />
  220. </div>
  221. </div>
  222. <div class="report_c">
  223. <p class="title">回执解析</p>
  224. <div class="form_line">
  225. <p class="tit">ADDRESS:</p>
  226. <input
  227. type="text"
  228. class="info"
  229. disabled
  230. id="receipt_address"
  231. />
  232. </div>
  233. <div class="form_line">
  234. <p class="tit">VALUE:</p>
  235. <input type="text" class="info" disabled id="receipt_val" />
  236. </div>
  237. <div class="form_line">
  238. <p class="tit">结果:</p>
  239. <input
  240. type="text"
  241. class="info"
  242. value="无"
  243. disabled
  244. id="receipt_message"
  245. />
  246. </div>
  247. </div>
  248. <div class="tabs">
  249. <ul class="tab-bar">
  250. <li class="tab active">通用指令</li>
  251. <li class="tab">指令列表</li>
  252. </ul>
  253. <div class="tab-content">
  254. <div class="tab-panel active">
  255. <div class="common_order_input">
  256. <div class="single">
  257. <p>ID</p>
  258. <input type="text" class="input" id="common_id" />
  259. </div>
  260. <div
  261. class="single"
  262. style="margin-left: 10px; margin-right: 5px"
  263. >
  264. <p>BASE</p>
  265. <input type="text" class="input" id="common_base" />
  266. </div>
  267. <div
  268. class="single"
  269. style="margin-left: 5px; margin-right: 10px"
  270. >
  271. <p>OFFSET</p>
  272. <input type="text" class="input" id="common_off" />
  273. </div>
  274. <div class="single">
  275. <p>VALUE</p>
  276. <input type="text" class="input" id="common_value" />
  277. </div>
  278. </div>
  279. <div class="common_btns">
  280. <button class="btn_c" onclick="writeFun()"></button>
  281. <button class="btn_c" onclick="read()"></button>
  282. <button class="btn_c" onclick="autoReport()">
  283. 使能自动上报
  284. </button>
  285. <button class="btn_c" onclick="reportCycle()">
  286. 设置上报周期
  287. </button>
  288. </div>
  289. </div>
  290. <div class="tab-panel">
  291. <div class="order" id="order"></div>
  292. </div>
  293. </div>
  294. </div>
  295. </div>
  296. <div class="panel">panel2</div>
  297. <div class="panel">panel3</div>
  298. </div>
  299. </div>
  300. </div>
  301. <div class="right_message">
  302. <div class="message_wrap" id="message_wrap"></div>
  303. <div style="display: flex; align-items: center; margin-top: 10px">
  304. <textarea style="flex: 1" name="bio" rows="15" cols="40"></textarea>
  305. <div style="display: flex; flex-direction: column; height: 100%">
  306. <button style="flex: 1" onclick="sendMessage()">发送</button>
  307. <button style="flex: 1" onclick="clearTextArea()">清空</button>
  308. </div>
  309. </div>
  310. </div>
  311. </div>
  312. </body>
  313. <script src="./config.js"></script>
  314. <script>
  315. window.onload = () => {
  316. const commonI = document.querySelector("#common_id");
  317. const commonB = document.querySelector("#common_base");
  318. commonI.value = localStorage.getItem("id");
  319. commonB.value = localStorage.getItem("base");
  320. };
  321. var ws = null;
  322. const websocketInput = document.querySelector("#ws_connnect_input");
  323. websocketInput.value = websocketAddress;
  324. // 先向order下动态添加指令集合
  325. const order = document.querySelector("#order");
  326. for (let key in config) {
  327. const button = document.createElement("button");
  328. button.textContent = key;
  329. button.className = "order_btn";
  330. button.setAttribute("v", key);
  331. order?.appendChild(button);
  332. }
  333. order.addEventListener("click", (e) => {
  334. const item = e.target;
  335. if (item && item.getAttribute("v")) {
  336. const key = item.getAttribute("v");
  337. sendOrder(config[key]);
  338. }
  339. });
  340. const commonI = document.querySelector("#common_id");
  341. const commonB = document.querySelector("#common_base");
  342. commonI.addEventListener("input", (e) => {
  343. localStorage.setItem("id", e.target.value);
  344. });
  345. commonB.addEventListener("input", (e) => {
  346. localStorage.setItem("base", e.target.value);
  347. });
  348. const tabs = document.querySelector(".tabs");
  349. const tabBars = document.querySelectorAll(".tab-bar .tab");
  350. const tabPanels = document.querySelectorAll(".tab-content .tab-panel");
  351. for (let i = 0; i < tabBars.length; i++) {
  352. tabBars[i].onclick = function () {
  353. removeActive();
  354. this.classList.add("active");
  355. tabPanels[i].classList.add("active");
  356. };
  357. }
  358. function removeActive() {
  359. for (let i = 0; i < tabBars.length; i++) {
  360. tabBars[i].classList.remove("active");
  361. tabPanels[i].classList.remove("active");
  362. }
  363. }
  364. const clearMessage = () => {
  365. const messageWrap = document.querySelector("#message_wrap");
  366. messageWrap.innerHTML = "";
  367. };
  368. const clearTextArea = () => {
  369. const textArea = document.querySelector("textarea");
  370. textArea.value = "";
  371. clearMessage();
  372. };
  373. const sendMessage = () => {
  374. if (ws) {
  375. const textArea = document.querySelector("textarea");
  376. const messageVal = textArea.value;
  377. ws.send(messageVal);
  378. const messageWrap = document.querySelector("#message_wrap");
  379. const div = document.createElement("div");
  380. div.classList = ["message"];
  381. div.textContent = `Tx: ${messageVal}`;
  382. messageWrap.appendChild(div);
  383. messageWrap.scrollTop =
  384. messageWrap.scrollHeight - messageWrap.clientHeight;
  385. } else {
  386. }
  387. };
  388. const transValToName = (val) => {
  389. switch (val) {
  390. case 0x00:
  391. return "kSuccess";
  392. case 2:
  393. return "kRegNotFound";
  394. case 3:
  395. return "kRegNotWritable";
  396. case 4:
  397. return "kRegNotReadable";
  398. case 5:
  399. return "kIllegalValue";
  400. case 6:
  401. return "kDeviceBusy";
  402. case 7:
  403. return "kDeviceException";
  404. case 8:
  405. return "kChannelDeviceException";
  406. case 9:
  407. return "kParameterError";
  408. case 10:
  409. return "kOvertime";
  410. case 11:
  411. return "kOperationInvalid";
  412. case 12:
  413. return "kunsupportOperation";
  414. case 13:
  415. return "kIllegalOperation";
  416. case 14:
  417. return "kPermissionDenied";
  418. case 15:
  419. return "koutOfRange";
  420. case 16:
  421. return "kmotorNotRunToHome";
  422. case 17:
  423. return "kParameterOutOfLimit";
  424. }
  425. };
  426. const connectWs = () => {
  427. console.log(123);
  428. const input = document.querySelector("#ws_connnect_input");
  429. const status = document.querySelector("#status");
  430. const address = input.value;
  431. try {
  432. ws = new WebSocket(address);
  433. ws.onopen = function () {
  434. console.log("Connected to WebSocket server.");
  435. // 改变状态
  436. status.innerHTML = `当前状态: 已连接${address}`;
  437. };
  438. ws.onmessage = function (evt) {
  439. const messageWrap = document.querySelector("#message_wrap");
  440. const div = document.createElement("div");
  441. div.classList = ["message"];
  442. div.textContent = `Rx: ${evt.data}`;
  443. messageWrap.appendChild(div);
  444. messageWrap.scrollTop =
  445. messageWrap.scrollHeight - messageWrap.clientHeight;
  446. // 对消息进行处理
  447. try {
  448. const { message: messageBody } = JSON.parse(evt.data);
  449. const { type, ctrlPointAddr, ctrlPointVal } = messageBody;
  450. const receiptMessage = document.querySelector("#receipt_message");
  451. const receiptAddress = document.querySelector("#receipt_address");
  452. const receiptVal = document.querySelector("#receipt_val");
  453. const reportAddress = document.querySelector("#report_address");
  454. const reportVal = document.querySelector("#report_val");
  455. if (type == "receipt") {
  456. receiptMessage.value = "正确";
  457. receiptAddress.value = ctrlPointAddr;
  458. receiptVal.value = ctrlPointVal;
  459. }
  460. if (type == "error_receipt") {
  461. receiptMessage.value = "错误";
  462. receiptAddress.value = ctrlPointAddr;
  463. // 错误回执需要吧值和英文进行对应
  464. receiptVal.value = transValToName(ctrlPointVal);
  465. }
  466. if (type == "report") {
  467. reportAddress.value = ctrlPointAddr;
  468. reportVal.value = ctrlPointVal;
  469. }
  470. } catch (error) {
  471. console.log(error);
  472. }
  473. };
  474. ws.onclose = function () {
  475. status.innerHTML = `当前状态: 已关闭`;
  476. };
  477. } catch (error) {
  478. status.innerHTML = `当前状态: 连接错误`;
  479. }
  480. };
  481. const sendOrder = (msg) => {
  482. if (ws) {
  483. ws.send(msg);
  484. const messageWrap = document.querySelector("#message_wrap");
  485. const div = document.createElement("div");
  486. div.classList = ["message"];
  487. div.textContent = `Tx: ${msg}`;
  488. messageWrap.appendChild(div);
  489. messageWrap.scrollTop =
  490. messageWrap.scrollHeight - messageWrap.clientHeight;
  491. }
  492. };
  493. const getCommonOrderInput = (type) => {
  494. const id = document.querySelector("#common_id");
  495. const base = document.querySelector("#common_base");
  496. const off = document.querySelector("#common_off");
  497. const value = document.querySelector("#common_value");
  498. const { protocol, message } = commonMessage;
  499. return JSON.stringify({
  500. protocol,
  501. message: {
  502. ...message,
  503. targetId: parseInt(id.value),
  504. ctrlPointAddr: parseInt(base.value) + parseInt(off.value),
  505. ctrlPointVal: parseInt(value.value),
  506. type,
  507. },
  508. });
  509. };
  510. const writeFun = () => {
  511. const msg = getCommonOrderInput("write");
  512. sendOrder(msg);
  513. };
  514. const read = () => {
  515. const msg = getCommonOrderInput("read");
  516. sendOrder(msg);
  517. };
  518. const autoReport = () => {
  519. const msg = getCommonOrderInput("set_auto_report_enable_flag");
  520. sendOrder(msg);
  521. };
  522. const reportCycle = () => {
  523. const msg = getCommonOrderInput("set_auto_report_period");
  524. sendOrder(msg);
  525. };
  526. document.querySelectorAll(".tab_top").forEach(function (node) {
  527. node.addEventListener("click", function () {
  528. var index;
  529. this.parentElement
  530. .querySelectorAll(".tab_top")
  531. .forEach(function (e, inx) {
  532. //e.style.display='none' 跳转的时候隐藏按钮
  533. e.classList.remove("active");
  534. if (node === e) {
  535. index = inx;
  536. }
  537. });
  538. this.classList.add("active");
  539. this.parentElement.nextElementSibling
  540. .querySelectorAll(".panel")
  541. .forEach(function (panel) {
  542. panel.classList.remove("active");
  543. });
  544. this.parentElement.nextElementSibling
  545. .querySelectorAll(".panel")
  546. [index].classList.add("active");
  547. });
  548. });
  549. </script>
  550. </html>