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.

444 lines
13 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
  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. .container {
  17. display: flex;
  18. width: 100vw;
  19. align-items: center;
  20. box-sizing: border-box;
  21. justify-content: space-between;
  22. }
  23. .left_chat {
  24. border: solid 1px #000;
  25. height: 100vh;
  26. display: flex;
  27. box-sizing: border-box;
  28. flex-direction: column;
  29. flex: 0.6;
  30. padding: 24px;
  31. overflow: scroll;
  32. }
  33. .right_message {
  34. height: 100vh;
  35. box-sizing: border-box;
  36. flex: 1;
  37. }
  38. .btn {
  39. padding: 36px;
  40. font-size: 24px;
  41. margin-top: 24px;
  42. width: 100%;
  43. }
  44. .right_message {
  45. padding: 24px;
  46. border: solid 1px #000;
  47. display: flex;
  48. flex-direction: column;
  49. }
  50. .message_wrap {
  51. flex: 1;
  52. border: solid 1px #ddd;
  53. overflow: scroll;
  54. }
  55. .message {
  56. padding: 6px 8px;
  57. border-bottom: solid 1px #ddd;
  58. }
  59. .input_wrap {
  60. display: flex;
  61. align-items: center;
  62. /* margin-bottom: 20px; */
  63. }
  64. .input_wrap .ws_connnect {
  65. flex: 2;
  66. padding: 4px 0;
  67. margin-right: 20px;
  68. }
  69. .input_wrap .connect {
  70. flex: 1;
  71. }
  72. .order {
  73. display: grid;
  74. grid-template-columns: repeat(1, 1fr);
  75. column-gap: 20px;
  76. row-gap: 10px;
  77. margin-bottom: 20px;
  78. }
  79. .status {
  80. padding: 4px 0;
  81. }
  82. .tabs {
  83. margin: 20px 0;
  84. }
  85. .tab-bar {
  86. display: flex;
  87. }
  88. .tab {
  89. padding: 10px 20px;
  90. border: 1px solid #ccc;
  91. border-bottom: none;
  92. cursor: pointer;
  93. }
  94. .active {
  95. border-bottom: 2px solid blue;
  96. }
  97. .tab-panel {
  98. display: none;
  99. padding: 20px;
  100. border: 1px solid #ccc;
  101. }
  102. .active {
  103. display: block;
  104. }
  105. .common_order_input {
  106. display: flex;
  107. align-items: center;
  108. justify-content: space-evenly;
  109. padding: 0 20px;
  110. margin-bottom: 10px;
  111. }
  112. .common_order_input .single {
  113. display: flex;
  114. flex-direction: column;
  115. align-items: center;
  116. }
  117. .single .input {
  118. width: 100%;
  119. text-align: center;
  120. padding: 4px;
  121. }
  122. .common_btns {
  123. width: 100%;
  124. }
  125. .btn_c {
  126. width: 100%;
  127. padding: 4px 0;
  128. margin-bottom: 10px;
  129. }
  130. .report_c {
  131. border: solid 1px #ddd;
  132. padding: 10px;
  133. }
  134. .form_line {
  135. display: flex;
  136. align-items: center;
  137. width: 100%;
  138. margin-bottom: 10px;
  139. }
  140. .form_line .tit {
  141. margin-right: 6px;
  142. white-space: nowrap;
  143. }
  144. .form_line .info {
  145. width: 100%;
  146. text-align: center;
  147. padding: 4px 0;
  148. }
  149. .report_c .title {
  150. border-bottom: solid 1px #ddd;
  151. margin-bottom: 10px;
  152. }
  153. </style>
  154. </head>
  155. <body>
  156. <div class="container">
  157. <div class="left_chat">
  158. <div class="input_wrap">
  159. <input type="text" class="ws_connnect" id="ws_connnect_input" />
  160. <button class="connect" onclick="connectWs()">连接</button>
  161. </div>
  162. <p class="status" id="status">当前状态: 未连接</p>
  163. <div class="report_c">
  164. <p class="title">上报解析</p>
  165. <div class="form_line">
  166. <p class="tit">ADDRESS:</p>
  167. <input type="text" class="info" disabled id="report_address" />
  168. </div>
  169. <div class="form_line">
  170. <p class="tit">VALUE:</p>
  171. <input type="text" class="info" disabled id="report_val" />
  172. </div>
  173. </div>
  174. <div class="report_c">
  175. <p class="title">回执解析</p>
  176. <div class="form_line">
  177. <p class="tit">ADDRESS:</p>
  178. <input type="text" class="info" disabled id="receipt_address" />
  179. </div>
  180. <div class="form_line">
  181. <p class="tit">VALUE:</p>
  182. <input type="text" class="info" disabled id="receipt_val" />
  183. </div>
  184. <div class="form_line">
  185. <p class="tit">结果:</p>
  186. <input
  187. type="text"
  188. class="info"
  189. value="无"
  190. disabled
  191. id="receipt_message"
  192. />
  193. </div>
  194. </div>
  195. <div class="tabs">
  196. <ul class="tab-bar">
  197. <li class="tab active">通用指令</li>
  198. <li class="tab">指令列表</li>
  199. </ul>
  200. <div class="tab-content">
  201. <div class="tab-panel active">
  202. <div class="common_order_input">
  203. <div class="single">
  204. <p>ID</p>
  205. <input type="text" class="input" id="common_id" />
  206. </div>
  207. <div
  208. class="single"
  209. style="margin-left: 10px; margin-right: 5px"
  210. >
  211. <p>BASE</p>
  212. <input type="text" class="input" id="common_base" />
  213. </div>
  214. <div
  215. class="single"
  216. style="margin-left: 5px; margin-right: 10px"
  217. >
  218. <p>OFFSET</p>
  219. <input type="text" class="input" id="common_off" />
  220. </div>
  221. <div class="single">
  222. <p>VALUE</p>
  223. <input type="text" class="input" id="common_value" />
  224. </div>
  225. </div>
  226. <div class="common_btns">
  227. <button class="btn_c" onclick="writeFun()"></button>
  228. <button class="btn_c" onclick="read()"></button>
  229. <button class="btn_c" onclick="autoReport()">
  230. 使能自动上报
  231. </button>
  232. <button class="btn_c" onclick="reportCycle()">
  233. 设置上报周期
  234. </button>
  235. </div>
  236. </div>
  237. <div class="tab-panel">
  238. <div class="order" id="order"></div>
  239. </div>
  240. </div>
  241. </div>
  242. </div>
  243. <div class="right_message">
  244. <div class="message_wrap" id="message_wrap"></div>
  245. <div style="display: flex; align-items: center; margin-top: 10px">
  246. <textarea style="flex: 1" name="bio" rows="15" cols="40"></textarea>
  247. <div style="display: flex; flex-direction: column; height: 100%">
  248. <button style="flex: 1" onclick="sendMessage()">发送</button>
  249. <button style="flex: 1" onclick="clearTextArea()">清空</button>
  250. </div>
  251. </div>
  252. </div>
  253. </div>
  254. </body>
  255. <script src="./config.js"></script>
  256. <script>
  257. window.onload = () => {
  258. const commonI = document.querySelector("#common_id");
  259. const commonB = document.querySelector("#common_base");
  260. commonI.value = localStorage.getItem("id");
  261. commonB.value = localStorage.getItem("base");
  262. };
  263. var ws = null;
  264. const websocketInput = document.querySelector("#ws_connnect_input");
  265. websocketInput.value = websocketAddress;
  266. // 先向order下动态添加指令集合
  267. const order = document.querySelector("#order");
  268. for (let key in config) {
  269. const button = document.createElement("button");
  270. button.textContent = key;
  271. button.className = "order_btn";
  272. button.setAttribute("v", key);
  273. order?.appendChild(button);
  274. }
  275. order.addEventListener("click", (e) => {
  276. const item = e.target;
  277. if (item && item.getAttribute("v")) {
  278. const key = item.getAttribute("v");
  279. sendOrder(config[key]);
  280. }
  281. });
  282. const commonI = document.querySelector("#common_id");
  283. const commonB = document.querySelector("#common_base");
  284. commonI.addEventListener("input", (e) => {
  285. localStorage.setItem("id", e.target.value);
  286. });
  287. commonB.addEventListener("input", (e) => {
  288. localStorage.setItem("base", e.target.value);
  289. });
  290. const tabs = document.querySelector(".tabs");
  291. const tabBars = document.querySelectorAll(".tab-bar .tab");
  292. const tabPanels = document.querySelectorAll(".tab-content .tab-panel");
  293. for (let i = 0; i < tabBars.length; i++) {
  294. tabBars[i].onclick = function () {
  295. removeActive();
  296. this.classList.add("active");
  297. tabPanels[i].classList.add("active");
  298. };
  299. }
  300. function removeActive() {
  301. for (let i = 0; i < tabBars.length; i++) {
  302. tabBars[i].classList.remove("active");
  303. tabPanels[i].classList.remove("active");
  304. }
  305. }
  306. const clearMessage = () => {
  307. const messageWrap = document.querySelector("#message_wrap");
  308. messageWrap.innerHTML = "";
  309. };
  310. const clearTextArea = () => {
  311. const textArea = document.querySelector("textarea");
  312. textArea.value = "";
  313. clearMessage();
  314. };
  315. const sendMessage = () => {
  316. if (ws) {
  317. const textArea = document.querySelector("textarea");
  318. const messageVal = textArea.value;
  319. ws.send(messageVal);
  320. const messageWrap = document.querySelector("#message_wrap");
  321. const div = document.createElement("div");
  322. div.classList = ["message"];
  323. div.textContent = `Tx: ${messageVal}`;
  324. messageWrap.appendChild(div);
  325. messageWrap.scrollTop =
  326. messageWrap.scrollHeight - messageWrap.clientHeight;
  327. } else {
  328. }
  329. };
  330. const connectWs = () => {
  331. const input = document.querySelector("#ws_connnect_input");
  332. const status = document.querySelector("#status");
  333. const address = input.value;
  334. try {
  335. ws = new WebSocket(address);
  336. ws.onopen = function () {
  337. console.log("Connected to WebSocket server.");
  338. // 改变状态
  339. status.innerHTML = `当前状态: 已连接${address}`;
  340. };
  341. ws.onmessage = function (evt) {
  342. console.log(evt.data);
  343. const messageWrap = document.querySelector("#message_wrap");
  344. const div = document.createElement("div");
  345. div.classList = ["message"];
  346. div.textContent = `Rx: ${evt.data}`;
  347. messageWrap.appendChild(div);
  348. messageWrap.scrollTop =
  349. messageWrap.scrollHeight - messageWrap.clientHeight;
  350. // 对消息进行处理
  351. try {
  352. const messageBody = JSON.parse(evt.data);
  353. const { type, ctrlPointAddr, ctrlPointVal } = messageBody;
  354. const receiptMessage = document.querySelector("#receipt_message");
  355. const receiptAddress = document.querySelector("#receipt_address");
  356. const receiptVal = document.querySelector("#receipt_val");
  357. const reportAddress = document.querySelector("#report_address");
  358. const reportVal = document.querySelector("#report_val");
  359. if (type == "receipt") {
  360. receiptMessage.value = "正确";
  361. receiptAddress.value = ctrlPointAddr;
  362. receiptVal.value = ctrlPointVal;
  363. }
  364. if (type == "error_receipt") {
  365. receiptMessage.value = "错误";
  366. receiptAddress.value = ctrlPointAddr;
  367. receiptVal.value = ctrlPointVal;
  368. }
  369. if (type == "report") {
  370. reportAddress.value = ctrlPointAddr;
  371. reportVal.value = ctrlPointVal;
  372. }
  373. } catch (error) {}
  374. };
  375. ws.onclose = function () {
  376. status.innerHTML = `当前状态: 已关闭`;
  377. };
  378. } catch (error) {
  379. status.innerHTML = `当前状态: 连接错误`;
  380. }
  381. };
  382. const sendOrder = (msg) => {
  383. if (ws) {
  384. ws.send(msg);
  385. const messageWrap = document.querySelector("#message_wrap");
  386. const div = document.createElement("div");
  387. div.classList = ["message"];
  388. div.textContent = `Tx: ${msg}`;
  389. messageWrap.appendChild(div);
  390. messageWrap.scrollTop =
  391. messageWrap.scrollHeight - messageWrap.clientHeight;
  392. }
  393. };
  394. const getCommonOrderInput = (type) => {
  395. const id = document.querySelector("#common_id");
  396. const base = document.querySelector("#common_base");
  397. const off = document.querySelector("#common_off");
  398. const value = document.querySelector("#common_value");
  399. const { protocol, message } = commonMessage;
  400. return JSON.stringify({
  401. protocol,
  402. message: {
  403. ...message,
  404. targetId: id.value,
  405. ctrlPointAddr: base.value + off.value,
  406. ctrlPointVal: value.value,
  407. type,
  408. },
  409. });
  410. };
  411. const writeFun = () => {
  412. const msg = getCommonOrderInput("write");
  413. sendOrder(msg);
  414. };
  415. const read = () => {
  416. const msg = getCommonOrderInput("read");
  417. sendOrder(msg);
  418. };
  419. const autoReport = () => {
  420. const msg = getCommonOrderInput("set_auto_report_enable_flag");
  421. sendOrder(msg);
  422. };
  423. const reportCycle = () => {
  424. const msg = getCommonOrderInput("set_auto_report_period");
  425. sendOrder(msg);
  426. };
  427. </script>
  428. </html>