{"id":35741,"date":"2025-11-25T08:50:57","date_gmt":"2025-11-25T00:50:57","guid":{"rendered":"https:\/\/www.modbus.cn\/?page_id=35741"},"modified":"2026-06-27T11:58:21","modified_gmt":"2026-06-27T03:58:21","slug":"modbustool","status":"publish","type":"page","link":"https:\/\/www.modbus.cn\/en\/modbustool","title":{"rendered":"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177"},"content":{"rendered":"        <!-- Modbus Tools Pro Frontend -->\r\n        <link rel=\"stylesheet\" href=\"https:\/\/www.modbus.cn\/wp-content\/plugins\/modbus-tools\/assets\/css\/modbus-tools.css?v=1783292406\" \/>\r\n        <style id=\"modbus-tools-theme-inline\">\n        .modbus-tools-frontend{width:100%;max-width:100%;margin:0;padding:0;}\n        .modbus-tabs-container{overflow:hidden;border:1px solid #dbe4f0;border-radius:12px;background:#fff;box-shadow:0 18px 46px rgba(14,31,53,.10);}\n        .modbus-tabs{display:flex;flex-wrap:wrap;gap:0;padding:8px;border-bottom:1px solid #dbe4f0;background:#eef3fa;}\n        .modbus-tab{flex:1 1 132px;min-width:118px;display:flex;align-items:center;justify-content:center;min-height:44px;padding:10px 14px;border:0;border-radius:8px;background:transparent;color:#657386;font-family:-apple-system,BlinkMacSystemFont,\"PingFang SC\",\"Microsoft YaHei\",sans-serif;font-size:13px;font-weight:850;text-align:center;text-decoration:none;transition:background .2s ease,color .2s ease,box-shadow .2s ease;}\n        .modbus-tab:hover{background:rgba(29,95,209,.08);color:#1d5fd1;}\n        .modbus-tab.active{background:#fff;color:#1d5fd1;box-shadow:0 8px 18px rgba(14,31,53,.08);}\n        .modbus-tab-content{display:none;padding:26px;background:#f8fbff;}\n        .modbus-tab-content.active{display:block;}\n        .serial-debug-container{min-height:600px;padding:20px;border:1px solid #dbe4f0;border-radius:12px;background:#fff;}\n        .serial-debug-layout{display:flex;gap:20px;flex-wrap:wrap;}\n        .serial-debug-left-panel{width:320px;flex-shrink:0;display:flex;flex-direction:column;gap:16px;}\n        .serial-debug-right-panel{flex:1;min-width:300px;display:flex;flex-direction:column;gap:16px;}\n        @media (max-width:1200px){.serial-debug-layout{flex-direction:column}.serial-debug-left-panel{width:100%}}\n        @media (max-width:768px){.modbus-tabs{padding:6px}.modbus-tab{flex:1 1 50%;min-width:0}.modbus-tab-content{padding:16px}}\n        <\/style>\n        <div class=\"modbus-tools-frontend\">\n            <section class=\"modbus-miniapp-hero\" aria-labelledby=\"modbus-miniapp-title\">\n                <div class=\"modbus-miniapp-hero__content\">\n                    <div class=\"modbus-miniapp-hero__eyebrow\">\n                        <span class=\"modbus-miniapp-hero__signal\" aria-hidden=\"true\"><\/span>\n                        \u5c0f\u7a0b\u5e8f\u7248\u5df2\u4e0a\u7ebf\n                    <\/div>\n                    <h2 id=\"modbus-miniapp-title\">\u5fae\u4fe1\u626b\u7801\uff0c\u968f\u8eab\u6253\u5f00 Modbus \u8c03\u8bd5\u5de5\u5177<\/h2>\n                    <p>\u73b0\u573a\u6392\u67e5\u3001\u8bbe\u5907\u9a8c\u6536\u3001\u4e34\u65f6\u7b97\u7801\uff0c\u4e0d\u7528\u5b89\u88c5\u8f6f\u4ef6\u3002\u6253\u5f00\u5c0f\u7a0b\u5e8f\u5373\u53ef\u4f7f\u7528 RTU \/ TCP \/ ASCII\u3001CRC \u6821\u9a8c\u3001\u4e32\u53e3\u8c03\u8bd5\u7b49\u5e38\u7528\u80fd\u529b\u3002<\/p>\n                    <div class=\"modbus-miniapp-hero__chips\" aria-label=\"\u5c0f\u7a0b\u5e8f\u80fd\u529b\">\n                        <span>\u73b0\u573a\u5373\u7528<\/span>\n                        <span>\u624b\u673a\u626b\u7801<\/span>\n                        <span>\u5e38\u7528\u547d\u4ee4\u751f\u6210<\/span>\n                        <span>\u6821\u9a8c\u8ba1\u7b97<\/span>\n                    <\/div>\n                <\/div>\n                <div class=\"modbus-miniapp-hero__visual\">\n                    <a href=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" target=\"_blank\" rel=\"noopener\" class=\"modbus-miniapp-hero__qr\" aria-label=\"\u6253\u5f00 Modbus \u5c0f\u7a0b\u5e8f\u7801\u5927\u56fe\">\n                        <img src=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" loading=\"lazy\" decoding=\"async\" loading=\"lazy\" title=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe\" alt=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe\" \/>\n                        <span class=\"modbus-miniapp-hero__scan\" aria-hidden=\"true\"><\/span>\n                    <\/a>\n                    <div class=\"modbus-miniapp-hero__caption\">\u5fae\u4fe1\u626b\u4e00\u626b\uff0c\u7acb\u5373\u4f7f\u7528\u5c0f\u7a0b\u5e8f\u7248<\/div>\n                <\/div>\n            <\/section>\n            <div class=\"modbus-tools-statusbar\" aria-label=\"Modbus\u5728\u7ebf\u5de5\u5177\u72b6\u6001\">\n                <span>RTU \/ TCP \/ ASCII<\/span>\n                <span>CRC \/ LRC \u6821\u9a8c<\/span>\n                <span>\u4e32\u53e3\u8c03\u8bd5<\/span>\n                <span>\u7ee7\u7535\u5668\u63a7\u5236<\/span>\n            <\/div>\n            <div class=\"modbus-tabs-container\">\n                <div class=\"modbus-tabs\">\r\n                                            <a href=\"#rtu-tab\" class=\"modbus-tab active\" data-tab=\"rtu\">Modbus RTU<\/a>\r\n                                                                <a href=\"#tcp-tab\" class=\"modbus-tab \" data-tab=\"tcp\">Modbus TCP<\/a>\r\n                                                                <a href=\"#ascii-tab\" class=\"modbus-tab \" data-tab=\"ascii\">Modbus ASCII<\/a>\r\n                                                                <a href=\"#debug-tab\" class=\"modbus-tab \" data-tab=\"debug\">Modbus\u8c03\u8bd5<\/a>\r\n                                                                                    <a href=\"#serial-debug-tab\" class=\"modbus-tab \" data-tab=\"serial-debug\">\u4e32\u53e3\u8c03\u8bd5<\/a>\r\n                                                                <a href=\"#relay-control-tab\" class=\"modbus-tab \" data-tab=\"relay-control\">\u7ee7\u7535\u5668\u63a7\u5236<\/a>\r\n                                    <\/div>\r\n\r\n                <!-- Modbus RTU \u9009\u9879\u5361 -->\r\n                                    <div id=\"rtu-tab\" class=\"modbus-tab-content active\">\r\n                                <div class=\"modbus-rtu-container\">\n            <div class=\"modbus-section\">\n                <h2>Modbus RTU \u8bf7\u6c42\u547d\u4ee4\u751f\u6210\u5668 <span class=\"mini-program-badge\" style=\"position:relative;display:inline-block;font-size:16px;color:#e53935;font-weight:bold;cursor:pointer;margin-left:10px;\" onmouseover=\"this.querySelector('img').style.display='block'\" onmouseout=\"this.querySelector('img').style.display='none'\">\u5c0f\u7a0b\u5e8f\u7248<img decoding=\"async\" src=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" style=\"display:none;position:absolute;left:0;top:25px;z-index:9999;max-width:300px;border:1px solid #ccc;box-shadow:0 2px 10px rgba(0,0,0,0.2);border-radius:4px;\"\/ loading=\"lazy\" title=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" alt=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" \/><\/span><\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u4ece\u7ad9\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"rtu-slave-id\" value=\"01\" placeholder=\"01\">\n                            <small>\u4ece\u7ad9\u5730\u5740\uff08\u5341\u8fdb\u5236\u6216\u5341\u516d\u8fdb\u5236\uff09<\/small>\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u529f\u80fd\u7801<\/label>\n                            <select class=\"form-control\" id=\"rtu-function-code\">\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"0F\">0F - \u5199\u5165\u591a\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"10\">10 - \u5199\u5165\u591a\u4e2a\u5bc4\u5b58\u5668<\/option>\n                            <\/select>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u8d77\u59cb\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"rtu-start-address\" value=\"0001\" placeholder=\"0001\">\n                            <small>\u8d77\u59cb\u5bc4\u5b58\u5668\u5730\u5740<\/small>\n                        <\/div>\n                        <!-- Unified dynamic field column to prevent layout jump -->\n                        <div class=\"form-col\" style=\"width:170px; min-width:170px;\">\n                            <div id=\"rtu-field-quantity\" class=\"rtu-dynamic-field\">\n                                <label>\u6570\u91cf<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"rtu-quantity\" value=\"0002\" placeholder=\"0002\">\n                                <small>\u8bfb\u53d6\u6570\u91cf<\/small>\n                            <\/div>\n                            <div id=\"rtu-field-coil-status\" class=\"rtu-dynamic-field\" style=\"display:none;\">\n                                <label>\u7ebf\u5708\u72b6\u6001<\/label>\n                                <select class=\"form-control\" id=\"rtu-coil-status\">\n                                    <option value=\"0000\">\u5173\u95ed (OFF)<\/option>\n                                    <option value=\"FF00\">\u6253\u5f00 (ON)<\/option>\n                                <\/select>\n                                <small>\u7ebf\u5708\u5f00\u5173\u72b6\u6001<\/small>\n                            <\/div>\n                            <div id=\"rtu-field-register-value\" class=\"rtu-dynamic-field\" style=\"display:none;\">\n                                <label>\u5bc4\u5b58\u5668\u503c<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"rtu-register-value\" value=\"0000\" placeholder=\"0000-FFFF\">\n                                <small>\u5bc4\u5b58\u5668\u6570\u503c<\/small>\n                            <\/div>\n                        <\/div>\n                        <div class=\"form-col\" id=\"rtu-coil-quantity-col\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u7ebf\u5708\u6570\u91cf(DEC)<\/label>\n                            <input type=\"number\" class=\"form-control\" id=\"rtu-coil-quantity\" value=\"1\" min=\"1\" max=\"2000\" placeholder=\"1\">\n                            <small>\u8bbe\u7f6e\u7ebf\u5708\u6570\u91cf<\/small>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u7ebf\u5708\u9009\u62e9\u5668\uff08\u53ea\u5728\u529f\u80fd\u78010F\u65f6\u663e\u793a\uff09 -->\n                    <div id=\"rtu-coil-selector-container\" style=\"display:none; margin-top:15px; padding:15px; background:#f9f9f9; border:1px solid #ddd; border-radius:4px;\">\n                        <label style=\"font-weight:bold; display:block; margin-bottom:10px;\">\u7ebf\u5708\u9009\u62e9<\/label>\n                        <div style=\"display:flex; gap:20px;\">\n                            <!-- \u7ebf\u5708\u6309\u94ae\u533a\u57df -->\n                            <div id=\"rtu-coil-buttons\" style=\"flex:1;\"><\/div>\n                            <!-- \u5341\u516d\u8fdb\u5236\u503c\u663e\u793a\u533a\u57df -->\n                            <div style=\"min-width:150px;\">\n                                <div id=\"rtu-coil-hex-display\" style=\"font-family:monospace; font-size:14px; font-weight:bold; line-height:1.8;\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u5bc4\u5b58\u5668\u7f16\u8f91\u5668\uff08\u53ea\u5728\u529f\u80fd\u780110\u65f6\u663e\u793a\uff09 -->\n                    <div id=\"rtu-register-editor-container\" style=\"display:none; margin-top:15px; padding:15px; background:#f9f9f9; border:1px solid #ddd; border-radius:4px;\">\n                        <label style=\"font-weight:bold; display:block; margin-bottom:10px;\">\u6dfb\u52a0\u5bc4\u5b58\u5668<\/label>\n                        <table style=\"width:100%; border-collapse:collapse; margin-bottom:10px;\">\n                            <thead>\n                                <tr style=\"background-color:#f0f0f0; border-bottom:2px solid #ccc;\">\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u5bc4\u5b58\u5668\u5730\u5740<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u6570\u636e\u7c7b\u578b<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u5b57\u8282\u5e8f<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u6570\u503c(\u5341\u8fdb\u5236)<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u64cd\u4f5c<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody id=\"rtu-register-items\">\n                                <tr class=\"rtu-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control rtu-register-address\" value=\"0001\" placeholder=\"0001\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control rtu-register-value\" value=\"20\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                                <tr class=\"rtu-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control rtu-register-address\" value=\"0002\" placeholder=\"0002\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control rtu-register-value\" value=\"0\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                                <tr class=\"rtu-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control rtu-register-address\" value=\"0003\" placeholder=\"0003\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control rtu-register-value\" value=\"0\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                                <tr class=\"rtu-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control rtu-register-address\" value=\"0004\" placeholder=\"0004\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control rtu-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control rtu-register-value\" value=\"0\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                            <\/tbody>\n                        <\/table>\n                        <button class=\"btn btn-secondary\" id=\"rtu-add-register-row-btn\">+ \u6dfb\u52a0\u5bc4\u5b58\u5668<\/button>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <button class=\"btn btn-primary\" id=\"rtu-generate-btn\">\u751f\u6210\u547d\u4ee4<\/button>\n                        <button class=\"btn btn-secondary\" id=\"rtu-example-btn\">\u793a\u4f8b\u6570\u636e<\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"modbus-output-box\">\n                    <div class=\"output-label\">\u751f\u6210\u7684\u8bf7\u6c42\u547d\u4ee4\uff08HEX\uff09<\/div>\n                    <div class=\"output-content\" id=\"rtu-request-output\">\n                        <span class=\"placeholder\">\u70b9\u51fb\"\u751f\u6210\u547d\u4ee4\"\u6309\u94ae\u751f\u6210<\/span>\n                    <\/div>\n                    <button class=\"btn btn-small btn-copy\" data-target=\"#rtu-request-output\">\u590d\u5236<\/button>\n                <\/div>\n\n                <!-- RTU \u8bf7\u6c42\u5386\u53f2\u8bb0\u5f55 -->\n                <div id=\"rtu-request-history-container\" style=\"margin-top:15px; display:none;\">\n                    <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;\">\n                        <h3 style=\"margin:0; font-size:14px;\">\ud83d\udccb \u8bf7\u6c42\u5386\u53f2\u8bb0\u5f55 (<span id=\"rtu-request-history-count\">0<\/span>)<\/h3>\n                        <div style=\"display:flex; gap:8px;\">\n                            <button class=\"btn btn-small\" id=\"rtu-copy-request-history-btn\">\u590d\u5236\u5168\u90e8<\/button>\n                            <button class=\"btn btn-small btn-danger\" id=\"rtu-clear-request-history-btn\">\u6e05\u7a7a<\/button>\n                        <\/div>\n                    <\/div>\n                    <div id=\"rtu-request-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <div style=\"text-align:center; color:#999; padding:20px;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/div>\n                    <\/div>\n                <\/div>\n\n                <div class=\"modbus-structure-box\" id=\"rtu-request-structure\" style=\"display:none;\">\n                    <h3>\u547d\u4ee4\u7ed3\u6784\u89e3\u6790<\/h3>\n                    <div class=\"structure-content\" id=\"rtu-request-structure-content\"><\/div>\n                <\/div>\n            <\/div>\n\n            <!-- \u54cd\u5e94\u62a5\u6587\u751f\u6210\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus RTU \u54cd\u5e94\u62a5\u6587\u751f\u6210\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u4ece\u7ad9\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"rtu-resp-slave-id\" value=\"01\" placeholder=\"01\">\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u529f\u80fd\u7801<\/label>\n                            <select class=\"form-control\" id=\"rtu-resp-function-code\">\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"0F\">0F - \u5199\u5165\u591a\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"10\">10 - \u5199\u5165\u591a\u4e2a\u5bc4\u5b58\u5668<\/option>\n                            <\/select>\n                        <\/div>\n                    <\/div>\n\n                    <!-- 0F\/10 \u4e13\u7528\u5b57\u6bb5 -->\n                    <div id=\"rtu-resp-0f10-fields\" style=\"display:none; margin-top:15px;\">\n                        <div class=\"form-row\">\n                            <div class=\"form-col\">\n                                <label>\u8d77\u59cb\u5730\u5740<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"rtu-resp-start-addr\" value=\"0001\" placeholder=\"0001\">\n                                <small>\u8bf7\u6c42\u4e2d\u7684\u8d77\u59cb\u5730\u5740<\/small>\n                            <\/div>\n                            <div class=\"form-col\">\n                                <label>\u5199\u5165\u6570\u91cf<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"rtu-resp-quantity\" value=\"000A\" placeholder=\"000A\">\n                                <small>\u8bf7\u6c42\u4e2d\u7684\u5199\u5165\u6570\u91cf<\/small>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <div id=\"rtu-registers-container\">\n                        <label>\u6dfb\u52a0\u5bc4\u5b58\u5668<\/label>\n                        <div class=\"register-item\" style=\"display:flex; gap: 10px; margin-bottom: 10px;\">\n                            <input type=\"text\" class=\"form-control register-value\" placeholder=\"\u5bc4\u5b58\u5668\u503c\uff0816\u8fdb\u5236\uff09\" value=\"1000\">\n                            <select class=\"form-control register-type\">\n                                <option value=\"UINT16\">UINT16<\/option>\n                                <option value=\"INT16\">INT16<\/option>\n                                <option value=\"UINT32\">UINT32<\/option>\n                                <option value=\"INT32\">INT32<\/option>\n                                <option value=\"FLOAT32\">FLOAT32<\/option>\n                                <option value=\"UINT64\">UINT64<\/option>\n                                <option value=\"INT64\">INT64<\/option>\n                                <option value=\"FLOAT64\">FLOAT64<\/option>\n                            <\/select>\n                            <select class=\"form-control register-order\">\n                                <option value=\"ABCD\">ABCD<\/option>\n                                <option value=\"DCBA\">DCBA<\/option>\n                                <option value=\"BADC\">BADC<\/option>\n                                <option value=\"CDAB\">CDAB<\/option>\n                            <\/select>\n                            <button class=\"btn btn-small btn-remove-register\">\u79fb\u9664<\/button>\n                        <\/div>\n                    <\/div>\n\n                    <button class=\"btn btn-secondary\" id=\"rtu-add-register-btn\">+ \u6dfb\u52a0\u5bc4\u5b58\u5668<\/button>\n                    <button class=\"btn btn-primary\" id=\"rtu-generate-response-btn\" style=\"margin-left: 10px;\">\u751f\u6210\u54cd\u5e94<\/button>\n                <\/div>\n\n                <div class=\"modbus-output-box\">\n                    <div class=\"output-label\">\u751f\u6210\u7684\u54cd\u5e94\u62a5\u6587\uff08HEX\uff09<\/div>\n                    <div class=\"output-content\" id=\"rtu-response-output\">\n                        <span class=\"placeholder\">\u70b9\u51fb\"\u751f\u6210\u54cd\u5e94\"\u6309\u94ae\u751f\u6210<\/span>\n                    <\/div>\n                    <button class=\"btn btn-small btn-copy\" data-target=\"#rtu-response-output\">\u590d\u5236<\/button>\n                <\/div>\n\n                <div class=\"modbus-structure-box\" id=\"rtu-response-structure\" style=\"display:none;\">\n                    <h3>\u54cd\u5e94\u7ed3\u6784\u89e3\u6790<\/h3>\n                    <div class=\"structure-content\" id=\"rtu-response-structure-content\"><\/div>\n                <\/div>\n                \n                <!-- \u5386\u53f2\u8bb0\u5f55 -->\n                <div class=\"modbus-section\" id=\"rtu-response-history-container\" style=\"margin-top:20px;\">\n                    <h3>\ud83d\udccb \u54cd\u5e94\u5386\u53f2\u8bb0\u5f55 (<span id=\"rtu-response-history-count\">0<\/span>)<\/h3>\n                    <div id=\"rtu-response-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <p style=\"color:#999; text-align:center;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/p>\n                    <\/div>\n                    <div style=\"margin-top:10px;\">\n                        <button class=\"btn btn-small\" onclick=\"ModbusTools.loadHistory('response')\">\u5237\u65b0\u5386\u53f2<\/button>\n                        <button class=\"btn btn-small btn-secondary\" onclick=\"ModbusTools.clearHistory('response'); ModbusTools.loadHistory('response');\">\u6e05\u7a7a\u5386\u53f2<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- \u62a5\u6587\u89e3\u6790\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus RTU \u62a5\u6587\u89e3\u6790\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <label>\u8f93\u5165Modbus RTU\u6570\u636e\uff08\u4f8b\u5982\uff1a01 03 0C 40 48 F5 C3 00 00 01 3A C6 FE FF FF 39 D4\uff09<\/label>\n                    <textarea class=\"form-control\" id=\"rtu-parse-input\" rows=\"3\" placeholder=\"\u8f93\u5165Modbus RTU\u62a5\u6587\u6570\u636e...\"><\/textarea>\n\n                    <div style=\"margin-top: 10px;\">\n                        <button class=\"btn btn-primary\" id=\"rtu-parse-btn\">\u89e3\u6790<\/button>\n                        <button class=\"btn btn-secondary\" id=\"rtu-parse-clear-btn\">\u6e05\u9664<\/button>\n                        <button class=\"btn btn-secondary\" id=\"rtu-parse-example-btn\">\u793a\u4f8b\u6570\u636e<\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"modbus-parse-rules\">\n                    <h3>\u89e3\u6790\u89c4\u5219\u914d\u7f6e<\/h3>\n                    <button class=\"btn btn-secondary\" id=\"rtu-add-rule-btn\">\u6dfb\u52a0\u89c4\u5219<\/button>\n                    <div id=\"rtu-rules-container\"><\/div>\n                <\/div>\n\n                <div class=\"modbus-output-box\" id=\"rtu-parse-output\" style=\"display:none;\">\n                    <h3>\u89e3\u6790\u7ed3\u679c<\/h3>\n                    <div class=\"structure-content\" id=\"rtu-parse-structure-content\"><\/div>\n                <\/div>\n            <\/div>\n\n            <!-- CRC\u6821\u9a8c -->\n            <div class=\"modbus-section\">\n                <h2>Modbus RTU CRC 16\u6821\u9a8c\u7801\u8ba1\u7b97\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <label>\u8f93\u5165\u547d\u4ee4\uff08\u4e0d\u542bCRC\uff09<\/label>\n                    <textarea class=\"form-control\" id=\"rtu-crc-input\" rows=\"2\" placeholder=\"01 03 00 01 00 02\"><\/textarea>\n\n                    <div style=\"margin-top: 10px;\">\n                        <button class=\"btn btn-primary\" id=\"rtu-crc-btn\">\u8ba1\u7b97CRC<\/button>\n                        <button class=\"btn btn-secondary\" id=\"rtu-crc-clear-btn\">\u6e05\u9664<\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"modbus-output-box\" id=\"rtu-crc-output\" style=\"display:none;\">\n                    <div class=\"crc-result\">\n                        <div class=\"result-item\">\n                            <span class=\"label\">CRC\u503c\uff08HEX\uff09<\/span>\n                            <span class=\"value\" id=\"rtu-crc-value\">--<\/span>\n                        <\/div>\n                        <button class=\"btn btn-small btn-copy\" data-target=\"#rtu-crc-value\">\u590d\u5236<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n                <!-- CRC \u5386\u53f2\u8bb0\u5f55 -->\n                <div id=\"crc-history-container\" style=\"margin-top:15px; display:none;\">\n                    <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;\">\n                        <h3 style=\"margin:0; font-size:14px;\">\ud83d\udccb CRC \u5386\u53f2\u8bb0\u5f55 (<span id=\"crc-history-count\">0<\/span>)<\/h3>\n                        <div style=\"display:flex; gap:8px;\">\n                            <button class=\"btn btn-small\" id=\"crc-copy-history-btn\">\u590d\u5236\u5168\u90e8<\/button>\n                            <button class=\"btn btn-small btn-secondary\" id=\"crc-clear-history-btn\">\u6e05\u7a7a<\/button>\n                        <\/div>\n                    <\/div>\n                    <div id=\"crc-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <p style=\"color:#999; text-align:center; padding:20px;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/p>\n                    <\/div>\n                <\/div>\n        <\/div>\n                            <\/div>\r\n                \r\n                <!-- Modbus TCP \u9009\u9879\u5361 -->\r\n                                    <div id=\"tcp-tab\" class=\"modbus-tab-content \">\r\n                                <div class=\"modbus-tcp-container\">\n            <!-- TCP\u8bf7\u6c42\u751f\u6210\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus TCP\u8bf7\u6c42\u547d\u4ee4\u751f\u6210\u5668 <span class=\"mini-program-badge\" style=\"position:relative;display:inline-block;font-size:16px;color:#e53935;font-weight:bold;cursor:pointer;margin-left:10px;\" onmouseover=\"this.querySelector('img').style.display='block'\" onmouseout=\"this.querySelector('img').style.display='none'\">\u5c0f\u7a0b\u5e8f\u7248<img decoding=\"async\" src=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" style=\"display:none;position:absolute;left:0;top:25px;z-index:9999;max-width:300px;border:1px solid #ccc;box-shadow:0 2px 10px rgba(0,0,0,0.2);border-radius:4px;\"\/ loading=\"lazy\" title=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" alt=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" \/><\/span><\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>HEX<br><small>\u5341\u516d\u8fdb\u5236<\/small><\/label>\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>DEC<br><small>\u5341\u8fdb\u5236<\/small><\/label>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u4ece\u7ad9\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-slave-id\" value=\"01\" placeholder=\"01\">\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u529f\u80fd\u7801<\/label>\n                            <select class=\"form-control\" id=\"tcp-function-code\">\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"0F\">0F - \u5199\u5165\u591a\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"10\">10 - \u5199\u5165\u591a\u4e2a\u5bc4\u5b58\u5668<\/option>\n                            <\/select>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u81ea\u5b9a\u4e49<\/label>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u8d77\u59cb\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-start-address\" value=\"0001\" placeholder=\"0001\">\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u4e8b\u52a1\u6807\u8bc6\u7b26<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-transaction-id\" value=\"0001\" placeholder=\"0001\">\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <!-- \u6570\u91cf\u5b57\u6bb5\uff08\u8bfb\u53d6\u529f\u80fd\u7801\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"tcp-field-quantity\" style=\"width:170px; min-width:170px;\">\n                            <label>\u6570\u91cf<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-quantity\" value=\"0002\" placeholder=\"0002\">\n                            <small>\u8bfb\u53d6\u6570\u91cf<\/small>\n                        <\/div>\n                        <!-- \u7ebf\u5708\u72b6\u6001\uff08\u529f\u80fd\u780105\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"tcp-field-coil-status\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u7ebf\u5708\u72b6\u6001<\/label>\n                            <select class=\"form-control\" id=\"tcp-coil-status\">\n                                <option value=\"0000\">\u5173\u95ed (OFF)<\/option>\n                                <option value=\"FF00\">\u6253\u5f00 (ON)<\/option>\n                            <\/select>\n                            <small>\u7ebf\u5708\u5f00\u5173\u72b6\u6001<\/small>\n                        <\/div>\n                        <!-- \u5bc4\u5b58\u5668\u503c\uff08\u529f\u80fd\u780106\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"tcp-field-register-value\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u5bc4\u5b58\u5668\u503c<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-register-value\" value=\"0000\" placeholder=\"0000-FFFF\">\n                            <small>\u5bc4\u5b58\u5668\u6570\u503c<\/small>\n                        <\/div>\n                        <!-- \u7ebf\u5708\u6570\u91cf\uff08\u529f\u80fd\u78010F\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"tcp-coil-quantity-col\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u7ebf\u5708\u6570\u91cf(DEC)<\/label>\n                            <input type=\"number\" class=\"form-control\" id=\"tcp-coil-quantity\" value=\"1\" min=\"1\" max=\"2000\" placeholder=\"1\">\n                            <small>\u8bbe\u7f6e\u7ebf\u5708\u6570\u91cf<\/small>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u7ebf\u5708\u9009\u62e9\u5668\uff08\u53ea\u5728\u529f\u80fd\u78010F\u65f6\u663e\u793a\uff09 -->\n                    <div id=\"tcp-coil-selector-container\" style=\"display:none; margin-top:15px; padding:15px; background:#f9f9f9; border:1px solid #ddd; border-radius:4px;\">\n                        <label style=\"font-weight:bold; display:block; margin-bottom:10px;\">\u7ebf\u5708\u9009\u62e9<\/label>\n                        <div style=\"display:flex; gap:20px;\">\n                            <!-- \u7ebf\u5708\u6309\u94ae\u533a\u57df -->\n                            <div id=\"tcp-coil-buttons\" style=\"flex:1;\"><\/div>\n                            <!-- \u5341\u516d\u8fdb\u5236\u503c\u663e\u793a\u533a\u57df -->\n                            <div style=\"min-width:150px;\">\n                                <div id=\"tcp-coil-hex-display\" style=\"font-family:monospace; font-size:14px; font-weight:bold; line-height:1.8;\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u5bc4\u5b58\u5668\u7f16\u8f91\u5668\uff08\u53ea\u5728\u529f\u80fd\u780110\u65f6\u663e\u793a\uff09 -->\n                    <div id=\"tcp-register-editor-container\" style=\"display:none; margin-top:15px; padding:15px; background:#f9f9f9; border:1px solid #ddd; border-radius:4px;\">\n                        <label style=\"font-weight:bold; display:block; margin-bottom:10px;\">\u6dfb\u52a0\u5bc4\u5b58\u5668<\/label>\n                        <table style=\"width:100%; border-collapse:collapse; margin-bottom:10px;\">\n                            <thead>\n                                <tr style=\"background-color:#f0f0f0; border-bottom:2px solid #ccc;\">\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u5bc4\u5b58\u5668\u5730\u5740<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u6570\u636e\u7c7b\u578b<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u5b57\u8282\u5e8f<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u6570\u503c(\u5341\u8fdb\u5236)<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u64cd\u4f5c<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody id=\"tcp-register-items\">\n                                <tr class=\"tcp-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control tcp-register-address\" value=\"0001\" placeholder=\"0001\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control tcp-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><option value=\"UINT64\">UINT64<\/option><option value=\"INT64\">INT64<\/option><option value=\"FLOAT64\">FLOAT64<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control tcp-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control tcp-register-value\" value=\"20\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-tcp-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                                <tr class=\"tcp-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control tcp-register-address\" value=\"0002\" placeholder=\"0002\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control tcp-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><option value=\"UINT64\">UINT64<\/option><option value=\"INT64\">INT64<\/option><option value=\"FLOAT64\">FLOAT64<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control tcp-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control tcp-register-value\" value=\"0\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-tcp-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                            <\/tbody>\n                        <\/table>\n                        <button class=\"btn btn-secondary\" id=\"tcp-add-register-row-btn\">+ \u6dfb\u52a0\u5bc4\u5b58\u5668<\/button>\n                    <\/div>\n\n                    <div class=\"form-row\" style=\"margin-top:15px;\">\n                        <button class=\"btn btn-primary\" id=\"tcp-generate-request-btn\">\u751f\u6210\u8bf7\u6c42<\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"modbus-output-box\">\n                    <div class=\"output-label\">\u751f\u6210\u7684\u8bf7\u6c42\u6570\u636e<\/div>\n                    <div class=\"output-content\" id=\"tcp-request-output\">\n                        <span class=\"placeholder\">\u70b9\u51fb\"\u751f\u6210\u8bf7\u6c42\"\u6309\u94ae\u751f\u6210<\/span>\n                    <\/div>\n                    <button class=\"btn btn-small btn-copy\" data-target=\"#tcp-request-output\">\u590d\u5236<\/button>\n                <\/div>\n\n                <!-- TCP \u8bf7\u6c42\u5386\u53f2\u8bb0\u5f55 -->\n                <div id=\"tcp-request-history-container\" style=\"margin-top:15px; display:none;\">\n                    <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;\">\n                        <h3 style=\"margin:0; font-size:14px;\">\ud83d\udccb \u8bf7\u6c42\u5386\u53f2\u8bb0\u5f55 (<span id=\"tcp-request-history-count\">0<\/span>)<\/h3>\n                        <div style=\"display:flex; gap:8px;\">\n                            <button class=\"btn btn-small\" id=\"tcp-copy-request-history-btn\">\u590d\u5236\u5168\u90e8<\/button>\n                            <button class=\"btn btn-small btn-danger\" id=\"tcp-clear-request-history-btn\">\u6e05\u7a7a<\/button>\n                        <\/div>\n                    <\/div>\n                    <div id=\"tcp-request-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <div style=\"text-align:center; color:#999; padding:20px;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/div>\n                    <\/div>\n                <\/div>\n\n                <div class=\"info-box\">\n                    <h3>\u8bf7\u6c42\u547d\u4ee4\u7ed3\u6784\u89e3\u6790<\/h3>\n                    <div id=\"tcp-request-structure\" class=\"structure-content\">\n                        <table class=\"structure-table\">\n                            <thead>\n                                <tr>\n                                    <th>\u5b57\u6bb5<\/th>\n                                    <th>\u503c<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody id=\"tcp-request-structure-content\">\n                                <tr><td colspan=\"2\" style=\"text-align:center;\">\u7b49\u5f85\u6570\u636e...<\/td><\/tr>\n                            <\/tbody>\n                        <\/table>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- TCP\u54cd\u5e94\u751f\u6210\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus TCP\u54cd\u5e94\u62a5\u6587\u751f\u6210\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u4e8b\u52a1\u6807\u8bc6\u7b26<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-resp-transaction-id\" value=\"0001\" placeholder=\"0001\">\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u5355\u5143\u6807\u8bc6\u7b26<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"tcp-resp-slave-id\" value=\"01\" placeholder=\"01\">\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u529f\u80fd\u7801<\/label>\n                            <select class=\"form-control\" id=\"tcp-resp-function-code\">\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"0F\">0F - \u5199\u5165\u591a\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"10\">10 - \u5199\u5165\u591a\u4e2a\u5bc4\u5b58\u5668<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u81ea\u5b9a\u4e49<\/label>\n                        <\/div>\n                    <\/div>\n\n                    <!-- TCP 0F\/10 \u4e13\u7528\u5b57\u6bb5 -->\n                    <div id=\"tcp-resp-0f10-fields\" style=\"display:none; margin-top:15px;\">\n                        <div class=\"form-row\">\n                            <div class=\"form-col\">\n                                <label>\u8d77\u59cb\u5730\u5740<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"tcp-resp-start-addr\" value=\"0001\" placeholder=\"0001\">\n                                <small>\u8bf7\u6c42\u4e2d\u7684\u8d77\u59cb\u5730\u5740<\/small>\n                            <\/div>\n                            <div class=\"form-col\">\n                                <label>\u5199\u5165\u6570\u91cf<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"tcp-resp-quantity\" value=\"000A\" placeholder=\"000A\">\n                                <small>\u8bf7\u6c42\u4e2d\u7684\u5199\u5165\u6570\u91cf<\/small>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <div id=\"tcp-registers-container\">\n                        <div class=\"form-row\">\n                            <div class=\"form-col\">\n                                <label>\u6dfb\u52a0\u6570\u636e<\/label>\n                            <\/div>\n                        <\/div>\n\n                        <div id=\"tcp-registers-list\">\n                        <\/div>\n\n                        <button type=\"button\" class=\"btn btn-secondary\" id=\"tcp-add-register-btn\">\u6dfb\u52a0\u6570\u636e<\/button>\n                    <\/div>\n\n                    <button type=\"button\" class=\"btn btn-primary\" id=\"tcp-generate-response-btn\">\u751f\u6210\u54cd\u5e94<\/button>\n                <\/div>\n\n                <div class=\"modbus-output-box\">\n                    <div class=\"output-label\">\u751f\u6210\u7684\u54cd\u5e94\u6570\u636e<\/div>\n                    <div class=\"output-content\" id=\"tcp-response-output\">\n                        <span class=\"placeholder\">\u70b9\u51fb\"\u751f\u6210\u54cd\u5e94\"\u6309\u94ae\u751f\u6210<\/span>\n                    <\/div>\n                    <button class=\"btn btn-small btn-copy\" data-target=\"#tcp-response-output\">\u590d\u5236<\/button>\n                <\/div>\n\n                <div class=\"info-box\">\n                    <h3>\u54cd\u5e94\u7ed3\u6784\u89e3\u6790<\/h3>\n                    <div id=\"tcp-response-structure\" class=\"structure-content\">\n                        <table class=\"structure-table\">\n                            <thead>\n                                <tr>\n                                    <th>\u5b57\u6bb5<\/th>\n                                    <th>\u503c<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody id=\"tcp-response-structure-content\">\n                                <tr><td colspan=\"2\" style=\"text-align:center;\">\u7b49\u5f85\u6570\u636e...<\/td><\/tr>\n                            <\/tbody>\n                        <\/table>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n\n                <!-- TCP \u54cd\u5e94\u5386\u53f2\u8bb0\u5f55 -->\n                <div class=\"modbus-section\" id=\"tcp-response-history-container\" style=\"margin-top:20px;\">\n                    <h3>\ud83d\udccb TCP \u54cd\u5e94\u5386\u53f2\u8bb0\u5f55 (<span id=\"tcp-response-history-count\">0<\/span>)<\/h3>\n                    <div id=\"tcp-response-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <p style=\"color:#999; text-align:center;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/p>\n                    <\/div>\n                    <div style=\"margin-top:10px;\">\n                        <button class=\"btn btn-small\" onclick=\"ModbusTools.loadHistory('tcp-response')\">\u5237\u65b0\u5386\u53f2<\/button>\n                        <button class=\"btn btn-small btn-secondary\" onclick=\"ModbusTools.clearHistory('tcp-response'); ModbusTools.loadHistory('tcp-response')\">\u6e05\u7a7a\u5386\u53f2<\/button>\n                    <\/div>\n                <\/div>\n            <!-- TCP\u62a5\u6587\u89e3\u6790\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus TCP\u62a5\u6587\u89e3\u6790\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <label>\u8f93\u5165\u6570\u636e<\/label>\n                    <p style=\"font-size:12px;color:#666;\">\u8f93\u5165Modbus TCP\u6570\u636e\uff08\u4f8b\u5982\uff1a00 01 00 00 00 0F 01 03 0C 40 48 F5 C3 00 00 01 3A C6 FE FF FF\uff09<\/p>\n                    <textarea class=\"form-control\" id=\"tcp-parse-input\" rows=\"3\" placeholder=\"\u8f93\u5165Modbus TCP\u6570\u636e...\"><\/textarea>\n\n                    <div style=\"margin-top:10px;\">\n                        <button class=\"btn btn-primary\" id=\"tcp-parse-btn\">\u89e3\u6790<\/button>\n                        <button class=\"btn btn-secondary\" id=\"tcp-parse-clear-btn\">\u6e05\u9664<\/button>\n                        <button class=\"btn btn-secondary\" id=\"tcp-parse-example-btn\">\u793a\u4f8b\u6570\u636e<\/button>\n                    <\/div>\n                <\/div>\n\n                <div id=\"tcp-parse-result\" style=\"display:none;\">\n                    <div class=\"info-box\">\n                        <h3>\u89e3\u6790\u89c4\u5219\u914d\u7f6e<\/h3>\n                        <div class=\"modbus-form-group\">\n                            <div id=\"tcp-rules-container\">\n                            <\/div>\n                            <button class=\"btn btn-secondary\" id=\"tcp-add-rule-btn\">\u6dfb\u52a0\u89c4\u5219<\/button>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"modbus-output-box\">\n                        <div class=\"output-label\">\u89e3\u6790\u7ed3\u679c<\/div>\n                        <div id=\"tcp-parse-output\" class=\"parse-result-content\">\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n                            <\/div>\r\n                \r\n                <!-- Modbus ASCII \u9009\u9879\u5361 -->\r\n                                    <div id=\"ascii-tab\" class=\"modbus-tab-content \">\r\n                                <div class=\"modbus-ascii-container\">\n            <!-- ASCII\u8bf7\u6c42\u751f\u6210\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus ASCII\u8bf7\u6c42\u547d\u4ee4\u751f\u6210\u5668 <span class=\"mini-program-badge\" style=\"position:relative;display:inline-block;font-size:16px;color:#e53935;font-weight:bold;cursor:pointer;margin-left:10px;\" onmouseover=\"this.querySelector('img').style.display='block'\" onmouseout=\"this.querySelector('img').style.display='none'\">\u5c0f\u7a0b\u5e8f\u7248<img decoding=\"async\" src=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" style=\"display:none;position:absolute;left:0;top:25px;z-index:9999;max-width:300px;border:1px solid #ccc;box-shadow:0 2px 10px rgba(0,0,0,0.2);border-radius:4px;\"\/ loading=\"lazy\" title=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" alt=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" \/><\/span><\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>HEX<br><small>\u5341\u516d\u8fdb\u5236<\/small><\/label>\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>DEC<br><small>\u5341\u8fdb\u5236<\/small><\/label>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u4ece\u7ad9\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"ascii-slave-id\" value=\"01\" placeholder=\"01\">\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u529f\u80fd\u7801<\/label>\n                            <select class=\"form-control\" id=\"ascii-function-code\">\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"0F\">0F - \u5199\u5165\u591a\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"10\">10 - \u5199\u5165\u591a\u4e2a\u5bc4\u5b58\u5668<\/option>\n                            <\/select>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u81ea\u5b9a\u4e49<\/label>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u8d77\u59cb\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"ascii-start-address\" value=\"0001\" placeholder=\"0001\">\n                        <\/div>\n                        <!-- \u6570\u91cf\u5b57\u6bb5\uff08\u8bfb\u53d6\u529f\u80fd\u7801\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"ascii-field-quantity\" style=\"width:170px; min-width:170px;\">\n                            <label>\u6570\u91cf<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"ascii-quantity\" value=\"0002\" placeholder=\"0002\">\n                            <small>\u8bfb\u53d6\u6570\u91cf<\/small>\n                        <\/div>\n                        <!-- \u7ebf\u5708\u72b6\u6001\uff08\u529f\u80fd\u780105\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"ascii-field-coil-status\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u7ebf\u5708\u72b6\u6001<\/label>\n                            <select class=\"form-control\" id=\"ascii-coil-status\">\n                                <option value=\"0000\">\u5173\u95ed (OFF)<\/option>\n                                <option value=\"FF00\">\u6253\u5f00 (ON)<\/option>\n                            <\/select>\n                            <small>\u7ebf\u5708\u5f00\u5173\u72b6\u6001<\/small>\n                        <\/div>\n                        <!-- \u5bc4\u5b58\u5668\u503c\uff08\u529f\u80fd\u780106\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"ascii-field-register-value\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u5bc4\u5b58\u5668\u503c<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"ascii-register-value\" value=\"0000\" placeholder=\"0000-FFFF\">\n                            <small>\u5bc4\u5b58\u5668\u6570\u503c<\/small>\n                        <\/div>\n                        <!-- \u7ebf\u5708\u6570\u91cf\uff08\u529f\u80fd\u78010F\u65f6\u663e\u793a\uff09 -->\n                        <div class=\"form-col\" id=\"ascii-coil-quantity-col\" style=\"display:none; width:170px; min-width:170px;\">\n                            <label>\u7ebf\u5708\u6570\u91cf(DEC)<\/label>\n                            <input type=\"number\" class=\"form-control\" id=\"ascii-coil-quantity\" value=\"1\" min=\"1\" max=\"2000\" placeholder=\"1\">\n                            <small>\u8bbe\u7f6e\u7ebf\u5708\u6570\u91cf<\/small>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u7ebf\u5708\u9009\u62e9\u5668\uff08\u53ea\u5728\u529f\u80fd\u78010F\u65f6\u663e\u793a\uff09 -->\n                    <div id=\"ascii-coil-selector-container\" style=\"display:none; margin-top:15px; padding:15px; background:#f9f9f9; border:1px solid #ddd; border-radius:4px;\">\n                        <label style=\"font-weight:bold; display:block; margin-bottom:10px;\">\u7ebf\u5708\u9009\u62e9<\/label>\n                        <div style=\"display:flex; gap:20px;\">\n                            <!-- \u7ebf\u5708\u6309\u94ae\u533a\u57df -->\n                            <div id=\"ascii-coil-buttons\" style=\"flex:1;\"><\/div>\n                            <!-- \u5341\u516d\u8fdb\u5236\u503c\u663e\u793a\u533a\u57df -->\n                            <div style=\"min-width:150px;\">\n                                <div id=\"ascii-coil-hex-display\" style=\"font-family:monospace; font-size:14px; font-weight:bold; line-height:1.8;\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u5bc4\u5b58\u5668\u7f16\u8f91\u5668\uff08\u53ea\u5728\u529f\u80fd\u780110\u65f6\u663e\u793a\uff09 -->\n                    <div id=\"ascii-register-editor-container\" style=\"display:none; margin-top:15px; padding:15px; background:#f9f9f9; border:1px solid #ddd; border-radius:4px;\">\n                        <label style=\"font-weight:bold; display:block; margin-bottom:10px;\">\u6dfb\u52a0\u5bc4\u5b58\u5668<\/label>\n                        <table style=\"width:100%; border-collapse:collapse; margin-bottom:10px;\">\n                            <thead>\n                                <tr style=\"background-color:#f0f0f0; border-bottom:2px solid #ccc;\">\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u5bc4\u5b58\u5668\u5730\u5740<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u6570\u636e\u7c7b\u578b<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u5b57\u8282\u5e8f<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u6570\u503c(\u5341\u8fdb\u5236)<\/th>\n                                    <th style=\"padding:8px; text-align:left; border:1px solid #ddd;\">\u64cd\u4f5c<\/th>\n                                <\/tr>\n                            <\/thead>\n                            <tbody id=\"ascii-register-items\">\n                                <tr class=\"ascii-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control ascii-register-address\" value=\"0001\" placeholder=\"0001\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control ascii-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><option value=\"UINT64\">UINT64<\/option><option value=\"INT64\">INT64<\/option><option value=\"FLOAT64\">FLOAT64<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control ascii-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control ascii-register-value\" value=\"20\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-ascii-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                                <tr class=\"ascii-register-row\">\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"text\" class=\"form-control ascii-register-address\" value=\"0002\" placeholder=\"0002\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control ascii-register-type\"><option value=\"UINT16\">UINT16<\/option><option value=\"INT16\">INT16<\/option><option value=\"UINT32\">UINT32<\/option><option value=\"INT32\">INT32<\/option><option value=\"FLOAT32\">FLOAT32<\/option><option value=\"UINT64\">UINT64<\/option><option value=\"INT64\">INT64<\/option><option value=\"FLOAT64\">FLOAT64<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><select class=\"form-control ascii-register-order\"><option value=\"ABCD\">ABCD<\/option><option value=\"DCBA\">DCBA<\/option><option value=\"BADC\">BADC<\/option><option value=\"CDAB\">CDAB<\/option><\/select><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><input type=\"number\" class=\"form-control ascii-register-value\" value=\"0\" placeholder=\"\u8f93\u5165\u5341\u8fdb\u5236\u6570\u503c\"><\/td>\n                                    <td style=\"padding:8px; border:1px solid #ddd;\"><button class=\"btn btn-small btn-remove-ascii-register-row\">\u79fb\u9664<\/button><\/td>\n                                <\/tr>\n                            <\/tbody>\n                        <\/table>\n                        <button class=\"btn btn-secondary\" id=\"ascii-add-register-row-btn\">+ \u6dfb\u52a0\u5bc4\u5b58\u5668<\/button>\n                    <\/div>\n\n                    <div class=\"form-row\" style=\"margin-top:15px;\">\n                        <button class=\"btn btn-primary\" id=\"ascii-generate-request-btn\">\u751f\u6210\u8bf7\u6c42<\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"modbus-output-box\">\n                    <div class=\"output-label\">\u751f\u6210\u7684\u8bf7\u6c42\u547d\u4ee4<\/div>\n                    <div class=\"output-content\" id=\"ascii-request-output\">\n                        <span class=\"placeholder\">\u70b9\u51fb\"\u751f\u6210\u8bf7\u6c42\"\u6309\u94ae\u751f\u6210<\/span>\n                    <\/div>\n                    <button class=\"btn btn-small btn-copy\" data-target=\"#ascii-request-output\">\u590d\u5236<\/button>\n                <\/div>\n\n                <!-- ASCII \u8bf7\u6c42\u5386\u53f2\u8bb0\u5f55 -->\n                <div id=\"ascii-request-history-container\" style=\"margin-top:15px; display:none;\">\n                    <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;\">\n                        <h3 style=\"margin:0; font-size:14px;\">\ud83d\udccb \u8bf7\u6c42\u5386\u53f2\u8bb0\u5f55 (<span id=\"ascii-request-history-count\">0<\/span>)<\/h3>\n                        <div style=\"display:flex; gap:8px;\">\n                            <button class=\"btn btn-small\" id=\"ascii-copy-request-history-btn\">\u590d\u5236\u5168\u90e8<\/button>\n                            <button class=\"btn btn-small btn-danger\" id=\"ascii-clear-request-history-btn\">\u6e05\u7a7a<\/button>\n                        <\/div>\n                    <\/div>\n                    <div id=\"ascii-request-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <div style=\"text-align:center; color:#999; padding:20px;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/div>\n                    <\/div>\n                <\/div>\n\n                <div class=\"info-box\">\n                    <h3>\u8bf7\u6c42\u547d\u4ee4\u7ed3\u6784\u89e3\u6790<\/h3>\n                    <table class=\"structure-table\">\n                        <tbody id=\"ascii-request-structure-content\">\n                            <tr><td colspan=\"2\" style=\"text-align:center;\">\u7b49\u5f85\u6570\u636e...<\/td><\/tr>\n                        <\/tbody>\n                    <\/table>\n                <\/div>\n            <\/div>\n\n            <!-- ASCII\u54cd\u5e94\u751f\u6210\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus ASCII\u54cd\u5e94\u62a5\u6587\u751f\u6210\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>HEX<br><small>\u5341\u516d\u8fdb\u5236<\/small><\/label>\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>DEC<br><small>\u5341\u8fdb\u5236<\/small><\/label>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u4ece\u7ad9\u5730\u5740<\/label>\n                            <input type=\"text\" class=\"form-control\" id=\"ascii-resp-slave-id\" value=\"01\" placeholder=\"01\">\n                        <\/div>\n                        <div class=\"form-col\">\n                            <label>\u529f\u80fd\u7801<\/label>\n                            <select class=\"form-control\" id=\"ascii-resp-function-code\">\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\n                                <option value=\"0F\">0F - \u5199\u5165\u591a\u4e2a\u7ebf\u5708<\/option>\n                                <option value=\"10\">10 - \u5199\u5165\u591a\u4e2a\u5bc4\u5b58\u5668<\/option>\n                            <\/select>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"form-row\">\n                        <div class=\"form-col\">\n                            <label>\u81ea\u5b9a\u4e49<\/label>\n                        <\/div>\n                    <\/div>\n\n                    <!-- ASCII 0F\/10 \u4e13\u7528\u5b57\u6bb5 -->\n                    <div id=\"ascii-resp-0f10-fields\" style=\"display:none; margin-top:15px;\">\n                        <div class=\"form-row\">\n                            <div class=\"form-col\">\n                                <label>\u8d77\u59cb\u5730\u5740<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"ascii-resp-start-addr\" value=\"0001\" placeholder=\"0001\">\n                                <small>\u8bf7\u6c42\u4e2d\u7684\u8d77\u59cb\u5730\u5740<\/small>\n                            <\/div>\n                            <div class=\"form-col\">\n                                <label>\u5199\u5165\u6570\u91cf<\/label>\n                                <input type=\"text\" class=\"form-control\" id=\"ascii-resp-quantity\" value=\"000A\" placeholder=\"000A\">\n                                <small>\u8bf7\u6c42\u4e2d\u7684\u5199\u5165\u6570\u91cf<\/small>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <div id=\"ascii-registers-container\">\n                        <div class=\"form-row\">\n                            <div class=\"form-col\">\n                                <label>\u6dfb\u52a0\u6570\u636e<\/label>\n                            <\/div>\n                        <\/div>\n\n                        <div id=\"ascii-registers-list\">\n                        <\/div>\n\n                        <button type=\"button\" class=\"btn btn-secondary\" id=\"ascii-add-register-btn\">\u6dfb\u52a0\u6570\u636e<\/button>\n                    <\/div>\n\n                    <button type=\"button\" class=\"btn btn-primary\" id=\"ascii-generate-response-btn\">\u751f\u6210\u54cd\u5e94<\/button>\n                <\/div>\n\n                <div class=\"modbus-output-box\">\n                    <div class=\"output-label\">\u751f\u6210\u7684\u54cd\u5e94\u6570\u636e<\/div>\n                    <div class=\"output-content\" id=\"ascii-response-output\">\n                        <span class=\"placeholder\">\u70b9\u51fb\"\u751f\u6210\u54cd\u5e94\"\u6309\u94ae\u751f\u6210<\/span>\n                    <\/div>\n                    <button class=\"btn btn-small btn-copy\" data-target=\"#ascii-response-output\">\u590d\u5236<\/button>\n                <\/div>\n\n\n                <!-- ASCII \u54cd\u5e94\u5386\u53f2\u8bb0\u5f55 -->\n                <div class=\"modbus-section\" id=\"ascii-response-history-container\" style=\"margin-top:20px; display:none;\">\n                    <h3>\ud83d\udccb ASCII \u54cd\u5e94\u5386\u53f2\u8bb0\u5f55 (<span id=\"ascii-response-history-count\">0<\/span>)<\/h3>\n                    <div id=\"ascii-response-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <p style=\"color:#999; text-align:center;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/p>\n                    <\/div>\n                    <div style=\"margin-top:10px;\">\n                        <button class=\"btn btn-small\" onclick=\"ModbusTools.loadHistory('ascii-response')\">\u5237\u65b0\u5386\u53f2<\/button>\n                        <button class=\"btn btn-small btn-secondary\" onclick=\"ModbusTools.clearHistory('ascii-response'); ModbusTools.loadHistory('ascii-response')\">\u6e05\u7a7a\u5386\u53f2<\/button>\n                    <\/div>\n                <\/div>\n                <div class=\"info-box\">\n                    <h3>\u54cd\u5e94\u7ed3\u6784\u89e3\u6790<\/h3>\n                    <table class=\"structure-table\">\n                        <tbody id=\"ascii-response-structure-content\">\n                            <tr><td colspan=\"2\" style=\"text-align:center;\">\u7b49\u5f85\u6570\u636e...<\/td><\/tr>\n                        <\/tbody>\n                    <\/table>\n                <\/div>\n            <\/div>\n\n            <!-- ASCII\u62a5\u6587\u89e3\u6790\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus ASCII\u62a5\u6587\u89e3\u6790\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <label>\u8f93\u5165\u6570\u636e<\/label>\n                    <p style=\"font-size:12px;color:#666;\">\u8f93\u5165Modbus ASCII\u6570\u636e\uff08\u4f8b\u5982\uff1a:01030C4048F5C30000013AC6FEFFFFB3\uff09<\/p>\n                    <textarea class=\"form-control\" id=\"ascii-parse-input\" rows=\"3\" placeholder=\"\u8f93\u5165Modbus ASCII\u6570\u636e...\"><\/textarea>\n\n                    <div style=\"margin-top:10px;\">\n                        <button class=\"btn btn-primary\" id=\"ascii-parse-btn\">\u89e3\u6790<\/button>\n                        <button class=\"btn btn-secondary\" id=\"ascii-parse-clear-btn\">\u6e05\u9664<\/button>\n                        <button class=\"btn btn-secondary\" id=\"ascii-parse-example-btn\">\u793a\u4f8b\u6570\u636e<\/button>\n                    <\/div>\n                <\/div>\n\n                <div id=\"ascii-parse-result\" style=\"display:none;\">\n                    <div class=\"modbus-output-box\">\n                        <div class=\"output-label\">\u89e3\u6790\u7ed3\u679c<\/div>\n                        <div id=\"ascii-parse-output\" class=\"parse-result-content\">\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- ASCII LRC\u6821\u9a8c\u7801\u8ba1\u7b97\u5668 -->\n            <div class=\"modbus-section\">\n                <h2>Modbus ASCII LRC\u6821\u9a8c\u7801\u8ba1\u7b97\u5668<\/h2>\n\n                <div class=\"modbus-form-group\">\n                    <label>\u8f93\u5165\u547d\u4ee4\uff08\u4e0d\u542bLRC\uff09<\/label>\n                    <p style=\"font-size:12px;color:#666;\">\u8f93\u5165\u5341\u516d\u8fdb\u5236\u6570\u636e\uff0c\u7528\u7a7a\u683c\u5206\u9694\uff08\u4f8b\u5982\uff1a01 03 00 01 00 02\uff09<\/p>\n                    <textarea class=\"form-control\" id=\"ascii-lrc-input\" rows=\"3\" placeholder=\"01 03 00 01 00 02\"><\/textarea>\n\n                    <div style=\"margin-top:10px;\">\n                        <button type=\"button\" class=\"btn btn-primary\" id=\"ascii-lrc-calculate-btn\">\u8ba1\u7b97LRC<\/button>\n                        <button type=\"button\" class=\"btn btn-secondary\" id=\"ascii-lrc-clear-btn\">\u6e05\u9664<\/button>\n                    <\/div>\n                <\/div>\n\n                <!-- LRC \u5386\u53f2\u8bb0\u5f55 -->\n                <div class=\"modbus-section\" style=\"margin-top:20px;\">\n                    <h3>\ud83d\udccb LRC \u5386\u53f2\u8bb0\u5f55<\/h3>\n                    <div id=\"lrc-history-list\" style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:4px; padding:10px; background:#f9f9f9;\">\n                        <p style=\"color:#999; text-align:center;\">\u6682\u65e0\u5386\u53f2\u8bb0\u5f55<\/p>\n                    <\/div>\n                    <div style=\"margin-top:10px;\">\n                        <button class=\"btn btn-small\" onclick=\"ModbusTools.loadHistory('lrc')\">\u5237\u65b0\u5386\u53f2<\/button>\n                        <button class=\"btn btn-small btn-secondary\" onclick=\"ModbusTools.clearHistory('lrc'); ModbusTools.loadHistory('lrc')\">\u6e05\u7a7a\u5386\u53f2<\/button>\n                    <\/div>\n                <\/div>\n\n                <div id=\"ascii-lrc-result\" style=\"display:none;\">\n                    <div class=\"modbus-output-box\">\n                        <div class=\"output-label\">\u8ba1\u7b97\u7ed3\u679c<\/div>\n                        <div id=\"ascii-lrc-output\" class=\"info-box\">\n                            <div style=\"padding:10px;\">\n                                <p><strong>LRC\u6821\u9a8c\u7801:<\/strong> <span id=\"ascii-lrc-value\" style=\"font-family:monospace;font-size:14px;color:#0073aa;\"><\/span><\/p>\n                                <p><strong>\u5b8c\u6574\u547d\u4ee4:<\/strong> <span id=\"ascii-lrc-full\" style=\"font-family:monospace;font-size:12px;\"><\/span><\/p>\n                                <p><strong>ASCII\u8f93\u51fa:<\/strong> <span id=\"ascii-lrc-ascii\" style=\"font-family:monospace;font-size:12px;word-break:break-all;\"><\/span><\/p>\n                            <\/div>\n                        <\/div>\n                        <button class=\"btn btn-small btn-copy\" data-target=\"#ascii-lrc-ascii\">\u590d\u5236<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- ASCII\u683c\u5f0f\u8bf4\u660e -->\n            <div class=\"modbus-section\">\n                <div class=\"info-box\">\n                    <h3>Modbus ASCII\u683c\u5f0f\u8bf4\u660e<\/h3>\n                    <ul>\n                        <li><strong>\u5f00\u59cb\u6807\u8bb0\uff1a<\/strong>\u5192\u53f7 (:)<\/li>\n                        <li><strong>\u7ed3\u675f\u6807\u8bb0\uff1a<\/strong>CR LF (\u56de\u8f66\u6362\u884c)<\/li>\n                        <li><strong>\u6821\u9a8c\u65b9\u5f0f\uff1a<\/strong>LRC\uff08\u7eb5\u5411\u5197\u4f59\u6821\u9a8c\uff09\u66ff\u4ee3CRC<\/li>\n                        <li><strong>\u7f16\u7801\u65b9\u5f0f\uff1a<\/strong>\u6240\u6709\u6570\u636e\u4f7f\u7528ASCII\u5b57\u7b26\u8868\u793a<\/li>\n                        <li><strong>\u6570\u636e\u683c\u5f0f\uff1a<\/strong>:NNFFAADDRQQLRCCC (N=\u4ece\u7ad9, FF=\u529f\u80fd\u7801, AA=\u8d77\u59cb\u5730\u5740, DD=\u6570\u636e, RR=\u957f\u5ea6, LRC=\u6821\u9a8c\u7801)<\/li>\n                        <li><strong>\u4f18\u70b9\uff1a<\/strong>\u6613\u4e8e\u8c03\u8bd5\uff0c\u652f\u6301\u66f4\u591a\u8bbe\u5907\uff0c\u6613\u4e8e\u901a\u8fc7\u4e32\u53e3\u4f20\u8f93<\/li>\n                    <\/ul>\n                <\/div>\n            <\/div>\n        <\/div>\n                            <\/div>\r\n                \r\n                <!-- Modbus \u8c03\u8bd5 \u9009\u9879\u5361 -->\r\n                                    <div id=\"debug-tab\" class=\"modbus-tab-content \">\r\n                                <div class=\"modbus-debugger-container\">\r\n            <!-- \u7b2c\u4e00\u884c\uff1a\u4e32\u53e3\u914d\u7f6e -->\r\n            <div class=\"modbus-section\">\r\n                <h3>\u4e32\u53e3\u914d\u7f6e<\/h3>\r\n                <div class=\"form-group\">\r\n                    <!-- \u7b2c\u4e00\u884c\uff1a\u6ce2\u7279\u7387\u3001\u6570\u636e\u4f4d\u3001\u505c\u6b62\u4f4d\u3001\u6821\u9a8c\u4f4d -->\r\n                    <div class=\"form-row\">\r\n                        <div class=\"form-col\">\r\n                            <label>\u6ce2\u7279\u7387<\/label>\r\n                            <select class=\"form-control\" id=\"debug-baudrate\">\r\n                                <option value=\"300\">300<\/option>\r\n                                <option value=\"600\">600<\/option>\r\n                                <option value=\"1200\">1200<\/option>\r\n                                <option value=\"2400\">2400<\/option>\r\n                                <option value=\"4800\">4800<\/option>\r\n                                <option value=\"9600\" selected>9600<\/option>\r\n                                <option value=\"14400\">14400<\/option>\r\n                                <option value=\"19200\">19200<\/option>\r\n                                <option value=\"28800\">28800<\/option>\r\n                                <option value=\"38400\">38400<\/option>\r\n                                <option value=\"57600\">57600<\/option>\r\n                                <option value=\"76800\">76800<\/option>\r\n                                <option value=\"115200\">115200<\/option>\r\n                                <option value=\"230400\">230400<\/option>\r\n                                <option value=\"460800\">460800<\/option>\r\n                                <option value=\"921600\">921600<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>\u6570\u636e\u4f4d<\/label>\r\n                            <select class=\"form-control\" id=\"debug-databits\">\r\n                                <option value=\"5\">5<\/option>\r\n                                <option value=\"6\">6<\/option>\r\n                                <option value=\"7\">7<\/option>\r\n                                <option value=\"8\" selected>8<\/option>\r\n                                <option value=\"9\">9<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>\u505c\u6b62\u4f4d<\/label>\r\n                            <select class=\"form-control\" id=\"debug-stopbits\">\r\n                                <option value=\"0.5\">0.5<\/option>\r\n                                <option value=\"1\" selected>1<\/option>\r\n                                <option value=\"1.5\">1.5<\/option>\r\n                                <option value=\"2\">2<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>\u6821\u9a8c\u4f4d<\/label>\r\n                            <select class=\"form-control\" id=\"debug-parity\">\r\n                                <option value=\"none\" selected>None - \u65e0\u6821\u9a8c<\/option>\r\n                                <option value=\"odd\">Odd - \u5947\u6821\u9a8c<\/option>\r\n                                <option value=\"even\">Even - \u5076\u6821\u9a8c<\/option>\r\n                                <option value=\"mark\">Mark - \u6807\u8bb0\u4f4d<\/option>\r\n                                <option value=\"space\">Space - \u7a7a\u683c\u4f4d<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                    <\/div>\r\n\r\n                    <!-- \u7b2c\u4e8c\u884c\uff1a\u4e32\u53e3\u9009\u62e9\u3001\u5237\u65b0\u3001\u8bf7\u6c42\u8bbe\u5907\u3001\u8fde\u63a5 -->\r\n                    <div class=\"form-row\">\r\n                        <div class=\"form-col\" style=\"flex: 2;\">\r\n                            <label>\u9009\u62e9\u4e32\u53e3<\/label>\r\n                            <select class=\"form-control\" id=\"debug-port\">\r\n                                <option value=\"\">-- \u672a\u68c0\u6d4b\u5230\u4e32\u53e3\uff0c\u70b9\u51fb\"\u8bf7\u6c42\u8bbe\u5907\"\u6309\u94ae --<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>&nbsp;<\/label>\r\n                            <button class=\"btn btn-info\" id=\"debug-request-port\" style=\"width:100%;\">\u8bf7\u6c42\u8bbe\u5907<\/button>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>&nbsp;<\/label>\r\n                            <button class=\"btn btn-secondary\" id=\"debug-refresh-ports\" style=\"width:100%;\">\u5237\u65b0<\/button>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>&nbsp;<\/label>\r\n                            <button class=\"btn btn-primary\" id=\"debug-connect-btn\" style=\"width:100%;\">\u8fde\u63a5<\/button>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- \u65e5\u5fd7\u914d\u7f6e\uff08\u7b2c\u4e00\u884c\uff09 -->\r\n            <div class=\"modbus-section\" style=\"margin-bottom:15px; padding-bottom:0;\">\r\n                <h3 style=\"margin-bottom:10px;\">\u65e5\u5fd7\u4fe1\u606f<\/h3>\r\n                <div class=\"form-group\">\r\n                    <div class=\"form-row\">\r\n                        <div class=\"form-col\" style=\"flex: 0 0 auto; min-width: auto;\">\r\n                            <label style=\"margin-bottom:8px;\">\u81ea\u52a8\u6e05\u7406<\/label>\r\n                            <div class=\"checkbox\">\r\n                                <label style=\"margin-bottom:0;\">\r\n                                    <input type=\"checkbox\" id=\"debug-auto-clear\"> \u542f\u7528\r\n                                <\/label>\r\n                            <\/div>\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 120px;\">\r\n                            <label>\u6700\u5927\u6570\u91cf<\/label>\r\n                            <input type=\"number\" class=\"form-control\" id=\"debug-max-logs\" value=\"1000\" min=\"100\" style=\"padding:5px; font-size:12px;\">\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 100px;\">\r\n                            <label>\u663e\u793a\u683c\u5f0f<\/label>\r\n                            <select class=\"form-control\" id=\"debug-log-format\" style=\"padding:5px; font-size:12px;\">\r\n                                <option value=\"HEX\" selected>HEX<\/option>\r\n                                <option value=\"DEC\">DEC<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 1; min-width: auto;\">\r\n                            <!-- \u5360\u4f4d\u7b26 -->\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- Modbus\u6a21\u5f0f\uff08\u7b2c\u4e8c\u884c\uff09 -->\r\n            <div class=\"modbus-section\" style=\"margin-bottom:15px; padding-bottom:0;\">\r\n                <h3 style=\"margin-bottom:10px;\">Modbus\u6a21\u5f0f<\/h3>\r\n                <div class=\"form-group\">\r\n                    <div class=\"form-row\">\r\n                        <div class=\"form-col\" style=\"flex: 0 0 auto; min-width: auto;\">\r\n                            <label style=\"margin-bottom:8px;\">\u8f93\u5165\u683c\u5f0f<\/label>\r\n                            <div style=\"display:flex; gap:10px; margin-top:0;\">\r\n                                <label style=\"margin-bottom:0;\">\r\n                                    <input type=\"radio\" name=\"debug-input-format\" value=\"HEX\" checked> HEX\r\n                                <\/label>\r\n                                <label style=\"margin-bottom:0;\">\r\n                                    <input type=\"radio\" name=\"debug-input-format\" value=\"DEC\"> DEC\r\n                                <\/label>\r\n                            <\/div>\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 100px;\">\r\n                            <label>\u4ece\u7ad9\u5730\u5740<\/label>\r\n                            <input type=\"text\" class=\"form-control\" id=\"debug-slave-id\" value=\"01\" placeholder=\"01\" style=\"padding:5px; font-size:12px;\">\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 auto; min-width: 200px;\">\r\n                            <label>\u529f\u80fd\u7801<\/label>\r\n                            <select class=\"form-control\" id=\"debug-func-code\" style=\"padding:5px; font-size:12px;\">\r\n                                <option value=\"03\" selected>03 - \u8bfb\u53d6\u4fdd\u6301\u5bc4\u5b58\u5668<\/option>\r\n                                <option value=\"01\">01 - \u8bfb\u53d6\u7ebf\u5708\u72b6\u6001<\/option>\r\n                                <option value=\"02\">02 - \u8bfb\u53d6\u79bb\u6563\u8f93\u5165<\/option>\r\n                                <option value=\"04\">04 - \u8bfb\u53d6\u8f93\u5165\u5bc4\u5b58\u5668<\/option>\r\n                                <option value=\"05\">05 - \u5199\u5165\u5355\u4e2a\u7ebf\u5708<\/option>\r\n                                <option value=\"06\">06 - \u5199\u5165\u5355\u4e2a\u5bc4\u5b58\u5668<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 100px;\">\r\n                            <label>\u8d77\u59cb\u5730\u5740<\/label>\r\n                            <input type=\"text\" class=\"form-control\" id=\"debug-start-addr\" value=\"0000\" placeholder=\"0000\" style=\"padding:5px; font-size:12px;\">\r\n                        <\/div>\r\n                        <!-- \u6570\u91cf\u5b57\u6bb5\uff08\u9ed8\u8ba4\u663e\u793a\uff09 -->\r\n                        <div class=\"form-col\" style=\"flex: 0 0 160px;\" id=\"debug-quantity-col\">\r\n                            <label>\u6570\u91cf<\/label>\r\n                            <input type=\"text\" class=\"form-control\" id=\"debug-quantity\" value=\"0001\" placeholder=\"0001\" style=\"padding:5px; font-size:12px;\">\r\n                        <\/div>\r\n                        <!-- \u7ebf\u5708\u72b6\u6001\u5b57\u6bb5\uff08\u529f\u80fd\u780105\uff09 -->\r\n                        <div class=\"form-col\" style=\"flex: 0 0 160px; display: none !important;\" id=\"debug-coil-status-col\">\r\n                            <label>\u7ebf\u5708\u72b6\u6001<\/label>\r\n                            <select class=\"form-control\" id=\"debug-coil-status\" style=\"padding:5px; font-size:12px;\">\r\n                                <option value=\"0000\">\u5173\u95ed (OFF)<\/option>\r\n                                <option value=\"FF00\">\u6253\u5f00 (ON)<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <!-- \u5bc4\u5b58\u5668\u503c\u5b57\u6bb5\uff08\u529f\u80fd\u780106\uff09 -->\r\n                        <div class=\"form-col\" style=\"flex: 0 0 160px; display: none !important;\" id=\"debug-register-value-col\">\r\n                            <label>\u5bc4\u5b58\u5668\u503c<\/label>\r\n                            <input type=\"text\" class=\"form-control\" id=\"debug-register-value\" value=\"0000\" placeholder=\"0000-FFFF\" style=\"padding:5px; font-size:12px;\">\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 auto; min-width: auto;\">\r\n                            <label>\u5faa\u73af\u53d1\u9001<\/label>\r\n                            <div style=\"display:flex; gap:3px; align-items:center;\">\r\n                                <input type=\"number\" class=\"form-control\" id=\"debug-loop-interval\" value=\"5000\" min=\"100\" style=\"width:70px; padding:5px; font-size:12px;\">\r\n                                <span style=\"padding:5px; font-size:12px;\">MS<\/span>\r\n                                <button class=\"btn btn-warning\" id=\"debug-add-command-btn\" style=\"padding:5px 12px; font-size:12px; white-space:nowrap;\">\u2795 \u589e\u52a0<\/button>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- \u751f\u6210\u7684\u547d\u4ee4\uff08\u652f\u6301\u5355\u6761\u6216\u591a\u6761\u663e\u793a\uff09 -->\r\n            <div class=\"modbus-section\" style=\"margin-top:10px; margin-bottom:10px;\">\r\n                <h3 style=\"margin-bottom:8px;\">\r\n                    \u751f\u6210\u7684\u547d\u4ee4\r\n                    <button class=\"btn btn-small\" id=\"debug-toggle-edit-mode\" style=\"float:right; padding:3px 8px; font-size:11px;\">\u7f16\u8f91<\/button>\r\n                <\/h3>\r\n\r\n                <!-- \u663e\u793a\u6a21\u5f0f\uff1a\u5355\u6761\u6216\u591a\u6761\u547d\u4ee4 -->\r\n                <div id=\"debug-command-display-mode\">\r\n                    <div id=\"debug-commands-display\" style=\"background:#f9f9f9; padding:8px; border-radius:4px;\">\r\n                        <!-- \u547d\u4ee4\u9879\u4f1a\u52a8\u6001\u6dfb\u52a0\u5230\u8fd9\u91cc -->\r\n                        <div style=\"padding:8px; text-align:center; color:#999;\">\r\n                            <p>\u7b49\u5f85\u751f\u6210\u547d\u4ee4...<\/p>\r\n                        <\/div>\r\n                    <\/div>\r\n                    <!-- \u7b2c\u4e00\u884c\uff1a\u590d\u5236\u3001\u53d1\u9001\u3001\u5faa\u73af\u3001\u4fdd\u5b58\u6a21\u677f -->\r\n                    <div style=\"display:flex; gap:8px; margin-top:8px;\">\r\n                        <button class=\"btn btn-copy\" id=\"debug-copy-all-commands\" style=\"padding:8px 14px; font-size:12px; height:36px; line-height:20px; margin-top:0;\">\u590d\u5236<\/button>\r\n                        <button class=\"btn btn-success\" id=\"debug-send-btn\" style=\"padding:8px 14px; font-size:12px; height:36px; line-height:20px;\">\u53d1\u9001<\/button>\r\n                        <button class=\"btn btn-primary\" id=\"debug-loop-send-btn\" style=\"padding:8px 14px; font-size:12px; height:36px; line-height:20px;\">\u5faa\u73af\u53d1\u9001<\/button>\r\n                        <button class=\"btn btn-info\" id=\"debug-save-template-quick-btn\" style=\"padding:8px 14px; font-size:12px; height:36px; line-height:20px;\">\ud83d\udcbe \u4fdd\u5b58\u4e3a\u6a21\u677f<\/button>\r\n                    <\/div>\r\n\r\n                    <!-- \u7b2c\u4e8c\u884c\uff1a\u9009\u62e9\u6a21\u677f -->\r\n                    <div style=\"display:flex; gap:8px; margin-top:8px;\">\r\n                        <select id=\"debug-template-select\" class=\"form-control\" style=\"flex:1; padding:6px; font-size:12px; border:1px solid #ddd; border-radius:3px;\">\r\n                            <option value=\"\">-- \u9009\u62e9\u6a21\u677f --<\/option>\r\n                        <\/select>\r\n                        <button class=\"btn btn-sm btn-success\" id=\"debug-load-template-btn\" style=\"padding:6px 12px; font-size:12px; height:34px; line-height:20px;\">\u52a0\u8f7d<\/button>\r\n                        <button class=\"btn btn-sm btn-warning\" id=\"debug-manage-template-btn\" style=\"padding:6px 12px; font-size:12px; height:34px; line-height:20px;\">\u2699\ufe0f \u7ba1\u7406\u6a21\u677f<\/button>\r\n                        <input type=\"text\" id=\"debug-template-name-quick\" placeholder=\"\u6a21\u677f\u540d\u79f0...\" style=\"width:150px; padding:6px; border:1px solid #ddd; border-radius:3px; font-size:12px;\">\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <!-- \u7f16\u8f91\u6a21\u5f0f -->\r\n                <div id=\"debug-command-edit-mode\" style=\"display:none;\">\r\n                    <div style=\"margin-bottom:8px;\">\r\n                        <p style=\"font-size:11px; color:#666; margin-bottom:5px;\">\ud83d\udca1 \u63d0\u793a\uff1a\u652f\u6301\u7f16\u8f91\u5355\u6761\u6216\u591a\u6761\u547d\u4ee4\uff08\u6bcf\u884c\u4e00\u4e2a\uff09<\/p>\r\n                        <textarea id=\"debug-command-edit\" style=\"width:100%; height:100px; font-family:monospace; font-size:12px; padding:8px; border:1px solid #ddd; border-radius:3px; resize:vertical;\" placeholder=\"\u8f93\u5165Modbus\u547d\u4ee4\uff0c\u652f\u6301\u591a\u884c...\"><\/textarea>\r\n                    <\/div>\r\n                    <div style=\"background:#f9f9f9; padding:8px; border-radius:4px; display:flex; gap:5px;\">\r\n                        <button class=\"btn btn-primary\" id=\"debug-save-command-btn\" style=\"padding:6px 12px; font-size:12px;\">\u2713 \u4fdd\u5b58<\/button>\r\n                        <button class=\"btn btn-secondary\" id=\"debug-cancel-edit-btn\" style=\"padding:6px 12px; font-size:12px;\">\u2715 \u53d6\u6d88<\/button>\r\n                        <button class=\"btn btn-info\" id=\"debug-save-as-template-btn\" style=\"padding:6px 12px; font-size:12px;\">\ud83d\udcbe \u4fdd\u5b58\u4e3a\u6a21\u677f<\/button>\r\n                        <input type=\"text\" id=\"debug-template-name\" placeholder=\"\u6a21\u677f\u540d\u79f0...\" style=\"flex:1; padding:6px; border:1px solid #ddd; border-radius:3px; font-size:12px;\">\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <!-- \u6a21\u677f\u5217\u8868 -->\r\n                <div id=\"debug-command-list-panel\" class=\"modbus-section\" style=\"display:none; margin-top:10px; margin-bottom:0;\">\r\n                    <h4 style=\"margin-bottom:8px;\">\r\n                        \u4fdd\u5b58\u7684\u6a21\u677f\r\n                        <button class=\"btn btn-small\" id=\"debug-close-list-btn\" style=\"float:right; padding:3px 8px; font-size:11px;\">\u5173\u95ed<\/button>\r\n                    <\/h4>\r\n                    <div style=\"max-height:300px; overflow-y:auto; border:1px solid #ddd; border-radius:3px;\">\r\n                        <div id=\"debug-command-list-content\" style=\"padding:8px;\">\r\n                            <p style=\"color:#999; text-align:center;\">\u52a0\u8f7d\u5217\u8868\u4e2d...<\/p>\r\n                        <\/div>\r\n                    <\/div>\r\n                    <div style=\"margin-top:8px; display:flex; gap:5px;\">\r\n                        <button class=\"btn btn-secondary\" id=\"debug-refresh-list-btn\" style=\"padding:6px 12px; font-size:12px;\">\u5237\u65b0<\/button>\r\n                        <button class=\"btn btn-danger\" id=\"debug-clear-all-templates-btn\" style=\"padding:6px 12px; font-size:12px;\">\u6e05\u7a7a\u6240\u6709<\/button>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <!-- \u6a21\u677f\u7f16\u8f91\u5f39\u7a97 -->\r\n                <div id=\"debug-template-edit-modal\" style=\"display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.5); z-index:10000; align-items:center; justify-content:center;\">\r\n                    <div style=\"background:white; border-radius:8px; padding:20px; max-width:600px; width:90%; max-height:80vh; overflow-y:auto; box-shadow:0 4px 20px rgba(0,0,0,0.3);\">\r\n                        <h3 style=\"margin-top:0; margin-bottom:15px;\">\ud83d\udcdd \u7f16\u8f91\u6a21\u677f<\/h3>\r\n\r\n                        <!-- \u6a21\u677f\u540d\u79f0 -->\r\n                        <div style=\"margin-bottom:15px;\">\r\n                            <label style=\"display:block; margin-bottom:5px; font-weight:bold;\">\u6a21\u677f\u540d\u79f0<\/label>\r\n                            <input type=\"text\" id=\"debug-edit-template-name\" style=\"width:100%; padding:8px; border:1px solid #ddd; border-radius:4px; box-sizing:border-box;\" placeholder=\"\u8f93\u5165\u6a21\u677f\u540d\u79f0\">\r\n                        <\/div>\r\n\r\n                        <!-- \u547d\u4ee4\u7f16\u8f91 -->\r\n                        <div style=\"margin-bottom:15px;\">\r\n                            <label style=\"display:block; margin-bottom:5px; font-weight:bold;\">\u547d\u4ee4\u5217\u8868\uff08\u6bcf\u884c\u4e00\u4e2a\uff09<\/label>\r\n                            <textarea id=\"debug-edit-commands\" style=\"width:100%; height:150px; padding:8px; border:1px solid #ddd; border-radius:4px; box-sizing:border-box; font-family:monospace; font-size:12px;\" placeholder=\"01 03 00 00 00 01 84 0A\"><\/textarea>\r\n                        <\/div>\r\n\r\n                        <!-- \u547d\u4ee4\u540d\u79f0\u7f16\u8f91 -->\r\n                        <div style=\"margin-bottom:15px;\">\r\n                            <label style=\"display:block; margin-bottom:5px; font-weight:bold;\">\u547d\u4ee4\u540d\u79f0\uff08JSON\u683c\u5f0f\uff0c\u53ef\u9009\uff09<\/label>\r\n                            <textarea id=\"debug-edit-command-names\" style=\"width:100%; height:100px; padding:8px; border:1px solid #ddd; border-radius:4px; box-sizing:border-box; font-family:monospace; font-size:12px;\" placeholder=\"{&quot;0&quot;:&quot;\u547d\u4ee41&quot;,&quot;1&quot;:&quot;\u547d\u4ee42&quot;}\"><\/textarea>\r\n                        <\/div>\r\n\r\n                        <!-- \u64cd\u4f5c\u6309\u94ae -->\r\n                        <div style=\"display:flex; gap:10px; justify-content:flex-end; border-top:1px solid #eee; padding-top:15px; margin-top:15px;\">\r\n                            <button class=\"btn btn-secondary\" id=\"debug-edit-template-cancel\" style=\"padding:8px 16px; font-size:12px;\">\u53d6\u6d88<\/button>\r\n                            <button class=\"btn btn-primary\" id=\"debug-edit-template-save\" style=\"padding:8px 16px; font-size:12px;\">\ud83d\udcbe \u4fdd\u5b58<\/button>\r\n                            <button class=\"btn btn-danger\" id=\"debug-edit-template-delete\" style=\"padding:8px 16px; font-size:12px;\">\ud83d\uddd1\ufe0f \u5220\u9664<\/button>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- \u65e5\u5fd7\u7a97\u53e3\uff08\u589e\u52a0\u9ad8\u5ea6\uff09 -->\r\n            <div class=\"modbus-section\" style=\"margin-top:10px; margin-bottom:10px;\">\r\n                <h3 style=\"margin-bottom:8px;\">\u65e5\u5fd7\u7a97\u53e3<\/h3>\r\n                <div style=\"background: #fff3cd; border: 1px solid #ffc107; padding: 8px; margin-bottom: 8px; border-radius: 4px; display: none; font-size:12px;\" id=\"debug-browser-errors\">\r\n                    <strong style=\"color: #856404;\">\u26a0\ufe0f \u6d4f\u89c8\u5668\u9519\u8bef\uff1a<\/strong>\r\n                    <div id=\"debug-browser-error-list\" style=\"color: #856404; font-size: 11px; margin-top: 5px;\"><\/div>\r\n                <\/div>\r\n                <div id=\"debug-log-window\" class=\"debug-log-window\" style=\"height: 600px;\">\r\n                    <div class=\"log-entry log-info\">\u7b49\u5f85\u8fde\u63a5...<\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- \u7b2c\u4e94\u884c\uff1a\u6570\u636e\u89e3\u6790 -->\r\n            <div class=\"modbus-section\">\r\n                <h3>Modbus\u6570\u636e\u89e3\u6790<\/h3>\r\n                <div class=\"form-group\">\r\n                    <div class=\"form-row\">\r\n                        <div class=\"form-col\">\r\n                            <label>\u6570\u636e\u6e90<\/label>\r\n                            <select class=\"form-control\" id=\"debug-data-source\">\r\n                                <option value=\"serial\" selected>\u4e32\u53e3\u6570\u636e<\/option>\r\n                                <option value=\"manual\">\u624b\u52a8\u8f93\u5165<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>\u6570\u636e\u683c\u5f0f<\/label>\r\n                            <select class=\"form-control\" id=\"debug-data-format\">\r\n                                <option value=\"binary\" selected>\u4e8c\u8fdb\u5236<\/option>\r\n                                <option value=\"hex\">\u5341\u516d\u8fdb\u5236<\/option>\r\n                            <\/select>\r\n                        <\/div>\r\n                        <div class=\"form-col\">\r\n                            <label>\u542f\u7528\u89e3\u6790<\/label>\r\n                            <div class=\"checkbox\" style=\"padding-top:8px;\">\r\n                                <label>\r\n                                    <input type=\"checkbox\" id=\"debug-enable-parse\" checked> \u542f\u7528\r\n                                <\/label>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <!-- \u89e3\u6790\u89c4\u5219\u8868\u683c -->\r\n                <h4 style=\"margin-top:15px;\">\u6dfb\u52a0\u89e3\u6790\u89c4\u5219<\/h4>\r\n                <div style=\"overflow-x:auto; margin-bottom:10px;\">\r\n                    <table class=\"table table-striped\" style=\"margin-bottom:10px; font-size:12px;\">\r\n                        <thead>\r\n                            <tr>\r\n                                <th style=\"width:120px;\">\u89c4\u5219\u540d\u79f0<\/th>\r\n                                <th style=\"width:100px;\">\u5bc4\u5b58\u5668\u53f7<\/th>\r\n                                <th style=\"width:100px;\">\u6570\u636e\u7c7b\u578b<\/th>\r\n                                <th style=\"width:80px;\">\u5b57\u8282\u5e8f<\/th>\r\n                                <th style=\"width:70px;\">\u7cfb\u6570<\/th>\r\n                                <th style=\"width:70px;\">\u5e38\u6570<\/th>\r\n                                <th style=\"width:80px;\">\u5c0f\u6570\u4f4d\u6570<\/th>\r\n                                <th style=\"width:70px;\">\u64cd\u4f5c<\/th>\r\n                            <\/tr>\r\n                        <\/thead>\r\n                        <tbody id=\"debug-rules-list\">\r\n                            <tr class=\"debug-rule-row\">\r\n                                <td><input type=\"text\" class=\"form-control input-sm\" placeholder=\"\u6e29\u5ea6\" value=\"\u6e29\u5ea6\"><\/td>\r\n                                <td>\r\n                                    <select class=\"form-control input-sm debug-register-select\">\r\n                                        <option value=\"0\">\u7b2c1\u4e2a<\/option>\r\n                                        <option value=\"1\">\u7b2c2\u4e2a<\/option>\r\n                                        <option value=\"2\">\u7b2c3\u4e2a<\/option>\r\n                                        <option value=\"3\">\u7b2c4\u4e2a<\/option>\r\n                                        <option value=\"4\">\u7b2c5\u4e2a<\/option>\r\n                                        <option value=\"5\">\u7b2c6\u4e2a<\/option>\r\n                                        <option value=\"6\">\u7b2c7\u4e2a<\/option>\r\n                                        <option value=\"7\">\u7b2c8\u4e2a<\/option>\r\n                                        <option value=\"8\">\u7b2c9\u4e2a<\/option>\r\n                                        <option value=\"9\">\u7b2c10\u4e2a<\/option>\r\n                                        <option value=\"10\">\u7b2c11\u4e2a<\/option>\r\n                                        <option value=\"11\">\u7b2c12\u4e2a<\/option>\r\n                                        <option value=\"12\">\u7b2c13\u4e2a<\/option>\r\n                                        <option value=\"13\">\u7b2c14\u4e2a<\/option>\r\n                                        <option value=\"14\">\u7b2c15\u4e2a<\/option>\r\n                                        <option value=\"15\">\u7b2c16\u4e2a<\/option>\r\n                                        <option value=\"16\">\u7b2c17\u4e2a<\/option>\r\n                                        <option value=\"17\">\u7b2c18\u4e2a<\/option>\r\n                                        <option value=\"18\">\u7b2c19\u4e2a<\/option>\r\n                                        <option value=\"19\">\u7b2c20\u4e2a<\/option>\r\n                                        <option value=\"20\">\u7b2c21\u4e2a<\/option>\r\n                                        <option value=\"21\">\u7b2c22\u4e2a<\/option>\r\n                                        <option value=\"22\">\u7b2c23\u4e2a<\/option>\r\n                                        <option value=\"23\">\u7b2c24\u4e2a<\/option>\r\n                                        <option value=\"24\">\u7b2c25\u4e2a<\/option>\r\n                                        <option value=\"25\">\u7b2c26\u4e2a<\/option>\r\n                                        <option value=\"26\">\u7b2c27\u4e2a<\/option>\r\n                                        <option value=\"27\">\u7b2c28\u4e2a<\/option>\r\n                                        <option value=\"28\">\u7b2c29\u4e2a<\/option>\r\n                                        <option value=\"29\">\u7b2c30\u4e2a<\/option>\r\n                                        <option value=\"30\">\u7b2c31\u4e2a<\/option>\r\n                                        <option value=\"31\">\u7b2c32\u4e2a<\/option>\r\n                                        <option value=\"32\">\u7b2c33\u4e2a<\/option>\r\n                                        <option value=\"33\">\u7b2c34\u4e2a<\/option>\r\n                                        <option value=\"34\">\u7b2c35\u4e2a<\/option>\r\n                                        <option value=\"35\">\u7b2c36\u4e2a<\/option>\r\n                                        <option value=\"36\">\u7b2c37\u4e2a<\/option>\r\n                                        <option value=\"37\">\u7b2c38\u4e2a<\/option>\r\n                                        <option value=\"38\">\u7b2c39\u4e2a<\/option>\r\n                                        <option value=\"39\">\u7b2c40\u4e2a<\/option>\r\n                                        <option value=\"40\">\u7b2c41\u4e2a<\/option>\r\n                                        <option value=\"41\">\u7b2c42\u4e2a<\/option>\r\n                                        <option value=\"42\">\u7b2c43\u4e2a<\/option>\r\n                                        <option value=\"43\">\u7b2c44\u4e2a<\/option>\r\n                                        <option value=\"44\">\u7b2c45\u4e2a<\/option>\r\n                                        <option value=\"45\">\u7b2c46\u4e2a<\/option>\r\n                                        <option value=\"46\">\u7b2c47\u4e2a<\/option>\r\n                                        <option value=\"47\">\u7b2c48\u4e2a<\/option>\r\n                                        <option value=\"48\">\u7b2c49\u4e2a<\/option>\r\n                                        <option value=\"49\">\u7b2c50\u4e2a<\/option>\r\n                                        <option value=\"50\">\u7b2c51\u4e2a<\/option>\r\n                                        <option value=\"51\">\u7b2c52\u4e2a<\/option>\r\n                                        <option value=\"52\">\u7b2c53\u4e2a<\/option>\r\n                                        <option value=\"53\">\u7b2c54\u4e2a<\/option>\r\n                                        <option value=\"54\">\u7b2c55\u4e2a<\/option>\r\n                                        <option value=\"55\">\u7b2c56\u4e2a<\/option>\r\n                                        <option value=\"56\">\u7b2c57\u4e2a<\/option>\r\n                                        <option value=\"57\">\u7b2c58\u4e2a<\/option>\r\n                                        <option value=\"58\">\u7b2c59\u4e2a<\/option>\r\n                                        <option value=\"59\">\u7b2c60\u4e2a<\/option>\r\n                                        <option value=\"60\">\u7b2c61\u4e2a<\/option>\r\n                                        <option value=\"61\">\u7b2c62\u4e2a<\/option>\r\n                                        <option value=\"62\">\u7b2c63\u4e2a<\/option>\r\n                                        <option value=\"63\">\u7b2c64\u4e2a<\/option>\r\n                                        <option value=\"64\">\u7b2c65\u4e2a<\/option>\r\n                                        <option value=\"65\">\u7b2c66\u4e2a<\/option>\r\n                                        <option value=\"66\">\u7b2c67\u4e2a<\/option>\r\n                                        <option value=\"67\">\u7b2c68\u4e2a<\/option>\r\n                                        <option value=\"68\">\u7b2c69\u4e2a<\/option>\r\n                                        <option value=\"69\">\u7b2c70\u4e2a<\/option>\r\n                                        <option value=\"70\">\u7b2c71\u4e2a<\/option>\r\n                                        <option value=\"71\">\u7b2c72\u4e2a<\/option>\r\n                                        <option value=\"72\">\u7b2c73\u4e2a<\/option>\r\n                                        <option value=\"73\">\u7b2c74\u4e2a<\/option>\r\n                                        <option value=\"74\">\u7b2c75\u4e2a<\/option>\r\n                                        <option value=\"75\">\u7b2c76\u4e2a<\/option>\r\n                                        <option value=\"76\">\u7b2c77\u4e2a<\/option>\r\n                                        <option value=\"77\">\u7b2c78\u4e2a<\/option>\r\n                                        <option value=\"78\">\u7b2c79\u4e2a<\/option>\r\n                                        <option value=\"79\">\u7b2c80\u4e2a<\/option>\r\n                                        <option value=\"80\">\u7b2c81\u4e2a<\/option>\r\n                                        <option value=\"81\">\u7b2c82\u4e2a<\/option>\r\n                                        <option value=\"82\">\u7b2c83\u4e2a<\/option>\r\n                                        <option value=\"83\">\u7b2c84\u4e2a<\/option>\r\n                                        <option value=\"84\">\u7b2c85\u4e2a<\/option>\r\n                                        <option value=\"85\">\u7b2c86\u4e2a<\/option>\r\n                                        <option value=\"86\">\u7b2c87\u4e2a<\/option>\r\n                                        <option value=\"87\">\u7b2c88\u4e2a<\/option>\r\n                                        <option value=\"88\">\u7b2c89\u4e2a<\/option>\r\n                                        <option value=\"89\">\u7b2c90\u4e2a<\/option>\r\n                                        <option value=\"90\">\u7b2c91\u4e2a<\/option>\r\n                                        <option value=\"91\">\u7b2c92\u4e2a<\/option>\r\n                                        <option value=\"92\">\u7b2c93\u4e2a<\/option>\r\n                                        <option value=\"93\">\u7b2c94\u4e2a<\/option>\r\n                                        <option value=\"94\">\u7b2c95\u4e2a<\/option>\r\n                                        <option value=\"95\">\u7b2c96\u4e2a<\/option>\r\n                                        <option value=\"96\">\u7b2c97\u4e2a<\/option>\r\n                                        <option value=\"97\">\u7b2c98\u4e2a<\/option>\r\n                                        <option value=\"98\">\u7b2c99\u4e2a<\/option>\r\n                                        <option value=\"99\">\u7b2c100\u4e2a<\/option>\r\n                                        <option value=\"100\">\u7b2c101\u4e2a<\/option>\r\n                                        <option value=\"101\">\u7b2c102\u4e2a<\/option>\r\n                                        <option value=\"102\">\u7b2c103\u4e2a<\/option>\r\n                                        <option value=\"103\">\u7b2c104\u4e2a<\/option>\r\n                                        <option value=\"104\">\u7b2c105\u4e2a<\/option>\r\n                                        <option value=\"105\">\u7b2c106\u4e2a<\/option>\r\n                                        <option value=\"106\">\u7b2c107\u4e2a<\/option>\r\n                                        <option value=\"107\">\u7b2c108\u4e2a<\/option>\r\n                                        <option value=\"108\">\u7b2c109\u4e2a<\/option>\r\n                                        <option value=\"109\">\u7b2c110\u4e2a<\/option>\r\n                                        <option value=\"110\">\u7b2c111\u4e2a<\/option>\r\n                                        <option value=\"111\">\u7b2c112\u4e2a<\/option>\r\n                                        <option value=\"112\">\u7b2c113\u4e2a<\/option>\r\n                                        <option value=\"113\">\u7b2c114\u4e2a<\/option>\r\n                                        <option value=\"114\">\u7b2c115\u4e2a<\/option>\r\n                                        <option value=\"115\">\u7b2c116\u4e2a<\/option>\r\n                                        <option value=\"116\">\u7b2c117\u4e2a<\/option>\r\n                                        <option value=\"117\">\u7b2c118\u4e2a<\/option>\r\n                                        <option value=\"118\">\u7b2c119\u4e2a<\/option>\r\n                                        <option value=\"119\">\u7b2c120\u4e2a<\/option>\r\n                                        <option value=\"120\">\u7b2c121\u4e2a<\/option>\r\n                                        <option value=\"121\">\u7b2c122\u4e2a<\/option>\r\n                                        <option value=\"122\">\u7b2c123\u4e2a<\/option>\r\n                                        <option value=\"123\">\u7b2c124\u4e2a<\/option>\r\n                                        <option value=\"124\">\u7b2c125\u4e2a<\/option>\r\n                                    <\/select>\r\n                                <\/td>\r\n                                <td>\r\n                                    <select class=\"form-control input-sm\">\r\n                                        <option value=\"UINT16\" selected title=\"\u8303\u56f4\uff1a0\uff5e65535 | \u9002\u7528\uff1a\u6e7f\u5ea6\u3001\u98ce\u901f\u7b49\">UINT16 - 16\u4f4d\u65e0\u7b26\u53f7<\/option>\r\n                                        <option value=\"INT16\" title=\"\u8303\u56f4\uff1a-32768\uff5e32767 | \u9002\u7528\uff1a\u6e29\u5ea6\uff08\u53ef\u8d1f\u6570\uff09\u7b49\">INT16 - 16\u4f4d\u6709\u7b26\u53f7<\/option>\r\n                                        <option value=\"UINT32\" title=\"\u8303\u56f4\uff1a0\uff5e4,294,967,295 | \u9002\u7528\uff1a\u7d2f\u8ba1\u503c\u3001\u6d41\u91cf\u8ba1\u7b49\">UINT32 - 32\u4f4d\u65e0\u7b26\u53f7<\/option>\r\n                                        <option value=\"INT32\" title=\"\u8303\u56f4\uff1a-2,147,483,648\uff5e2,147,483,647 | \u9002\u7528\uff1a\u5927\u8303\u56f4\u53ef\u8d1f\u6570\">INT32 - 32\u4f4d\u6709\u7b26\u53f7<\/option>\r\n                                        <option value=\"FLOAT32\" title=\"\u8303\u56f4\uff1a\u00b13.4\u00d710\u00b3\u2078 | \u7cbe\u5ea6\uff1a6-7\u4f4d | \u9002\u7528\uff1a\u6e29\u5ea6\u3001\u7535\u538b\uff08\u5c0f\u6570\uff09\u7b49\">FLOAT32 - 32\u4f4d\u6d6e\u70b9<\/option>\r\n                                    <\/select>\r\n                                <\/td>\r\n                                <td>\r\n                                    <select class=\"form-control input-sm\">\r\n                                        <option value=\"ABCD\" selected>ABCD<\/option>\r\n                                        <option value=\"DCBA\">DCBA<\/option>\r\n                                        <option value=\"BADC\">BADC<\/option>\r\n                                    <\/select>\r\n                                <\/td>\r\n                                <td><input type=\"number\" class=\"form-control input-sm\" value=\"1\" step=\"0.01\" title=\"\u7cfb\u6570\uff1a\u7528\u4e8e\u4e58\u6cd5\u8fd0\u7b97 | \u516c\u5f0f\uff1a\u6700\u7ec8\u503c = \u539f\u59cb\u503c \u00d7 \u7cfb\u6570 + \u5e38\u6570 | \u4f8b\u5982\uff1a\u6e29\u5ea6\u4f20\u611f\u5668\u8f93\u51fa\u4e3a 100\uff0c\u7cfb\u6570 0.1 = \u5b9e\u9645\u6e29\u5ea6 10\u00b0C\"><\/td>\r\n                                <td><input type=\"number\" class=\"form-control input-sm\" value=\"0\" step=\"0.01\" title=\"\u5e38\u6570\uff1a\u7528\u4e8e\u52a0\u6cd5\u8fd0\u7b97 | \u516c\u5f0f\uff1a\u6700\u7ec8\u503c = \u539f\u59cb\u503c \u00d7 \u7cfb\u6570 + \u5e38\u6570 | \u4f8b\u5982\uff1a\u6e29\u5ea6\u4f20\u611f\u5668\u8f93\u51fa\u4e3a 100\uff0c\u5e38\u6570 -40 = \u5b9e\u9645\u6e29\u5ea6 -30\u00b0C\"><\/td>\r\n                                <td><input type=\"number\" class=\"form-control input-sm\" value=\"2\" min=\"0\" max=\"10\"><\/td>\r\n                                <td>\r\n                                    <button class=\"btn btn-danger btn-xs debug-remove-rule\">\u5220\u9664<\/button>\r\n                                <\/td>\r\n                            <\/tr>\r\n                        <\/tbody>\r\n                    <\/table>\r\n                <\/div>\r\n                <button class=\"btn btn-secondary\" id=\"debug-add-rule\">\u6dfb\u52a0\u89c4\u5219<\/button>\r\n            <\/div>\r\n\r\n            <!-- \u7b2c\u516d\u884c\uff1a\u5386\u53f2\u8bb0\u5f55 -->\r\n            <div class=\"modbus-section\">\r\n                <h3>\u539f\u59cb\u62a5\u6587<\/h3>\r\n                <div class=\"form-group\">\r\n                    <div class=\"form-row\" style=\"display: flex; gap: 10px; align-items: flex-end;\">\r\n                        <div class=\"form-col\" style=\"flex: 0 0 auto;\">\r\n                            <label>\u81ea\u52a8\u6e05\u7406<\/label>\r\n                            <div class=\"checkbox\">\r\n                                <label>\r\n                                    <input type=\"checkbox\" id=\"debug-auto-clear-history\"> \u542f\u7528\r\n                                <\/label>\r\n                            <\/div>\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 150px;\">\r\n                            <label>\u6700\u5927\u6570\u91cf<\/label>\r\n                            <input type=\"number\" class=\"form-control\" id=\"debug-max-history\" value=\"1000\" min=\"100\" style=\"width:100%;\">\r\n                        <\/div>\r\n                        <div class=\"form-col\" style=\"flex: 0 0 auto; display: flex; gap: 5px;\">\r\n                            <button class=\"btn btn-secondary btn-sm\" id=\"debug-export-history\" style=\"margin:0; padding:8px 14px;\">\u5bfc\u51fa<\/button>\r\n                            <button class=\"btn btn-danger btn-sm\" id=\"debug-clear-history\" style=\"margin:0; padding:8px 14px;\">\u6e05\u7a7a<\/button>\r\n                        <\/div>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <!-- \u5386\u53f2\u8bb0\u5f55\u8868\u683c -->\r\n                <div style=\"overflow-x:auto; margin-bottom:10px;\">\r\n                    <table class=\"table table-striped\" style=\"font-size:12px;\">\r\n                        <thead>\r\n                            <tr>\r\n                                <th style=\"width:50px;\">\u5e8f\u53f7<\/th>\r\n                                <th style=\"width:200px;\">\u65f6\u95f4<\/th>\r\n                                <th>\u62a5\u6587<\/th>\r\n                            <\/tr>\r\n                        <\/thead>\r\n                        <tbody id=\"debug-history-list\">\r\n                            <tr>\r\n                                <td colspan=\"3\" style=\"text-align:center;color:#999;\">\u6682\u65e0\u6570\u636e<\/td>\r\n                            <\/tr>\r\n                        <\/tbody>\r\n                    <\/table>\r\n                <\/div>\r\n\r\n                <!-- \u5206\u9875\u63a7\u5236 -->\r\n                <div style=\"text-align:center; margin-top:10px;\">\r\n                    <nav>\r\n                        <ul class=\"pagination pagination-sm\">\r\n                            <li><a href=\"#\" id=\"debug-page-first\">\u9996\u9875<\/a><\/li>\r\n                            <li><a href=\"#\" id=\"debug-page-prev\">\u4e0a\u4e00\u9875<\/a><\/li>\r\n                            <li><span id=\"debug-page-info\">1 \/ 1<\/span><\/li>\r\n                            <li><a href=\"#\" id=\"debug-page-next\">\u4e0b\u4e00\u9875<\/a><\/li>\r\n                            <li><a href=\"#\" id=\"debug-page-last\">\u672b\u9875<\/a><\/li>\r\n                            <li style=\"margin-left:20px;\">\r\n                                <select id=\"debug-page-size\" class=\"form-control\" style=\"width:70px; display:inline-block;\">\r\n                                    <option value=\"10\" selected>10<\/option>\r\n                                    <option value=\"20\">20<\/option>\r\n                                    <option value=\"50\">50<\/option>\r\n                                <\/select>\r\n                                \/ Page\r\n                            <\/li>\r\n                        <\/ul>\r\n                    <\/nav>\r\n                    <p id=\"debug-total-count\">Total : 0<\/p>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <style>\r\n            .modbus-debugger-container {\r\n                margin-top: 20px;\r\n                width: 100%;\r\n            }\r\n\r\n            .debug-log-window {\r\n                background: #1e1e1e;\r\n                color: #00ff00;\r\n                font-family: 'Courier New', monospace;\r\n                padding: 5px 5px 5px 5px;\r\n                border-radius: 4px;\r\n                height: 300px;\r\n                overflow-y: auto;\r\n                border: 1px solid #ddd;\r\n                margin-bottom: 15px;\r\n                line-height: 1.4;\r\n            }\r\n\r\n            .log-entry {\r\n                padding: 1px 0px;\r\n                border-bottom: none;\r\n                font-size: 12px;\r\n                white-space: pre-wrap;\r\n                word-wrap: break-word;\r\n                margin: 0px 0px;\r\n            }\r\n\r\n            .log-send {\r\n                color: #00ff00;\r\n            }\r\n\r\n            .log-recv {\r\n                color: #00ccff;\r\n            }\r\n\r\n            .log-error {\r\n                color: #ff0000;\r\n            }\r\n\r\n            .log-info {\r\n                color: #ffff00;\r\n            }\r\n\r\n            .debug-data-view {\r\n                display: none;\r\n            }\r\n\r\n            .debug-data-view.active {\r\n                display: block;\r\n            }\r\n\r\n            .input-sm {\r\n                font-size: 12px;\r\n                padding: 3px 6px;\r\n                height: 30px;\r\n            }\r\n\r\n            .btn-xs {\r\n                padding: 3px 6px;\r\n                font-size: 11px;\r\n            }\r\n\r\n            \/* \u8c03\u8bd5\u9875\u9762\u529f\u80fd\u7801\u5b57\u6bb5\u663e\u793a\/\u9690\u85cf *\/\r\n\r\n            #debug-coil-status-col {\r\n                display: none !important;\r\n            }\r\n\r\n            #debug-register-value-col {\r\n                display: none !important;\r\n            }\r\n\r\n            @media (max-width: 1200px) {\r\n                .debug-log-window {\r\n                    height: 250px;\r\n                }\r\n\r\n                [style*=\"display: flex\"] {\r\n                    flex-direction: column;\r\n                }\r\n            }\r\n\r\n            @media (max-width: 768px) {\r\n                .debug-log-window {\r\n                    height: 200px;\r\n                }\r\n\r\n                [style*=\"display: flex\"] {\r\n                    flex-direction: column;\r\n                }\r\n            }\r\n        <\/style>\r\n                            <\/div>\r\n                \r\n                <!-- Modbus \u4ece\u7ad9\u6a21\u62df \u9009\u9879\u5361 -->\r\n                \r\n                <!-- \u4e32\u53e3\u8c03\u8bd5 \u9009\u9879\u5361 -->\r\n                                    <div id=\"serial-debug-tab\" class=\"modbus-tab-content \">\r\n                                <div class=\"serial-debug-container\">\n            <div class=\"serial-debug-layout\">\n                <!-- \u5de6\u4fa7\u63a7\u5236\u9762\u677f -->\n                <div class=\"serial-debug-left-panel\">\n                    <!-- \u4e32\u53e3\u53c2\u6570\u914d\u7f6e -->\n                    <div class=\"serial-section serial-port-config\">\n                        <h3>\u4e32\u53e3\u53c2\u6570 <span class=\"mini-program-badge\" style=\"position:relative;display:inline-block;font-size:16px;color:#e53935;font-weight:bold;cursor:pointer;margin-left:10px;\" onmouseover=\"this.querySelector('img').style.display='block'\" onmouseout=\"this.querySelector('img').style.display='none'\">\u5c0f\u7a0b\u5e8f\u7248<img decoding=\"async\" src=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" style=\"display:none;position:absolute;left:0;top:25px;z-index:9999;max-width:300px;border:1px solid #ccc;box-shadow:0 2px 10px rgba(0,0,0,0.2);border-radius:4px;\"\/ loading=\"lazy\" title=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" alt=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" \/><\/span><\/h3>\n                        <div class=\"serial-form-group\">\n                            <label>COM\u7aef\u53e3<\/label>\n                            <select class=\"serial-control\" id=\"serial-port-select\">\n                                <option value=\"\">-- \u672a\u68c0\u6d4b\u5230\u4e32\u53e3 --<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"serial-form-group\">\n                            <label>\u6ce2\u7279\u7387<\/label>\n                            <select class=\"serial-control\" id=\"serial-baudrate\">\n                                <option value=\"300\">300<\/option>\n                                <option value=\"600\">600<\/option>\n                                <option value=\"1200\">1200<\/option>\n                                <option value=\"2400\">2400<\/option>\n                                <option value=\"4800\">4800<\/option>\n                                <option value=\"9600\">9600<\/option>\n                                <option value=\"14400\">14400<\/option>\n                                <option value=\"19200\">19200<\/option>\n                                <option value=\"38400\">38400<\/option>\n                                <option value=\"57600\">57600<\/option>\n                                <option value=\"115200\" selected>115200<\/option>\n                                <option value=\"230400\">230400<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"serial-form-group\">\n                            <label>\u6570\u636e\u4f4d<\/label>\n                            <select class=\"serial-control\" id=\"serial-databits\">\n                                <option value=\"5\">5<\/option>\n                                <option value=\"6\">6<\/option>\n                                <option value=\"7\">7<\/option>\n                                <option value=\"8\" selected>8<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"serial-form-group\">\n                            <label>\u6821\u9a8c\u4f4d<\/label>\n                            <select class=\"serial-control\" id=\"serial-parity\">\n                                <option value=\"none\" selected>\u65e0<\/option>\n                                <option value=\"odd\">\u5947\u6821\u9a8c<\/option>\n                                <option value=\"even\">\u5076\u6821\u9a8c<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"serial-form-group\">\n                            <label>\u505c\u6b62\u4f4d<\/label>\n                            <select class=\"serial-control\" id=\"serial-stopbits\">\n                                <option value=\"1\" selected>1<\/option>\n                                <option value=\"1.5\">1.5<\/option>\n                                <option value=\"2\">2<\/option>\n                            <\/select>\n                        <\/div>\n                        <button class=\"serial-btn serial-btn-danger\" id=\"serial-toggle-btn\">\u6253\u5f00\u4e32\u53e3<\/button>\n                    <\/div>\n\n                    <!-- \u8ba1\u6570\u533a -->\n                    <div class=\"serial-section serial-counter\">\n                        <h3>\u8ba1\u6570\u533a<\/h3>\n                        <div class=\"serial-counter-item\">\n                            <span>\u53d1\u9001\u5e27\u6570\uff1a<\/span>\n                            <span id=\"serial-send-frames\">0<\/span>\n                        <\/div>\n                        <div class=\"serial-counter-item\">\n                            <span>\u53d1\u9001\u5b57\u8282\u6570\uff1a<\/span>\n                            <span id=\"serial-send-bytes\">0<\/span>\n                        <\/div>\n                        <div class=\"serial-counter-item\">\n                            <span>\u63a5\u6536\u5e27\u6570\uff1a<\/span>\n                            <span id=\"serial-receive-frames\">0<\/span>\n                        <\/div>\n                        <div class=\"serial-counter-item\">\n                            <span>\u63a5\u6536\u5b57\u8282\u6570\uff1a<\/span>\n                            <span id=\"serial-receive-bytes\">0<\/span>\n                        <\/div>\n                        <button class=\"serial-btn serial-btn-secondary\" id=\"serial-reset-counter\">\u91cd\u7f6e\u8ba1\u6570<\/button>\n                    <\/div>\n\n                    <!-- \u64cd\u63a7\u533a -->\n                    <div class=\"serial-section serial-control-area\">\n                        <h3>\u64cd\u63a7\u533a<\/h3>\n                        <div class=\"serial-form-group\">\n                            <label>\u6570\u636e\u4fdd\u5b58\u8def\u5f84<\/label>\n                            <input type=\"text\" class=\"serial-control\" id=\"serial-save-path\" value=\"\" readonly>\n                            <button class=\"serial-btn serial-btn-secondary\" id=\"serial-choose-path\">\u9009\u62e9\u8def\u5f84<\/button>\n                        <\/div>\n                        <div class=\"serial-form-group\">\n                            <label>\u5faa\u73af\u6b21\u6570<\/label>\n                            <div class=\"serial-cycle-row\">\n                                <input type=\"number\" class=\"serial-control serial-cycle-input\" id=\"serial-cycle-count\" value=\"10\" min=\"1\">\n                                <label class=\"serial-checkbox-label\">\n                                    <input type=\"checkbox\" id=\"serial-infinite-cycle\"> \u65e0\u9650\u5faa\u73af\n                                <\/label>\n                            <\/div>\n                        <\/div>\n                        <div class=\"serial-control-buttons\">\n                            <button class=\"serial-btn serial-btn-warning\" id=\"serial-stop-cycle\">\u505c\u6b62\u5faa\u73af<\/button>\n                            <button class=\"serial-btn serial-btn-primary\" id=\"serial-save-data\">\u4fdd\u5b58\u6570\u636e<\/button>\n                        <\/div>\n                    <\/div>\n                <\/div>\n\n                <!-- \u53f3\u4fa7\u4e3b\u5de5\u4f5c\u533a -->\n                <div class=\"serial-debug-right-panel\">\n                    <!-- \u6536\u53d1\u62a5\u6587\u663e\u793a\u533a -->\n                    <div class=\"serial-section serial-message-display\">\n                        <h3>\u6536\u53d1\u62a5\u6587<\/h3>\n                        <div class=\"serial-message-output\" id=\"serial-message-output\"><\/div>\n                        <div class=\"serial-message-controls\">\n                            <button class=\"serial-btn serial-btn-secondary\" id=\"serial-clear-messages\">\u6e05\u7a7a<\/button>\n                            <label class=\"serial-checkbox-label\">\n                                <input type=\"checkbox\" id=\"serial-auto-scroll\" checked> \u81ea\u52a8\u6eda\u52a8\n                            <\/label>\n                            <label class=\"serial-checkbox-label\">\n                                <input type=\"checkbox\" id=\"serial-show-timestamp\" checked> \u663e\u793a\u65f6\u95f4\u6233\n                            <\/label>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u53d1\u9001\u533a\u914d\u7f6e -->\n                    <div class=\"serial-section serial-send-area\">\n                        <h3>\u53d1\u9001\u533a\u914d\u7f6e<\/h3>\n\n                        <div class=\"serial-send-zones\">\n                            <!-- \u53d1\u9001\u533a1-6 -->\n                                                        <div class=\"serial-send-zone\">\n                                <div class=\"serial-zone-header\">\n                                    <span class=\"serial-zone-label\">\u53d1\u90011\u533a<\/span>\n                                    <div class=\"serial-zone-actions\">\n                                        <button class=\"serial-btn-small serial-btn-secondary\" data-zone=\"1\" data-action=\"clear\">\u6e05\u7a7a<\/button>\n                                        <button class=\"serial-btn-small serial-btn-primary\" data-zone=\"1\" data-action=\"send\">\u53d1\u9001<\/button>\n                                    <\/div>\n                                <\/div>\n\n                                <!-- \u6bcf\u4e2a\u53d1\u9001\u533a\u7684\u6821\u9a8c\u914d\u7f6e -->\n                                <div class=\"serial-zone-checksum\">\n                                    <div class=\"serial-form-group\">\n                                        <label>\u6821\u9a8c\uff1a<\/label>\n                                        <select class=\"serial-control serial-checksum-mode\" data-zone=\"1\">\n                                            <option value=\"none\" selected>\u65e0<\/option>\n                                            <option value=\"crc16-lsb\">CRC16\u4f4e\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"crc16-msb\">CRC16\u9ad8\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"checksum\">\u6821\u9a8c\u548c<\/option>\n                                            <option value=\"xor\">\u5f02\u6216\u6821\u9a8c<\/option>\n                                        <\/select>\n                                    <\/div>\n\n                                    <!-- \u8303\u56f4\u9009\u62e9\uff08\u6761\u4ef6\u663e\u793a\uff09 -->\n                                    <div class=\"serial-checksum-range\" data-zone=\"1\" style=\"display: none;\">\n                                        <div class=\"serial-form-group-inline\">\n                                            <label>\u4ece:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-start\" data-zone=\"1\" value=\"1\" min=\"1\">\n                                            <label>\u5230:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-end\" data-zone=\"1\" value=\"0\" min=\"0\" placeholder=\"0=\u672b\">\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n\n                                <textarea class=\"serial-send-input\" id=\"serial-send-zone-1\" rows=\"2\"><\/textarea>\n                            <\/div>\n                                                        <div class=\"serial-send-zone\">\n                                <div class=\"serial-zone-header\">\n                                    <span class=\"serial-zone-label\">\u53d1\u90012\u533a<\/span>\n                                    <div class=\"serial-zone-actions\">\n                                        <button class=\"serial-btn-small serial-btn-secondary\" data-zone=\"2\" data-action=\"clear\">\u6e05\u7a7a<\/button>\n                                        <button class=\"serial-btn-small serial-btn-primary\" data-zone=\"2\" data-action=\"send\">\u53d1\u9001<\/button>\n                                    <\/div>\n                                <\/div>\n\n                                <!-- \u6bcf\u4e2a\u53d1\u9001\u533a\u7684\u6821\u9a8c\u914d\u7f6e -->\n                                <div class=\"serial-zone-checksum\">\n                                    <div class=\"serial-form-group\">\n                                        <label>\u6821\u9a8c\uff1a<\/label>\n                                        <select class=\"serial-control serial-checksum-mode\" data-zone=\"2\">\n                                            <option value=\"none\" selected>\u65e0<\/option>\n                                            <option value=\"crc16-lsb\">CRC16\u4f4e\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"crc16-msb\">CRC16\u9ad8\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"checksum\">\u6821\u9a8c\u548c<\/option>\n                                            <option value=\"xor\">\u5f02\u6216\u6821\u9a8c<\/option>\n                                        <\/select>\n                                    <\/div>\n\n                                    <!-- \u8303\u56f4\u9009\u62e9\uff08\u6761\u4ef6\u663e\u793a\uff09 -->\n                                    <div class=\"serial-checksum-range\" data-zone=\"2\" style=\"display: none;\">\n                                        <div class=\"serial-form-group-inline\">\n                                            <label>\u4ece:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-start\" data-zone=\"2\" value=\"1\" min=\"1\">\n                                            <label>\u5230:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-end\" data-zone=\"2\" value=\"0\" min=\"0\" placeholder=\"0=\u672b\">\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n\n                                <textarea class=\"serial-send-input\" id=\"serial-send-zone-2\" rows=\"2\"><\/textarea>\n                            <\/div>\n                                                        <div class=\"serial-send-zone\">\n                                <div class=\"serial-zone-header\">\n                                    <span class=\"serial-zone-label\">\u53d1\u90013\u533a<\/span>\n                                    <div class=\"serial-zone-actions\">\n                                        <button class=\"serial-btn-small serial-btn-secondary\" data-zone=\"3\" data-action=\"clear\">\u6e05\u7a7a<\/button>\n                                        <button class=\"serial-btn-small serial-btn-primary\" data-zone=\"3\" data-action=\"send\">\u53d1\u9001<\/button>\n                                    <\/div>\n                                <\/div>\n\n                                <!-- \u6bcf\u4e2a\u53d1\u9001\u533a\u7684\u6821\u9a8c\u914d\u7f6e -->\n                                <div class=\"serial-zone-checksum\">\n                                    <div class=\"serial-form-group\">\n                                        <label>\u6821\u9a8c\uff1a<\/label>\n                                        <select class=\"serial-control serial-checksum-mode\" data-zone=\"3\">\n                                            <option value=\"none\" selected>\u65e0<\/option>\n                                            <option value=\"crc16-lsb\">CRC16\u4f4e\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"crc16-msb\">CRC16\u9ad8\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"checksum\">\u6821\u9a8c\u548c<\/option>\n                                            <option value=\"xor\">\u5f02\u6216\u6821\u9a8c<\/option>\n                                        <\/select>\n                                    <\/div>\n\n                                    <!-- \u8303\u56f4\u9009\u62e9\uff08\u6761\u4ef6\u663e\u793a\uff09 -->\n                                    <div class=\"serial-checksum-range\" data-zone=\"3\" style=\"display: none;\">\n                                        <div class=\"serial-form-group-inline\">\n                                            <label>\u4ece:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-start\" data-zone=\"3\" value=\"1\" min=\"1\">\n                                            <label>\u5230:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-end\" data-zone=\"3\" value=\"0\" min=\"0\" placeholder=\"0=\u672b\">\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n\n                                <textarea class=\"serial-send-input\" id=\"serial-send-zone-3\" rows=\"2\"><\/textarea>\n                            <\/div>\n                                                        <div class=\"serial-send-zone\">\n                                <div class=\"serial-zone-header\">\n                                    <span class=\"serial-zone-label\">\u53d1\u90014\u533a<\/span>\n                                    <div class=\"serial-zone-actions\">\n                                        <button class=\"serial-btn-small serial-btn-secondary\" data-zone=\"4\" data-action=\"clear\">\u6e05\u7a7a<\/button>\n                                        <button class=\"serial-btn-small serial-btn-primary\" data-zone=\"4\" data-action=\"send\">\u53d1\u9001<\/button>\n                                    <\/div>\n                                <\/div>\n\n                                <!-- \u6bcf\u4e2a\u53d1\u9001\u533a\u7684\u6821\u9a8c\u914d\u7f6e -->\n                                <div class=\"serial-zone-checksum\">\n                                    <div class=\"serial-form-group\">\n                                        <label>\u6821\u9a8c\uff1a<\/label>\n                                        <select class=\"serial-control serial-checksum-mode\" data-zone=\"4\">\n                                            <option value=\"none\" selected>\u65e0<\/option>\n                                            <option value=\"crc16-lsb\">CRC16\u4f4e\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"crc16-msb\">CRC16\u9ad8\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"checksum\">\u6821\u9a8c\u548c<\/option>\n                                            <option value=\"xor\">\u5f02\u6216\u6821\u9a8c<\/option>\n                                        <\/select>\n                                    <\/div>\n\n                                    <!-- \u8303\u56f4\u9009\u62e9\uff08\u6761\u4ef6\u663e\u793a\uff09 -->\n                                    <div class=\"serial-checksum-range\" data-zone=\"4\" style=\"display: none;\">\n                                        <div class=\"serial-form-group-inline\">\n                                            <label>\u4ece:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-start\" data-zone=\"4\" value=\"1\" min=\"1\">\n                                            <label>\u5230:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-end\" data-zone=\"4\" value=\"0\" min=\"0\" placeholder=\"0=\u672b\">\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n\n                                <textarea class=\"serial-send-input\" id=\"serial-send-zone-4\" rows=\"2\"><\/textarea>\n                            <\/div>\n                                                        <div class=\"serial-send-zone\">\n                                <div class=\"serial-zone-header\">\n                                    <span class=\"serial-zone-label\">\u53d1\u90015\u533a<\/span>\n                                    <div class=\"serial-zone-actions\">\n                                        <button class=\"serial-btn-small serial-btn-secondary\" data-zone=\"5\" data-action=\"clear\">\u6e05\u7a7a<\/button>\n                                        <button class=\"serial-btn-small serial-btn-primary\" data-zone=\"5\" data-action=\"send\">\u53d1\u9001<\/button>\n                                    <\/div>\n                                <\/div>\n\n                                <!-- \u6bcf\u4e2a\u53d1\u9001\u533a\u7684\u6821\u9a8c\u914d\u7f6e -->\n                                <div class=\"serial-zone-checksum\">\n                                    <div class=\"serial-form-group\">\n                                        <label>\u6821\u9a8c\uff1a<\/label>\n                                        <select class=\"serial-control serial-checksum-mode\" data-zone=\"5\">\n                                            <option value=\"none\" selected>\u65e0<\/option>\n                                            <option value=\"crc16-lsb\">CRC16\u4f4e\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"crc16-msb\">CRC16\u9ad8\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"checksum\">\u6821\u9a8c\u548c<\/option>\n                                            <option value=\"xor\">\u5f02\u6216\u6821\u9a8c<\/option>\n                                        <\/select>\n                                    <\/div>\n\n                                    <!-- \u8303\u56f4\u9009\u62e9\uff08\u6761\u4ef6\u663e\u793a\uff09 -->\n                                    <div class=\"serial-checksum-range\" data-zone=\"5\" style=\"display: none;\">\n                                        <div class=\"serial-form-group-inline\">\n                                            <label>\u4ece:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-start\" data-zone=\"5\" value=\"1\" min=\"1\">\n                                            <label>\u5230:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-end\" data-zone=\"5\" value=\"0\" min=\"0\" placeholder=\"0=\u672b\">\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n\n                                <textarea class=\"serial-send-input\" id=\"serial-send-zone-5\" rows=\"2\"><\/textarea>\n                            <\/div>\n                                                        <div class=\"serial-send-zone\">\n                                <div class=\"serial-zone-header\">\n                                    <span class=\"serial-zone-label\">\u53d1\u90016\u533a<\/span>\n                                    <div class=\"serial-zone-actions\">\n                                        <button class=\"serial-btn-small serial-btn-secondary\" data-zone=\"6\" data-action=\"clear\">\u6e05\u7a7a<\/button>\n                                        <button class=\"serial-btn-small serial-btn-primary\" data-zone=\"6\" data-action=\"send\">\u53d1\u9001<\/button>\n                                    <\/div>\n                                <\/div>\n\n                                <!-- \u6bcf\u4e2a\u53d1\u9001\u533a\u7684\u6821\u9a8c\u914d\u7f6e -->\n                                <div class=\"serial-zone-checksum\">\n                                    <div class=\"serial-form-group\">\n                                        <label>\u6821\u9a8c\uff1a<\/label>\n                                        <select class=\"serial-control serial-checksum-mode\" data-zone=\"6\">\n                                            <option value=\"none\" selected>\u65e0<\/option>\n                                            <option value=\"crc16-lsb\">CRC16\u4f4e\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"crc16-msb\">CRC16\u9ad8\u5b57\u8282\u5728\u524d<\/option>\n                                            <option value=\"checksum\">\u6821\u9a8c\u548c<\/option>\n                                            <option value=\"xor\">\u5f02\u6216\u6821\u9a8c<\/option>\n                                        <\/select>\n                                    <\/div>\n\n                                    <!-- \u8303\u56f4\u9009\u62e9\uff08\u6761\u4ef6\u663e\u793a\uff09 -->\n                                    <div class=\"serial-checksum-range\" data-zone=\"6\" style=\"display: none;\">\n                                        <div class=\"serial-form-group-inline\">\n                                            <label>\u4ece:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-start\" data-zone=\"6\" value=\"1\" min=\"1\">\n                                            <label>\u5230:<\/label>\n                                            <input type=\"number\" class=\"serial-control-small serial-checksum-end\" data-zone=\"6\" value=\"0\" min=\"0\" placeholder=\"0=\u672b\">\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n\n                                <textarea class=\"serial-send-input\" id=\"serial-send-zone-6\" rows=\"2\"><\/textarea>\n                            <\/div>\n                                                    <\/div>\n\n                        <!-- \u53d1\u9001\u9009\u9879 -->\n                        <div class=\"serial-send-options\">\n                            <div class=\"serial-options-row\">\n                                <label class=\"serial-checkbox-label\">\n                                    <input type=\"checkbox\" id=\"serial-hex-mode\" checked> 16\u8fdb\u5236\n                                <\/label>\n                                <div class=\"serial-delay-config\">\n                                    <label>\u5ef6\u8fdf\uff1a<\/label>\n                                    <input type=\"number\" class=\"serial-control serial-delay-input\" id=\"serial-send-delay\" value=\"1000\" min=\"0\">\n                                    <span>ms<\/span>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <script>\n        jQuery(document).ready(function($) {\n            \/\/ \u4e32\u53e3\u8c03\u8bd5\u72b6\u6001\n            const serialDebugState = {\n                port: null,\n                isOpen: false,\n                sendFrames: 0,\n                sendBytes: 0,\n                receiveFrames: 0,\n                receiveBytes: 0,\n                cycleInterval: null,\n                autoScroll: true,\n                showTimestamp: true,\n                receiveBuffer: [],          \/\/ \u63a5\u6536\u6570\u636e\u7f13\u51b2\u533a\n                receiveTimeout: null        \/\/ \u63a5\u6536\u8d85\u65f6\u5b9a\u65f6\u5668\n            };\n\n            \/\/ \u521d\u59cb\u5316\u9ed8\u8ba4\u6570\u636e\n            const defaultSendData = [\n                'FF 55 02 02 00 58',\n                'FF 55 82 01 00 3',\n                '3C 3A 1 1 1 1 01 00 3E 80 FF 00 0E 02 FF FF FF FF 00 00 80 50 10 00 00 00 01 3A 2',\n                '3C 3A 06 FD 3A 3E',\n                '3C 3B 06 FD 3A 3E',\n                '3C 3D 21 FA 01 23 3E 40 0F 03 0E 02 FF FF FF 00 02 08 01 3A 3E'\n            ];\n\n            \/\/ \u586b\u5145\u9ed8\u8ba4\u6570\u636e\n            defaultSendData.forEach((data, index) => {\n                $(`#serial-send-zone-${index + 1}`).val(data);\n            });\n\n            \/\/ \u8bf7\u6c42\u4e32\u53e3\u6743\u9650\n            async function requestSerialPort() {\n                if (!('serial' in navigator)) {\n                    alert('\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301Web Serial API\u3002\u8bf7\u4f7f\u7528Chrome\u3001Edge\u7b49\u652f\u6301\u8be5API\u7684\u6d4f\u89c8\u5668\u3002');\n                    return;\n                }\n\n                try {\n                    const port = await navigator.serial.requestPort();\n                    serialDebugState.port = port;\n                    updatePortList();\n                    addMessage('\u7cfb\u7edf', '\u4e32\u53e3\u8bbe\u5907\u5df2\u83b7\u53d6\u6388\u6743');\n                } catch (error) {\n                    addMessage('\u9519\u8bef', '\u672a\u9009\u62e9\u4e32\u53e3\u8bbe\u5907');\n                }\n            }\n\n            \/\/ \u66f4\u65b0\u4e32\u53e3\u5217\u8868\n            async function updatePortList() {\n                if (!('serial' in navigator)) return;\n\n                const ports = await navigator.serial.getPorts();\n                const $select = $('#serial-port-select');\n                $select.empty();\n\n                if (ports.length === 0) {\n                    $select.append('<option value=\"\">-- \u672a\u68c0\u6d4b\u5230\u4e32\u53e3\uff0c\u8bf7\u70b9\u51fb\"\u6253\u5f00\u4e32\u53e3\"\u6309\u94ae\u6388\u6743 --<\/option>');\n                } else {\n                    ports.forEach((port, index) => {\n                        const info = port.getInfo();\n                        const label = `COM${index + 1} (VID: ${info.usbVendorId || 'N\/A'}, PID: ${info.usbProductId || 'N\/A'})`;\n                        $select.append(`<option value=\"${index}\">${label}<\/option>`);\n                    });\n                    if (ports.length > 0) {\n                        serialDebugState.port = ports[0];\n                    }\n                }\n            }\n\n            \/\/ \u6253\u5f00\/\u5173\u95ed\u4e32\u53e3\n            $('#serial-toggle-btn').on('click', async function() {\n                if (serialDebugState.isOpen) {\n                    await closeSerialPort();\n                } else {\n                    await openSerialPort();\n                }\n            });\n\n            \/\/ \u6253\u5f00\u4e32\u53e3\n            async function openSerialPort() {\n                if (!serialDebugState.port) {\n                    await requestSerialPort();\n                    if (!serialDebugState.port) return;\n                }\n\n                const baudRate = parseInt($('#serial-baudrate').val());\n                const dataBits = parseInt($('#serial-databits').val());\n                const stopBits = parseFloat($('#serial-stopbits').val());\n                const parity = $('#serial-parity').val();\n\n                try {\n                    await serialDebugState.port.open({\n                        baudRate: baudRate,\n                        dataBits: dataBits,\n                        stopBits: stopBits,\n                        parity: parity\n                    });\n\n                    serialDebugState.isOpen = true;\n                    $('#serial-toggle-btn').text('\u5173\u95ed\u4e32\u53e3').removeClass('serial-btn-danger').addClass('serial-btn-success');\n                    $('.serial-port-config select').prop('disabled', true);\n                    addMessage('\u7cfb\u7edf', `\u4e32\u53e3\u5df2\u6253\u5f00 [\u6ce2\u7279\u7387: ${baudRate}, \u6570\u636e\u4f4d: ${dataBits}, \u505c\u6b62\u4f4d: ${stopBits}, \u6821\u9a8c: ${parity}]`);\n\n                    \/\/ \u5f00\u59cb\u8bfb\u53d6\u6570\u636e\n                    readSerialData();\n                } catch (error) {\n                    addMessage('\u9519\u8bef', `\u6253\u5f00\u4e32\u53e3\u5931\u8d25: ${error.message}`);\n                }\n            }\n\n            \/\/ \u5173\u95ed\u4e32\u53e3\n            async function closeSerialPort() {\n                if (!serialDebugState.port || !serialDebugState.isOpen) return;\n\n                try {\n                    \/\/ \u6e05\u7406\u63a5\u6536\u8d85\u65f6\u5b9a\u65f6\u5668\n                    if (serialDebugState.receiveTimeout) {\n                        clearTimeout(serialDebugState.receiveTimeout);\n                        serialDebugState.receiveTimeout = null;\n                    }\n\n                    \/\/ \u5982\u679c\u7f13\u51b2\u533a\u8fd8\u6709\u6570\u636e\uff0c\u5148\u663e\u793a\u51fa\u6765\n                    if (serialDebugState.receiveBuffer.length > 0) {\n                        const hexData = serialDebugState.receiveBuffer\n                            .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                            .join(' ');\n                        serialDebugState.receiveFrames++;\n                        updateCounters();\n                        addMessage('\u63a5\u6536', hexData);\n                        serialDebugState.receiveBuffer = [];\n                    }\n\n                    if (serialDebugState.reader) {\n                        await serialDebugState.reader.cancel();\n                    }\n                    await serialDebugState.port.close();\n                    serialDebugState.isOpen = false;\n                    $('#serial-toggle-btn').text('\u6253\u5f00\u4e32\u53e3').removeClass('serial-btn-success').addClass('serial-btn-danger');\n                    $('.serial-port-config select').prop('disabled', false);\n                    addMessage('\u7cfb\u7edf', '\u4e32\u53e3\u5df2\u5173\u95ed');\n                } catch (error) {\n                    addMessage('\u9519\u8bef', `\u5173\u95ed\u4e32\u53e3\u5931\u8d25: ${error.message}`);\n                }\n            }\n\n            \/\/ \u8bfb\u53d6\u4e32\u53e3\u6570\u636e\n            async function readSerialData() {\n                if (!serialDebugState.port || !serialDebugState.isOpen) return;\n\n                try {\n                    serialDebugState.reader = serialDebugState.port.readable.getReader();\n\n                    while (true) {\n                        const { value, done } = await serialDebugState.reader.read();\n                        if (done) break;\n\n                        \/\/ \u5c06\u63a5\u6536\u7684\u6570\u636e\u6dfb\u52a0\u5230\u7f13\u51b2\u533a\n                        serialDebugState.receiveBuffer.push(...value);\n                        serialDebugState.receiveBytes += value.length;\n\n                        \/\/ \u6e05\u9664\u4e4b\u524d\u7684\u8d85\u65f6\u5b9a\u65f6\u5668\n                        if (serialDebugState.receiveTimeout) {\n                            clearTimeout(serialDebugState.receiveTimeout);\n                        }\n\n                        \/\/ \u8bbe\u7f6e\u65b0\u7684\u8d85\u65f6\u5b9a\u65f6\u5668\uff0850ms\u5185\u6ca1\u6709\u65b0\u6570\u636e\u5219\u663e\u793a\uff09\n                        serialDebugState.receiveTimeout = setTimeout(() => {\n                            if (serialDebugState.receiveBuffer.length > 0) {\n                                \/\/ \u5408\u5e76\u663e\u793a\u7f13\u51b2\u533a\u4e2d\u7684\u6240\u6709\u6570\u636e\n                                const hexData = serialDebugState.receiveBuffer\n                                    .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                                    .join(' ');\n\n                                serialDebugState.receiveFrames++;\n                                updateCounters();\n                                addMessage('\u63a5\u6536', hexData);\n\n                                \/\/ \u6e05\u7a7a\u7f13\u51b2\u533a\n                                serialDebugState.receiveBuffer = [];\n                            }\n                        }, 50); \/\/ 50ms\u8d85\u65f6\uff0c\u53ef\u4ee5\u6839\u636e\u9700\u8981\u8c03\u6574\n                    }\n                } catch (error) {\n                    if (error.name !== 'NetworkError') {\n                        addMessage('\u9519\u8bef', `\u8bfb\u53d6\u6570\u636e\u5931\u8d25: ${error.message}`);\n                    }\n                } finally {\n                    serialDebugState.reader.releaseLock();\n                }\n            }\n\n            \/\/ CRC16\u8ba1\u7b97\u51fd\u6570\uff08\u4f4e\u5b57\u8282\u5728\u524d\uff09\n            function calculateCRC16_LSB(bytes) {\n                let crc = 0xFFFF;\n                for (let i = 0; i < bytes.length; i++) {\n                    crc ^= bytes[i];\n                    for (let j = 0; j < 8; j++) {\n                        if (crc & 1) {\n                            crc = (crc >> 1) ^ 0xA001;\n                        } else {\n                            crc >>= 1;\n                        }\n                    }\n                }\n                return crc;\n            }\n\n            \/\/ CRC16\u8ba1\u7b97\u51fd\u6570\uff08\u9ad8\u5b57\u8282\u5728\u524d\uff09\n            function calculateCRC16_MSB(bytes) {\n                let crc = 0xFFFF;\n                for (let i = 0; i < bytes.length; i++) {\n                    crc ^= (bytes[i] << 8);\n                    for (let j = 0; j < 8; j++) {\n                        if (crc & 0x8000) {\n                            crc = ((crc << 1) ^ 0x1021) & 0xFFFF;\n                        } else {\n                            crc = (crc << 1) & 0xFFFF;\n                        }\n                    }\n                }\n                return crc;\n            }\n\n            \/\/ \u6821\u9a8c\u548c\uff08Checksum\uff09\u8ba1\u7b97\n            function calculateChecksum(bytes, startByte, endByte) {\n                let sum = 0;\n                const actualEnd = endByte === 0 || endByte > bytes.length ? bytes.length : endByte;\n                for (let i = startByte - 1; i < actualEnd; i++) {\n                    sum += bytes[i];\n                }\n                return (sum & 0xFF);\n            }\n\n            \/\/ \u5f02\u6216\u6821\u9a8c\uff08XOR\uff09\u8ba1\u7b97\n            function calculateXOR(bytes, startByte, endByte) {\n                let xor = 0;\n                const actualEnd = endByte === 0 || endByte > bytes.length ? bytes.length : endByte;\n                for (let i = startByte - 1; i < actualEnd; i++) {\n                    xor ^= bytes[i];\n                }\n                return xor;\n            }\n\n            \/\/ \u5904\u7406\u6821\u9a8c\u548c\u6dfb\u52a0\u5230\u6570\u636e\uff08\u652f\u6301\u6307\u5b9a\u53d1\u9001\u533a\uff09\n            function processChecksum(bytes, zone) {\n                zone = zone || 1; \/\/ \u9ed8\u8ba4\u53d1\u9001\u533a1\n                const checksumMode = $(`.serial-checksum-mode[data-zone=\"${zone}\"]`).val();\n                if (checksumMode === 'none') {\n                    return bytes;\n                }\n\n                let checksumBytes = new Uint8Array(bytes);\n\n                if (checksumMode === 'crc16-lsb') {\n                    const crc = calculateCRC16_LSB(bytes);\n                    checksumBytes = new Uint8Array(bytes.length + 2);\n                    checksumBytes.set(bytes);\n                    checksumBytes[bytes.length] = crc & 0xFF;        \/\/ \u4f4e\u5b57\u8282\u5728\u524d\n                    checksumBytes[bytes.length + 1] = (crc >> 8) & 0xFF;\n                } else if (checksumMode === 'crc16-msb') {\n                    const crc = calculateCRC16_MSB(bytes);\n                    checksumBytes = new Uint8Array(bytes.length + 2);\n                    checksumBytes.set(bytes);\n                    checksumBytes[bytes.length] = (crc >> 8) & 0xFF; \/\/ \u9ad8\u5b57\u8282\u5728\u524d\n                    checksumBytes[bytes.length + 1] = crc & 0xFF;\n                } else if (checksumMode === 'checksum') {\n                    const startByte = parseInt($(`.serial-checksum-start[data-zone=\"${zone}\"]`).val()) || 1;\n                    const endByte = parseInt($(`.serial-checksum-end[data-zone=\"${zone}\"]`).val()) || 0;\n                    const checksum = calculateChecksum(bytes, startByte, endByte);\n                    checksumBytes = new Uint8Array(bytes.length + 1);\n                    checksumBytes.set(bytes);\n                    checksumBytes[bytes.length] = checksum;\n                } else if (checksumMode === 'xor') {\n                    const startByte = parseInt($(`.serial-checksum-start[data-zone=\"${zone}\"]`).val()) || 1;\n                    const endByte = parseInt($(`.serial-checksum-end[data-zone=\"${zone}\"]`).val()) || 0;\n                    const xor = calculateXOR(bytes, startByte, endByte);\n                    checksumBytes = new Uint8Array(bytes.length + 1);\n                    checksumBytes.set(bytes);\n                    checksumBytes[bytes.length] = xor;\n                }\n\n                return checksumBytes;\n            }\n\n            \/\/ \u53d1\u9001\u6570\u636e\uff08\u652f\u6301\u6307\u5b9a\u53d1\u9001\u533a\u7684\u6821\u9a8c\uff09\n            async function sendData(data, zone) {\n                if (!serialDebugState.port || !serialDebugState.isOpen) {\n                    addMessage('\u9519\u8bef', '\u4e32\u53e3\u672a\u6253\u5f00');\n                    return;\n                }\n\n                zone = zone || 1; \/\/ \u9ed8\u8ba4\u53d1\u9001\u533a1\n\n                try {\n                    const writer = serialDebugState.port.writable.getWriter();\n                    const hexMode = $('#serial-hex-mode').is(':checked');\n                    let bytes;\n\n                    if (hexMode) {\n                        \/\/ 16\u8fdb\u5236\u6a21\u5f0f\n                        const hexArray = data.trim().split(\/\\s+\/);\n                        bytes = new Uint8Array(hexArray.map(hex => parseInt(hex, 16)));\n                    } else {\n                        \/\/ ASCII\u6a21\u5f0f\n                        bytes = new TextEncoder().encode(data);\n                    }\n\n                    \/\/ \u5904\u7406\u6821\u9a8c\uff08\u4f20\u5165\u53d1\u9001\u533a\u53f7\uff09\n                    bytes = processChecksum(bytes, zone);\n\n                    await writer.write(bytes);\n                    writer.releaseLock();\n\n                    serialDebugState.sendFrames++;\n                    serialDebugState.sendBytes += bytes.length;\n                    updateCounters();\n\n                    const hexData = Array.from(bytes).map(b => b.toString(16).toUpperCase().padStart(2, '0')).join(' ');\n                    addMessage('\u53d1\u9001', hexData);\n                } catch (error) {\n                    addMessage('\u9519\u8bef', `\u53d1\u9001\u6570\u636e\u5931\u8d25: ${error.message}`);\n                }\n            }\n\n            \/\/ \u66f4\u65b0\u8ba1\u6570\u5668\n            function updateCounters() {\n                $('#serial-send-frames').text(serialDebugState.sendFrames);\n                $('#serial-send-bytes').text(serialDebugState.sendBytes);\n                $('#serial-receive-frames').text(serialDebugState.receiveFrames);\n                $('#serial-receive-bytes').text(serialDebugState.receiveBytes);\n            }\n\n            \/\/ \u91cd\u7f6e\u8ba1\u6570\u5668\n            $('#serial-reset-counter').on('click', function() {\n                serialDebugState.sendFrames = 0;\n                serialDebugState.sendBytes = 0;\n                serialDebugState.receiveFrames = 0;\n                serialDebugState.receiveBytes = 0;\n                updateCounters();\n            });\n\n            \/\/ \u6dfb\u52a0\u6d88\u606f\n            function addMessage(type, data) {\n                const timestamp = serialDebugState.showTimestamp ? getCurrentTime() + ' ' : '';\n                const $output = $('#serial-message-output');\n                const $message = $('<div class=\"serial-message\"><\/div>');\n\n                $message.html(`<span class=\"serial-message-time\">${timestamp}<\/span><span class=\"serial-message-type serial-message-${type.toLowerCase()}\">${type}:<\/span> <span class=\"serial-message-data\">${data}<\/span>`);\n\n                $output.append($message);\n\n                \/\/ \u81ea\u52a8\u6eda\u52a8\n                if (serialDebugState.autoScroll) {\n                    $output.scrollTop($output[0].scrollHeight);\n                }\n            }\n\n            \/\/ \u83b7\u53d6\u5f53\u524d\u65f6\u95f4\n            function getCurrentTime() {\n                const now = new Date();\n                const h = now.getHours().toString().padStart(2, '0');\n                const m = now.getMinutes().toString().padStart(2, '0');\n                const s = now.getSeconds().toString().padStart(2, '0');\n                const ms = now.getMilliseconds().toString().padStart(3, '0');\n                return `${h}:${m}:${s}.${ms}`;\n            }\n\n            \/\/ \u6e05\u7a7a\u6d88\u606f\n            $('#serial-clear-messages').on('click', function() {\n                $('#serial-message-output').empty();\n            });\n\n            \/\/ \u81ea\u52a8\u6eda\u52a8\u9009\u9879\n            $('#serial-auto-scroll').on('change', function() {\n                serialDebugState.autoScroll = $(this).is(':checked');\n            });\n\n            \/\/ \u65f6\u95f4\u6233\u9009\u9879\n            $('#serial-show-timestamp').on('change', function() {\n                serialDebugState.showTimestamp = $(this).is(':checked');\n            });\n\n            \/\/ \u6821\u9a8c\u6a21\u5f0f\u9009\u62e9\u53d8\u5316\u4e8b\u4ef6\uff08\u6bcf\u4e2a\u53d1\u9001\u533a\u72ec\u7acb\uff09\n            $(document).on('change', '.serial-checksum-mode', function() {\n                const zone = $(this).data('zone');\n                const mode = $(this).val();\n                const $rangeConfig = $(`.serial-checksum-range[data-zone=\"${zone}\"]`);\n\n                \/\/ \u53ea\u6709\u6821\u9a8c\u548c\u548c\u5f02\u6216\u6821\u9a8c\u9700\u8981\u663e\u793a\u8303\u56f4\u9009\u62e9\n                if (mode === 'checksum' || mode === 'xor') {\n                    $rangeConfig.show();\n                } else {\n                    $rangeConfig.hide();\n                }\n            });\n\n            \/\/ \u53d1\u9001\u533a\u6309\u94ae\u4e8b\u4ef6 - \u4f7f\u7528\u4e8b\u4ef6\u59d4\u6258\n            $(document).on('click', '.serial-zone-actions button', function(e) {\n                e.preventDefault();\n                const zone = $(this).data('zone');\n                const action = $(this).data('action');\n                const $textarea = $(`#serial-send-zone-${zone}`);\n\n                if (action === 'clear') {\n                    $textarea.val('');\n                    addMessage('\u7cfb\u7edf', `\u5df2\u6e05\u7a7a\u53d1\u9001${zone}\u533a`);\n                } else if (action === 'send') {\n                    const data = $textarea.val().trim();\n                    if (data) {\n                        \/\/ \u68c0\u67e5\u662f\u5426\u542f\u7528\u5faa\u73af\n                        const cycleCount = parseInt($('#serial-cycle-count').val()) || 1;\n                        const isInfinite = $('#serial-infinite-cycle').is(':checked');\n                        const delay = parseInt($('#serial-send-delay').val()) || 1000;\n\n                        if (isInfinite || cycleCount > 1) {\n                            \/\/ \u542f\u52a8\u5faa\u73af\u53d1\u9001\n                            startCycleSend(data, zone, cycleCount, isInfinite, delay);\n                        } else {\n                            \/\/ \u5355\u6b21\u53d1\u9001\n                            sendData(data, zone);\n                        }\n                    } else {\n                        addMessage('\u9519\u8bef', `\u53d1\u9001${zone}\u533a\u4e3a\u7a7a\uff0c\u8bf7\u8f93\u5165\u6570\u636e`);\n                    }\n                }\n            });\n\n            \/\/ \u5faa\u73af\u53d1\u9001\u51fd\u6570\uff08\u652f\u6301\u533a\u53f7\uff09\n            function startCycleSend(data, zone, maxCount, isInfinite, delay) {\n                \/\/ \u5982\u679c\u5df2\u6709\u5faa\u73af\u5728\u8fd0\u884c\uff0c\u5148\u505c\u6b62\n                if (serialDebugState.cycleInterval) {\n                    clearInterval(serialDebugState.cycleInterval);\n                    serialDebugState.cycleInterval = null;\n                }\n\n                let currentCount = 0;\n                const totalCount = isInfinite ? '\u221e' : maxCount;\n\n                \/\/ \u6dfb\u52a0\u89c6\u89c9\u53cd\u9988\uff1a\u6309\u94ae\u53d8\u7ea2\u5e76\u95ea\u70c1\n                $('#serial-stop-cycle').addClass('cycling').text('\u23f8 \u505c\u6b62\u5faa\u73af');\n\n                addMessage('\u7cfb\u7edf', `\ud83d\udd04 \u5f00\u59cb\u5faa\u73af\u53d1\u9001\uff0c\u5171 ${totalCount} \u6b21\uff0c\u5ef6\u8fdf ${delay}ms`);\n\n                \/\/ \u7acb\u5373\u53d1\u9001\u7b2c\u4e00\u6b21\n                sendData(data, zone);\n                currentCount++;\n\n                \/\/ \u8bbe\u7f6e\u5b9a\u65f6\u5668\u8fdb\u884c\u540e\u7eed\u53d1\u9001\n                serialDebugState.cycleInterval = setInterval(function() {\n                    if (!isInfinite && currentCount >= maxCount) {\n                        \/\/ \u8fbe\u5230\u6b21\u6570\uff0c\u505c\u6b62\u5faa\u73af\n                        clearInterval(serialDebugState.cycleInterval);\n                        serialDebugState.cycleInterval = null;\n                        $('#serial-stop-cycle').removeClass('cycling').text('\u505c\u6b62\u5faa\u73af');\n                        addMessage('\u7cfb\u7edf', `\u2705 \u5faa\u73af\u53d1\u9001\u5b8c\u6210\uff0c\u5171\u53d1\u9001 ${currentCount} \u6b21`);\n                        return;\n                    }\n\n                    \/\/ \u68c0\u67e5\u4e32\u53e3\u662f\u5426\u8fd8\u5728\u8fde\u63a5\n                    if (!serialDebugState.isOpen) {\n                        clearInterval(serialDebugState.cycleInterval);\n                        serialDebugState.cycleInterval = null;\n                        $('#serial-stop-cycle').removeClass('cycling').text('\u505c\u6b62\u5faa\u73af');\n                        addMessage('\u9519\u8bef', '\u274c \u4e32\u53e3\u5df2\u65ad\u5f00\uff0c\u5faa\u73af\u53d1\u9001\u5df2\u505c\u6b62');\n                        return;\n                    }\n\n                    sendData(data, zone);\n                    currentCount++;\n\n                    if (!isInfinite) {\n                        addMessage('\u7cfb\u7edf', `\ud83d\udd04 \u5faa\u73af\u53d1\u9001\u8fdb\u5ea6: ${currentCount}\/${maxCount}`);\n                    }\n                }, delay);\n            }\n\n            \/\/ \u505c\u6b62\u5faa\u73af\n            $('#serial-stop-cycle').on('click', function() {\n                if (serialDebugState.cycleInterval) {\n                    clearInterval(serialDebugState.cycleInterval);\n                    serialDebugState.cycleInterval = null;\n                    $(this).removeClass('cycling').text('\u505c\u6b62\u5faa\u73af');\n                    addMessage('\u7cfb\u7edf', '\u23f9 \u5faa\u73af\u53d1\u9001\u5df2\u624b\u52a8\u505c\u6b62');\n                } else {\n                    addMessage('\u7cfb\u7edf', '\u26a0\ufe0f \u5f53\u524d\u6ca1\u6709\u6b63\u5728\u8fd0\u884c\u7684\u5faa\u73af\u53d1\u9001');\n                }\n            });\n\n            \/\/ \u4fdd\u5b58\u6570\u636e\n            $('#serial-save-data').on('click', function() {\n                const messages = [];\n                $('#serial-message-output .serial-message').each(function() {\n                    messages.push($(this).text());\n                });\n\n                const content = messages.join('\\n');\n                const blob = new Blob([content], { type: 'text\/plain' });\n                const url = URL.createObjectURL(blob);\n                const a = document.createElement('a');\n                a.href = url;\n                a.download = `serial-debug-${Date.now()}.txt`;\n                a.click();\n                URL.revokeObjectURL(url);\n                addMessage('\u7cfb\u7edf', '\u6570\u636e\u5df2\u4fdd\u5b58');\n            });\n\n            \/\/ \u521d\u59cb\u5316\n            loadSerialPorts();\n\n            \/\/ \u5ef6\u8fdf\u52a0\u8f7d\u4e32\u53e3\u5217\u8868\uff08\u7b49\u5f85\u9875\u9762\u5b8c\u5168\u52a0\u8f7d\uff09\n            setTimeout(function() {\n                if ('serial' in navigator) {\n                    loadSerialPorts();\n                }\n            }, 500);\n\n            addMessage('\u7cfb\u7edf', '\u4e32\u53e3\u8c03\u8bd5\u6a21\u5757\u521d\u59cb\u5316\u5b8c\u6210');\n        });\n        <\/script>\n                            <\/div>\r\n                \r\n                <!-- \u7ee7\u7535\u5668\u63a7\u5236 \u9009\u9879\u5361 -->\r\n                                    <div id=\"relay-control-tab\" class=\"modbus-tab-content \">\r\n                                <div class=\"relay-control-container\">\n            <div class=\"relay-control-layout\">\n                <!-- \u5de6\u4fa7\u63a7\u5236\u9762\u677f -->\n                <div class=\"relay-control-left-panel\">\n                    <!-- \u4e32\u53e3\u53c2\u6570\u914d\u7f6e -->\n                    <div class=\"relay-section relay-port-config\">\n                        <h3><i class=\"dashicons dashicons-admin-settings\"><\/i> \u4e32\u53e3\u53c2\u6570 <span class=\"mini-program-badge\" style=\"position:relative;display:inline-block;font-size:16px;color:#e53935;font-weight:bold;cursor:pointer;margin-left:10px;\" onmouseover=\"this.querySelector('img').style.display='block'\" onmouseout=\"this.querySelector('img').style.display='none'\">\u5c0f\u7a0b\u5e8f\u7248<img decoding=\"async\" src=\"https:\/\/image.modbus.cn\/wp-content\/uploads\/2025\/12\/20251231180825631.webp\" style=\"display:none;position:absolute;left:0;top:25px;z-index:9999;max-width:300px;border:1px solid #ccc;box-shadow:0 2px 10px rgba(0,0,0,0.2);border-radius:4px;\"\/ loading=\"lazy\" title=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" alt=\"Modbus\u5728\u7ebf\u8c03\u8bd5\u5de5\u5177\u63d2\u56fe1\" \/><\/span><\/h3>\n                        <div class=\"relay-form-group\">\n                            <label>COM\u7aef\u53e3<\/label>\n                            <select class=\"relay-control\" id=\"relay-port-select\">\n                                <option value=\"\">-- \u672a\u68c0\u6d4b\u5230\u4e32\u53e3 --<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"relay-form-group\">\n                            <label>\u6ce2\u7279\u7387<\/label>\n                            <select class=\"relay-control\" id=\"relay-baudrate\">\n                                <option value=\"300\">300<\/option>\n                                <option value=\"600\">600<\/option>\n                                <option value=\"1200\">1200<\/option>\n                                <option value=\"2400\">2400<\/option>\n                                <option value=\"4800\">4800<\/option>\n                                <option value=\"9600\" selected>9600<\/option>\n                                <option value=\"14400\">14400<\/option>\n                                <option value=\"19200\">19200<\/option>\n                                <option value=\"38400\">38400<\/option>\n                                <option value=\"57600\">57600<\/option>\n                                <option value=\"115200\">115200<\/option>\n                                <option value=\"128000\">128000<\/option>\n                                <option value=\"230400\">230400<\/option>\n                                <option value=\"256000\">256000<\/option>\n                                <option value=\"460800\">460800<\/option>\n                                <option value=\"921600\">921600<\/option>\n                            <\/select>\n                        <\/div>\n                        <div class=\"relay-form-group-inline\">\n                            <div class=\"relay-form-col\">\n                                <label>\u6570\u636e\u4f4d<\/label>\n                                <select class=\"relay-control\" id=\"relay-databits\">\n                                    <option value=\"7\">7<\/option>\n                                    <option value=\"8\" selected>8<\/option>\n                                <\/select>\n                            <\/div>\n                            <div class=\"relay-form-col\">\n                                <label>\u6821\u9a8c\u4f4d<\/label>\n                                <select class=\"relay-control\" id=\"relay-parity\">\n                                    <option value=\"none\" selected>\u65e0<\/option>\n                                    <option value=\"odd\">\u5947<\/option>\n                                    <option value=\"even\">\u5076<\/option>\n                                <\/select>\n                            <\/div>\n                            <div class=\"relay-form-col\">\n                                <label>\u505c\u6b62\u4f4d<\/label>\n                                <select class=\"relay-control\" id=\"relay-stopbits\">\n                                    <option value=\"1\" selected>1<\/option>\n                                    <option value=\"2\">2<\/option>\n                                <\/select>\n                            <\/div>\n                        <\/div>\n                        <div class=\"relay-connection-status\">\n                            <span class=\"relay-status-indicator\" id=\"relay-status-indicator\"><\/span>\n                            <span class=\"relay-status-text\" id=\"relay-status-text\">\u672a\u8fde\u63a5<\/span>\n                        <\/div>\n                        <button class=\"relay-btn relay-btn-primary relay-btn-block\" id=\"relay-connect-btn\">\n                            <i class=\"dashicons dashicons-admin-plugins\"><\/i> \u8fde\u63a5\u4e32\u53e3\n                        <\/button>\n                    <\/div>\n\n                    <!-- \u7edf\u8ba1\u4fe1\u606f -->\n                    <div class=\"relay-section relay-statistics\">\n                        <h3><i class=\"dashicons dashicons-chart-bar\"><\/i> \u901a\u4fe1\u7edf\u8ba1<\/h3>\n                        <div class=\"relay-stat-grid\">\n                            <div class=\"relay-stat-item\">\n                                <div class=\"relay-stat-label\">\u53d1\u9001\u5e27\u6570<\/div>\n                                <div class=\"relay-stat-value\" id=\"relay-tx-frames\">0<\/div>\n                            <\/div>\n                            <div class=\"relay-stat-item\">\n                                <div class=\"relay-stat-label\">\u53d1\u9001\u5b57\u8282<\/div>\n                                <div class=\"relay-stat-value\" id=\"relay-tx-bytes\">0<\/div>\n                            <\/div>\n                            <div class=\"relay-stat-item\">\n                                <div class=\"relay-stat-label\">\u63a5\u6536\u5e27\u6570<\/div>\n                                <div class=\"relay-stat-value\" id=\"relay-rx-frames\">0<\/div>\n                            <\/div>\n                            <div class=\"relay-stat-item\">\n                                <div class=\"relay-stat-label\">\u63a5\u6536\u5b57\u8282<\/div>\n                                <div class=\"relay-stat-value\" id=\"relay-rx-bytes\">0<\/div>\n                            <\/div>\n                            <div class=\"relay-stat-item\">\n                                <div class=\"relay-stat-label\">\u9519\u8bef\u8ba1\u6570<\/div>\n                                <div class=\"relay-stat-value relay-stat-error\" id=\"relay-errors\">0<\/div>\n                            <\/div>\n                        <\/div>\n                        <button class=\"relay-btn relay-btn-secondary relay-btn-block\" id=\"relay-reset-stats\">\n                            <i class=\"dashicons dashicons-image-rotate\"><\/i> \u91cd\u7f6e\u7edf\u8ba1\n                        <\/button>\n                    <\/div>\n\n                    <!-- IO\u6570\u91cf\u914d\u7f6e -->\n                    <div class=\"relay-section relay-io-config\">\n                        <h3><i class=\"dashicons dashicons-admin-generic\"><\/i> IO\u914d\u7f6e<\/h3>\n                        <div class=\"relay-form-group\">\n                            <label>\u8f93\u51fa\u70b9\u6570\uff08\u7ee7\u7535\u5668\uff09<\/label>\n                            <input type=\"number\" class=\"relay-control\" id=\"relay-output-count\" value=\"4\" min=\"1\" max=\"64\">\n                        <\/div>\n                        <div class=\"relay-form-group\">\n                            <label>\u8f93\u5165\u70b9\u6570<\/label>\n                            <input type=\"number\" class=\"relay-control\" id=\"relay-input-count\" value=\"4\" min=\"1\" max=\"32\">\n                        <\/div>\n                        <button class=\"relay-btn relay-btn-success relay-btn-block\" id=\"relay-apply-config\">\n                            <i class=\"dashicons dashicons-yes\"><\/i> \u5e94\u7528\u914d\u7f6e\n                        <\/button>\n                    <\/div>\n                <\/div>\n\n                <!-- \u53f3\u4fa7\u4e3b\u5de5\u4f5c\u533a -->\n                <div class=\"relay-control-right-panel\">\n                    <!-- IO\u72b6\u6001\u663e\u793a\u533a -->\n                    <div class=\"relay-section relay-io-status\">\n                        <div class=\"relay-io-header\">\n                            <h3><i class=\"dashicons dashicons-lightbulb\"><\/i> \u8f93\u51fa\u72b6\u6001\uff08\u7ee7\u7535\u5668\uff09<\/h3>\n                            <div class=\"relay-batch-controls\">\n                                <button class=\"relay-btn relay-btn-small relay-btn-success\" id=\"relay-all-on\" title=\"\u5168\u90e8\u5f00\u542f\">\n                                    <i class=\"dashicons dashicons-yes\"><\/i> \u5168\u5f00\n                                <\/button>\n                                <button class=\"relay-btn relay-btn-small relay-btn-danger\" id=\"relay-all-off\" title=\"\u5168\u90e8\u5173\u95ed\">\n                                    <i class=\"dashicons dashicons-no\"><\/i> \u5168\u5173\n                                <\/button>\n                                <button class=\"relay-btn relay-btn-small relay-btn-info\" id=\"relay-odd-on\" title=\"\u5355\u6570\u5f00\u542f\">\n                                    \u5355\u6570\n                                <\/button>\n                                <button class=\"relay-btn relay-btn-small relay-btn-info\" id=\"relay-even-on\" title=\"\u53cc\u6570\u5f00\u542f\">\n                                    \u53cc\u6570\n                                <\/button>\n                                <button class=\"relay-btn relay-btn-small relay-btn-warning\" id=\"relay-sequence\" title=\"\u5e8f\u5217\u63a7\u5236\">\n                                    <i class=\"dashicons dashicons-controls-play\"><\/i> \u5e8f\u5217\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                        <div class=\"relay-outputs-grid\" id=\"relay-outputs-grid\">\n                            <!-- \u52a8\u6001\u751f\u6210\u7ee7\u7535\u5668\u8f93\u51fa\u70b9 -->\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"relay-section relay-inputs-section\">\n                        <div class=\"relay-io-header\">\n                            <h3><i class=\"dashicons dashicons-visibility\"><\/i> \u8f93\u5165\u72b6\u6001<\/h3>\n                            <button class=\"relay-btn relay-btn-small relay-btn-secondary\" id=\"relay-refresh-inputs\">\n                                <i class=\"dashicons dashicons-update\"><\/i> \u5237\u65b0\n                            <\/button>\n                        <\/div>\n                        <div class=\"relay-inputs-grid\" id=\"relay-inputs-grid\">\n                            <!-- \u52a8\u6001\u751f\u6210\u8f93\u5165\u70b9 -->\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u63a7\u5236\u547d\u4ee4\u751f\u6210\u533a -->\n                    <div class=\"relay-section relay-command-section\">\n                        <h3><i class=\"dashicons dashicons-admin-tools\"><\/i> \u547d\u4ee4\u63a7\u5236<\/h3>\n                        <div class=\"relay-command-tabs\">\n                            <button class=\"relay-cmd-tab active\" data-tab=\"single\">\u5355\u70b9\u63a7\u5236<\/button>\n                            <button class=\"relay-cmd-tab\" data-tab=\"multi\">\u591a\u70b9\u63a7\u5236<\/button>\n                            <button class=\"relay-cmd-tab\" data-tab=\"template\">\u547d\u4ee4\u6a21\u677f<\/button>\n                        <\/div>\n\n                        <div class=\"relay-cmd-content active\" id=\"relay-cmd-single\">\n                            <div class=\"relay-form-group-inline\">\n                                <div class=\"relay-form-col\">\n                                    <label>\u7ee7\u7535\u5668\u7f16\u53f7<\/label>\n                                    <input type=\"number\" class=\"relay-control\" id=\"relay-single-num\" value=\"1\" min=\"1\" max=\"64\">\n                                <\/div>\n                                <div class=\"relay-form-col\">\n                                    <label>\u64cd\u4f5c<\/label>\n                                    <select class=\"relay-control\" id=\"relay-single-action\">\n                                        <option value=\"on\">\u5f00\u542f<\/option>\n                                        <option value=\"off\">\u5173\u95ed<\/option>\n                                        <option value=\"toggle\">\u5207\u6362<\/option>\n                                    <\/select>\n                                <\/div>\n                                <div class=\"relay-form-col\">\n                                    <label>&nbsp;<\/label>\n                                    <button class=\"relay-btn relay-btn-primary\" id=\"relay-single-send\">\n                                        <i class=\"dashicons dashicons-controls-forward\"><\/i> \u53d1\u9001\n                                    <\/button>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n\n                        <div class=\"relay-cmd-content\" id=\"relay-cmd-multi\">\n                            <div class=\"relay-form-group\">\n                                <label>\u9009\u62e9\u591a\u4e2a\u7ee7\u7535\u5668\uff08\u9017\u53f7\u5206\u9694\uff0c\u5982: 1,3,5-8\uff09<\/label>\n                                <input type=\"text\" class=\"relay-control\" id=\"relay-multi-nums\" placeholder=\"\u4f8b\u5982: 1,2,3 \u6216 1-4,7,9\">\n                            <\/div>\n                            <div class=\"relay-form-group-inline\">\n                                <div class=\"relay-form-col\">\n                                    <label>\u64cd\u4f5c<\/label>\n                                    <select class=\"relay-control\" id=\"relay-multi-action\">\n                                        <option value=\"on\">\u5f00\u542f<\/option>\n                                        <option value=\"off\">\u5173\u95ed<\/option>\n                                    <\/select>\n                                <\/div>\n                                <div class=\"relay-form-col\">\n                                    <label>&nbsp;<\/label>\n                                    <button class=\"relay-btn relay-btn-primary\" id=\"relay-multi-send\">\n                                        <i class=\"dashicons dashicons-controls-forward\"><\/i> \u6279\u91cf\u53d1\u9001\n                                    <\/button>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n\n                        <div class=\"relay-cmd-content\" id=\"relay-cmd-template\">\n                            <div class=\"relay-form-group\">\n                                <label>\u547d\u4ee4\u6a21\u677f<\/label>\n                                <select class=\"relay-control\" id=\"relay-template-select\">\n                                    <option value=\"\">-- \u9009\u62e9\u6a21\u677f --<\/option>\n                                    <option value=\"all-on\">\u5168\u90e8\u5f00\u542f<\/option>\n                                    <option value=\"all-off\">\u5168\u90e8\u5173\u95ed<\/option>\n                                    <option value=\"alternate\">\u4ea4\u66ff\u95ea\u70c1<\/option>\n                                <\/select>\n                            <\/div>\n                            <div class=\"relay-form-group\">\n                                <label>\u81ea\u5b9a\u4e49\u547d\u4ee4\uff08\u5341\u516d\u8fdb\u5236\uff0c\u7a7a\u683c\u5206\u9694\uff09<\/label>\n                                <textarea class=\"relay-control\" id=\"relay-custom-cmd\" rows=\"3\" placeholder=\"\u4f8b\u5982: 01 05 00 00 FF 00\"><\/textarea>\n                            <\/div>\n                            <button class=\"relay-btn relay-btn-primary relay-btn-block\" id=\"relay-template-send\">\n                                <i class=\"dashicons dashicons-controls-forward\"><\/i> \u53d1\u9001\u547d\u4ee4\n                            <\/button>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u81ea\u52a8\u67e5\u8be2\u8bbe\u7f6e -->\n                    <div class=\"relay-section relay-auto-query\">\n                        <h3><i class=\"dashicons dashicons-clock\"><\/i> \u81ea\u52a8\u67e5\u8be2<\/h3>\n                        <div class=\"relay-form-group-inline\">\n                            <div class=\"relay-form-col\">\n                                <label>\u67e5\u8be2\u95f4\u9694\uff08ms\uff09<\/label>\n                                <input type=\"number\" class=\"relay-control\" id=\"relay-query-interval\" value=\"1000\" min=\"100\" max=\"10000\" step=\"100\">\n                            <\/div>\n                            <div class=\"relay-form-col\">\n                                <label>\u67e5\u8be2\u6a21\u5f0f<\/label>\n                                <select class=\"relay-control\" id=\"relay-query-mode\">\n                                    <option value=\"all\" selected>\u5168\u90e8<\/option>\n                                    <option value=\"output\">\u4ec5\u8f93\u51fa<\/option>\n                                    <option value=\"input\">\u4ec5\u8f93\u5165<\/option>\n                                <\/select>\n                            <\/div>\n                            <div class=\"relay-form-col\">\n                                <label>&nbsp;<\/label>\n                                <button class=\"relay-btn relay-btn-warning\" id=\"relay-query-toggle\">\n                                    <i class=\"dashicons dashicons-controls-play\"><\/i> \u5f00\u59cb\u67e5\u8be2\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <!-- \u547d\u4ee4\u65e5\u5fd7 -->\n                    <div class=\"relay-section relay-log-section\">\n                        <div class=\"relay-log-header\">\n                            <h3><i class=\"dashicons dashicons-media-text\"><\/i> \u547d\u4ee4\u65e5\u5fd7<\/h3>\n                            <button class=\"relay-btn relay-btn-small relay-btn-secondary\" id=\"relay-clear-log\">\n                                <i class=\"dashicons dashicons-trash\"><\/i> \u6e05\u7a7a\n                            <\/button>\n                        <\/div>\n                        <div class=\"relay-log-output\" id=\"relay-log-output\">\n                            <div class=\"relay-log-entry relay-log-info\">\n                                <span class=\"relay-log-time\">[\u7cfb\u7edf]<\/span>\n                                <span class=\"relay-log-msg\">\u7ee7\u7535\u5668\u63a7\u5236\u6a21\u5757\u5df2\u51c6\u5907\u5c31\u7eea\uff0c\u8bf7\u8fde\u63a5\u4e32\u53e3...<\/span>\n                            <\/div>\n                        <\/div>\n                        <div class=\"relay-log-controls\">\n                            <label class=\"relay-checkbox-label\">\n                                <input type=\"checkbox\" id=\"relay-auto-scroll\" checked> \u81ea\u52a8\u6eda\u52a8\n                            <\/label>\n                            <label class=\"relay-checkbox-label\">\n                                <input type=\"checkbox\" id=\"relay-show-hex\" checked> \u663e\u793a\u5341\u516d\u8fdb\u5236\n                            <\/label>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <script>\n        jQuery(document).ready(function($) {\n            \/\/ \u68c0\u67e5Web Serial API\u652f\u6301\n            if (!('serial' in navigator)) {\n                addLog('\u9519\u8bef', '\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301 Web Serial API\u3002\u8bf7\u4f7f\u7528 Chrome\u3001Edge \u6216 Opera \u6d4f\u89c8\u5668\u3002', 'error');\n                $('#relay-connect-btn').prop('disabled', true);\n                $('#relay-refresh-ports').prop('disabled', true);\n            }\n\n            \/\/ \u7ee7\u7535\u5668\u63a7\u5236\u72b6\u6001\n            const relayState = {\n                port: null,\n                reader: null,\n                writer: null,\n                isConnected: false,\n                outputCount: 4,\n                inputCount: 4,\n                outputs: {},\n                inputs: {},\n                txFrames: 0,\n                txBytes: 0,\n                rxFrames: 0,\n                rxBytes: 0,\n                errors: 0,\n                queryInterval: null,\n                isQuerying: false,\n                sequenceInterval: null,\n                isSequencing: false\n            };\n\n            \/\/ \u52a0\u8f7d\u4e32\u53e3\u5217\u8868\n            async function loadSerialPorts() {\n                if (!('serial' in navigator)) {\n                    return;\n                }\n\n                try {\n                    const ports = await navigator.serial.getPorts();\n                    const $portSelect = $('#relay-port-select');\n                    $portSelect.empty();\n\n                    if (ports.length === 0) {\n                        $portSelect.append('<option value=\"\">-- \u672a\u68c0\u6d4b\u5230\u4e32\u53e3\uff0c\u8bf7\u70b9\u51fb\"\u8fde\u63a5\u4e32\u53e3\"\u6309\u94ae\u6388\u6743 --<\/option>');\n                        addLog('\u7cfb\u7edf', '\u672a\u68c0\u6d4b\u5230\u4e32\u53e3\u8bbe\u5907\uff0c\u8bf7\u70b9\u51fb\"\u8fde\u63a5\u4e32\u53e3\"\u6309\u94ae\u9009\u62e9\u8bbe\u5907', 'info');\n                    } else {\n                        $portSelect.append('<option value=\"\">-- \u8bf7\u9009\u62e9\u4e32\u53e3 --<\/option>');\n                        ports.forEach((port, index) => {\n                            const info = port.getInfo();\n                            \/\/ \u663e\u793a\u8be6\u7ec6\u7684\u4e32\u53e3\u4fe1\u606f\uff08\u53c2\u8003\u4e32\u53e3\u8c03\u8bd5\u5b9e\u73b0\uff09\n                            const label = `COM${index + 1} (VID: ${info.usbVendorId || 'N\/A'}, PID: ${info.usbProductId || 'N\/A'})`;\n                            const $option = $('<option><\/option>')\n                                .val(index)\n                                .text(label)\n                                .data('port', port);\n                            $portSelect.append($option);\n                        });\n                        addLog('\u7cfb\u7edf', `\u5df2\u68c0\u6d4b\u5230 ${ports.length} \u4e2a\u4e32\u53e3\u8bbe\u5907`, 'success');\n                    }\n                } catch (error) {\n                    console.error('\u83b7\u53d6\u4e32\u53e3\u5217\u8868\u5931\u8d25:', error);\n                    addLog('\u9519\u8bef', `\u83b7\u53d6\u4e32\u53e3\u5217\u8868\u5931\u8d25: ${error.message}`, 'error');\n                }\n            }\n\n            \/\/ \u521d\u59cb\u5316IO\n            function initIO() {\n                const outputCount = parseInt($('#relay-output-count').val()) || 4;\n                const inputCount = parseInt($('#relay-input-count').val()) || 4;\n\n                relayState.outputCount = outputCount;\n                relayState.inputCount = inputCount;\n\n                \/\/ \u521d\u59cb\u5316\u8f93\u51fa\u72b6\u6001\n                relayState.outputs = {};\n                for (let i = 1; i <= outputCount; i++) {\n                    relayState.outputs[i] = false;\n                }\n\n                \/\/ \u521d\u59cb\u5316\u8f93\u5165\u72b6\u6001\n                relayState.inputs = {};\n                for (let i = 1; i <= inputCount; i++) {\n                    relayState.inputs[i] = false;\n                }\n\n                renderOutputs();\n                renderInputs();\n                addLog('\u7cfb\u7edf', `IO\u914d\u7f6e\u5df2\u66f4\u65b0\uff1a\u8f93\u51fa=${outputCount}\uff0c\u8f93\u5165=${inputCount}`, 'info');\n            }\n\n            \/\/ \u6e32\u67d3\u8f93\u51fa\u70b9\uff08\u7ee7\u7535\u5668\uff09\n            function renderOutputs() {\n                const $grid = $('#relay-outputs-grid');\n                $grid.empty();\n\n                for (let i = 1; i <= relayState.outputCount; i++) {\n                    const state = relayState.outputs[i];\n                    const statusClass = state ? 'relay-on' : 'relay-off';\n                    const statusText = state ? 'ON' : 'OFF';\n\n                    const $relay = $(`\n                        <div class=\"relay-output-item ${statusClass}\" data-relay=\"${i}\">\n                            <div class=\"relay-indicator\"><\/div>\n                            <div class=\"relay-label\">\u7ee7\u7535\u5668 ${i}<\/div>\n                            <div class=\"relay-status\">${statusText}<\/div>\n                            <div class=\"relay-actions\">\n                                <button class=\"relay-btn-icon relay-btn-on\" data-relay=\"${i}\" data-action=\"on\" title=\"\u5f00\u542f\">\n                                    <i class=\"dashicons dashicons-yes\"><\/i>\n                                <\/button>\n                                <button class=\"relay-btn-icon relay-btn-off\" data-relay=\"${i}\" data-action=\"off\" title=\"\u5173\u95ed\">\n                                    <i class=\"dashicons dashicons-no\"><\/i>\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                    `);\n                    $grid.append($relay);\n                }\n\n                \/\/ \u7ed1\u5b9a\u70b9\u51fb\u4e8b\u4ef6\n                $('.relay-output-item .relay-indicator').on('click', function() {\n                    const relayNum = $(this).parent().data('relay');\n                    toggleRelay(relayNum);\n                });\n\n                $('.relay-btn-icon').on('click', function(e) {\n                    e.stopPropagation();\n                    const relayNum = $(this).data('relay');\n                    const action = $(this).data('action');\n                    controlRelay(relayNum, action);\n                });\n            }\n\n            \/\/ \u6e32\u67d3\u8f93\u5165\u70b9\n            function renderInputs() {\n                const $grid = $('#relay-inputs-grid');\n                $grid.empty();\n\n                for (let i = 1; i <= relayState.inputCount; i++) {\n                    const state = relayState.inputs[i];\n                    const statusClass = state ? 'input-active' : 'input-inactive';\n                    const statusText = state ? '\u6709\u6548' : '\u65e0\u6548';\n\n                    const $input = $(`\n                        <div class=\"relay-input-item ${statusClass}\">\n                            <div class=\"input-indicator\"><\/div>\n                            <div class=\"input-label\">\u8f93\u5165 ${i}<\/div>\n                            <div class=\"input-status\">${statusText}<\/div>\n                        <\/div>\n                    `);\n                    $grid.append($input);\n                }\n            }\n\n            \/\/ \u66f4\u65b0\u7edf\u8ba1\u4fe1\u606f\n            function updateStats() {\n                $('#relay-tx-frames').text(relayState.txFrames);\n                $('#relay-tx-bytes').text(relayState.txBytes);\n                $('#relay-rx-frames').text(relayState.rxFrames);\n                $('#relay-rx-bytes').text(relayState.rxBytes);\n                $('#relay-errors').text(relayState.errors);\n            }\n\n            \/\/ \u6dfb\u52a0\u65e5\u5fd7\n            function addLog(type, message, level = 'info') {\n                const $output = $('#relay-log-output');\n                const time = new Date().toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });\n                const $entry = $(`\n                    <div class=\"relay-log-entry relay-log-${level}\">\n                        <span class=\"relay-log-time\">[${time}]<\/span>\n                        <span class=\"relay-log-type\">${type}:<\/span>\n                        <span class=\"relay-log-msg\">${message}<\/span>\n                    <\/div>\n                `);\n                $output.append($entry);\n\n                \/\/ \u81ea\u52a8\u6eda\u52a8\n                if ($('#relay-auto-scroll').is(':checked')) {\n                    $output.scrollTop($output[0].scrollHeight);\n                }\n            }\n\n            \/\/ \u63a7\u5236\u7ee7\u7535\u5668\n            function controlRelay(relayNum, action) {\n                if (!relayState.isConnected) {\n                    addLog('\u9519\u8bef', '\u8bf7\u5148\u8fde\u63a5\u4e32\u53e3', 'error');\n                    return;\n                }\n\n                let newState;\n                if (action === 'on') {\n                    newState = true;\n                } else if (action === 'off') {\n                    newState = false;\n                } else if (action === 'toggle') {\n                    newState = !relayState.outputs[relayNum];\n                }\n\n                \/\/ \u751f\u6210Modbus\u547d\u4ee4\uff08\u529f\u80fd\u780105\uff1a\u5199\u5355\u4e2a\u7ebf\u5708\uff09\n                const command = generateModbusCommand(relayNum, newState);\n                sendCommand(command);\n\n                \/\/ \u66f4\u65b0\u72b6\u6001\n                relayState.outputs[relayNum] = newState;\n                updateRelayUI(relayNum, newState);\n\n                addLog('\u53d1\u9001', `\u7ee7\u7535\u5668${relayNum} \u2192 ${newState ? 'ON' : 'OFF'} [${command}]`, 'send');\n            }\n\n            \/\/ \u5207\u6362\u7ee7\u7535\u5668\u72b6\u6001\n            function toggleRelay(relayNum) {\n                controlRelay(relayNum, 'toggle');\n            }\n\n            \/\/ \u751f\u6210Modbus\u547d\u4ee4\n            function generateModbusCommand(relayNum, state) {\n                \/\/ \u5047\u8bbe\u4ece\u7ad9\u5730\u5740\u4e3a01\uff0c\u529f\u80fd\u780105\uff08\u5199\u5355\u4e2a\u7ebf\u5708\uff09\n                const slaveId = '01';\n                const funcCode = '05';\n                const address = (relayNum - 1).toString(16).toUpperCase().padStart(4, '0');\n                const value = state ? 'FF00' : '0000';\n\n                \/\/ \u8ba1\u7b97CRC\uff08\u7b80\u5316\u7248\uff0c\u5b9e\u9645\u5e94\u7528\u9700\u8981\u6b63\u786e\u7684CRC\u8ba1\u7b97\uff09\n                const dataStr = slaveId + funcCode + address + value;\n                const crc = calculateCRC(dataStr);\n\n                return `${slaveId} ${funcCode} ${address.match(\/.{2}\/g).join(' ')} ${value.match(\/.{2}\/g).join(' ')} ${crc}`;\n            }\n\n            \/\/ Modbus CRC-16\u8ba1\u7b97\n            function calculateCRC(hexStr) {\n                \/\/ \u79fb\u9664\u7a7a\u683c\u5e76\u8f6c\u6362\u4e3a\u5b57\u8282\u6570\u7ec4\n                const bytes = hexStr.replace(\/\\s+\/g, '').match(\/.{2}\/g).map(h => parseInt(h, 16));\n\n                let crc = 0xFFFF;\n                for (let byte of bytes) {\n                    crc ^= byte;\n                    for (let i = 0; i < 8; i++) {\n                        if (crc & 0x0001) {\n                            crc = (crc >> 1) ^ 0xA001;\n                        } else {\n                            crc >>= 1;\n                        }\n                    }\n                }\n\n                \/\/ \u8fd4\u56de\u4f4e\u5b57\u8282\u5728\u524d\n                const low = (crc & 0xFF).toString(16).toUpperCase().padStart(2, '0');\n                const high = ((crc >> 8) & 0xFF).toString(16).toUpperCase().padStart(2, '0');\n                return `${low} ${high}`;\n            }\n\n            \/\/ \u53d1\u9001\u961f\u5217\uff08\u907f\u514dWritableStream\u9501\u5b9a\u51b2\u7a81\uff09\n            const sendQueue = [];\n            let isSending = false;\n\n            \/\/ \u53d1\u9001\u547d\u4ee4\n            async function sendCommand(command) {\n                if (!relayState.isConnected || !relayState.port) {\n                    addLog('\u9519\u8bef', '\u4e32\u53e3\u672a\u8fde\u63a5\uff0c\u65e0\u6cd5\u53d1\u9001\u547d\u4ee4', 'error');\n                    return;\n                }\n\n                \/\/ \u5c06\u547d\u4ee4\u52a0\u5165\u961f\u5217\n                sendQueue.push(command);\n\n                \/\/ \u5982\u679c\u6ca1\u6709\u6b63\u5728\u53d1\u9001\uff0c\u5f00\u59cb\u5904\u7406\u961f\u5217\n                if (!isSending) {\n                    await processSendQueue();\n                }\n            }\n\n            \/\/ \u5904\u7406\u53d1\u9001\u961f\u5217\n            async function processSendQueue() {\n                if (isSending || sendQueue.length === 0) {\n                    return;\n                }\n\n                isSending = true;\n\n                while (sendQueue.length > 0) {\n                    const command = sendQueue.shift();\n\n                    try {\n                        \/\/ \u5c06\u5341\u516d\u8fdb\u5236\u5b57\u7b26\u4e32\u8f6c\u6362\u4e3a\u5b57\u8282\u6570\u7ec4\n                        const hexArray = command.replace(\/\\s+\/g, '').match(\/.{2}\/g);\n                        if (!hexArray) {\n                            addLog('\u9519\u8bef', '\u547d\u4ee4\u683c\u5f0f\u9519\u8bef', 'error');\n                            continue;\n                        }\n\n                        const bytes = new Uint8Array(hexArray.map(h => parseInt(h, 16)));\n\n                        \/\/ \u4f7f\u7528\u6301\u4e45\u7684writer\uff0c\u907f\u514d\u91cd\u590d\u83b7\u53d6\u9501\n                        if (!relayState.writer) {\n                            relayState.writer = relayState.port.writable.getWriter();\n                        }\n\n                        await relayState.writer.write(bytes);\n\n                        \/\/ \u66f4\u65b0\u7edf\u8ba1\n                        relayState.txFrames++;\n                        relayState.txBytes += bytes.length;\n                        updateStats();\n\n                        addLog('\u53d1\u9001', command, 'send');\n\n                        \/\/ \u53d1\u9001\u95f4\u9694\uff0c\u907f\u514d\u592a\u5feb\n                        await new Promise(resolve => setTimeout(resolve, 50));\n\n                    } catch (error) {\n                        addLog('\u9519\u8bef', `\u53d1\u9001\u547d\u4ee4\u5931\u8d25: ${error.message}`, 'error');\n                        relayState.errors++;\n                        updateStats();\n                        console.error('\u53d1\u9001\u9519\u8bef:', error);\n\n                        \/\/ \u5982\u679cwriter\u51fa\u9519\uff0c\u91cd\u7f6e\u5b83\n                        if (relayState.writer) {\n                            try {\n                                relayState.writer.releaseLock();\n                            } catch (e) {}\n                            relayState.writer = null;\n                        }\n                    }\n                }\n\n                isSending = false;\n            }\n\n            \/\/ \u63a5\u6536\u7f13\u51b2\u533a\n            let receiveBuffer = [];\n            let receiveTimer = null;\n\n            \/\/ \u8bfb\u53d6\u4e32\u53e3\u6570\u636e\n            async function readSerialData() {\n                try {\n                    const reader = relayState.port.readable.getReader();\n                    relayState.reader = reader;\n\n                    while (true) {\n                        const { value, done } = await reader.read();\n                        if (done) {\n                            break;\n                        }\n\n                        \/\/ \u5c06\u63a5\u6536\u7684\u5b57\u8282\u6dfb\u52a0\u5230\u7f13\u51b2\u533a\n                        receiveBuffer.push(...Array.from(value));\n\n                        \/\/ \u66f4\u65b0\u7edf\u8ba1\uff08\u5b57\u8282\u6570\uff09\n                        relayState.rxBytes += value.length;\n                        updateStats();\n\n                        \/\/ \u5c1d\u8bd5\u4ece\u7f13\u51b2\u533a\u63d0\u53d6\u5b8c\u6574\u7684Modbus\u5e27\n                        processReceiveBuffer();\n\n                        \/\/ \u6e05\u9664\u4e4b\u524d\u7684\u5b9a\u65f6\u5668\n                        if (receiveTimer) {\n                            clearTimeout(receiveTimer);\n                        }\n\n                        \/\/ \u8bbe\u7f6e\u5b9a\u65f6\u5668\uff1a50ms\u5185\u6ca1\u6709\u65b0\u6570\u636e\uff0c\u5904\u7406\u5269\u4f59\u6570\u636e\n                        receiveTimer = setTimeout(() => {\n                            if (receiveBuffer.length > 0) {\n                                \/\/ \u5904\u7406\u7f13\u51b2\u533a\u4e2d\u5269\u4f59\u7684\u6570\u636e\n                                processReceiveBuffer(true);\n                            }\n                        }, 50);\n                    }\n                } catch (error) {\n                    if (error.name !== 'NetworkError') {\n                        addLog('\u9519\u8bef', `\u8bfb\u53d6\u6570\u636e\u5931\u8d25: ${error.message}`, 'error');\n                        console.error('\u8bfb\u53d6\u9519\u8bef:', error);\n                    }\n                } finally {\n                    if (relayState.reader) {\n                        relayState.reader.releaseLock();\n                        relayState.reader = null;\n                    }\n                    \/\/ \u6e05\u9664\u5b9a\u65f6\u5668\n                    if (receiveTimer) {\n                        clearTimeout(receiveTimer);\n                    }\n                }\n            }\n\n            \/\/ \u5904\u7406\u63a5\u6536\u7f13\u51b2\u533a\uff0c\u63d0\u53d6\u5b8c\u6574\u7684Modbus\u5e27\n            function processReceiveBuffer(forceFlush = false) {\n                while (receiveBuffer.length > 0) {\n                    \/\/ Modbus RTU \u6700\u5c0f\u5e27\u957f\u5ea6\uff1a\u4ece\u7ad9\u5730\u5740(1) + \u529f\u80fd\u7801(1) + CRC(2) = 4\u5b57\u8282\n                    if (receiveBuffer.length < 4 && !forceFlush) {\n                        break; \/\/ \u6570\u636e\u4e0d\u8db3\uff0c\u7b49\u5f85\u66f4\u591a\u6570\u636e\n                    }\n\n                    \/\/ \u5c1d\u8bd5\u8bc6\u522bModbus\u5e27\u7684\u957f\u5ea6\n                    const frameLength = getModbusFrameLength(receiveBuffer);\n\n                    if (frameLength === -1) {\n                        \/\/ \u65e0\u6cd5\u8bc6\u522b\u5e27\u957f\u5ea6\n                        if (forceFlush) {\n                            \/\/ \u5f3a\u5236\u5237\u65b0\uff0c\u663e\u793a\u6240\u6709\u6570\u636e\n                            const hexData = receiveBuffer\n                                .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                                .join(' ');\n                            relayState.rxFrames++;\n                            updateStats();\n                            addLog('\u63a5\u6536', hexData, 'success');\n                            receiveBuffer = [];\n                        }\n                        break;\n                    }\n\n                    if (receiveBuffer.length < frameLength) {\n                        if (forceFlush) {\n                            \/\/ \u6570\u636e\u4e0d\u5b8c\u6574\u4f46\u5f3a\u5236\u5237\u65b0\n                            const hexData = receiveBuffer\n                                .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                                .join(' ');\n                            relayState.rxFrames++;\n                            updateStats();\n                            addLog('\u63a5\u6536', hexData + ' [\u4e0d\u5b8c\u6574]', 'success');\n                            receiveBuffer = [];\n                        }\n                        break; \/\/ \u7b49\u5f85\u66f4\u591a\u6570\u636e\n                    }\n\n                    \/\/ \u63d0\u53d6\u5b8c\u6574\u7684\u5e27\n                    const frame = receiveBuffer.slice(0, frameLength);\n                    receiveBuffer = receiveBuffer.slice(frameLength);\n\n                    \/\/ \u663e\u793a\u5e27\n                    const hexData = frame\n                        .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                        .join(' ');\n\n                    relayState.rxFrames++;\n                    updateStats();\n                    addLog('\u63a5\u6536', hexData, 'success');\n\n                    \/\/ \u89e3\u6790Modbus\u54cd\u5e94\n                    parseModbusResponse(frame);\n                }\n            }\n\n            \/\/ \u83b7\u53d6Modbus\u5e27\u7684\u957f\u5ea6\n            function getModbusFrameLength(buffer) {\n                if (buffer.length < 2) {\n                    return -1;\n                }\n\n                const funcCode = buffer[1];\n\n                \/\/ \u68c0\u67e5\u662f\u5426\u662f\u9519\u8bef\u54cd\u5e94\uff08\u529f\u80fd\u7801\u6700\u9ad8\u4f4d\u4e3a1\uff09\n                if ((funcCode & 0x80) !== 0) {\n                    return 5; \/\/ \u9519\u8bef\u54cd\u5e94\uff1a\u5730\u5740(1) + \u529f\u80fd\u7801(1) + \u9519\u8bef\u7801(1) + CRC(2)\n                }\n\n                \/\/ \u6839\u636e\u529f\u80fd\u7801\u5224\u65ad\u5e27\u957f\u5ea6\n                switch (funcCode) {\n                    case 0x05: \/\/ \u5199\u5355\u4e2a\u7ebf\u5708\n                    case 0x06: \/\/ \u5199\u5355\u4e2a\u5bc4\u5b58\u5668\n                        return 8; \/\/ \u5730\u5740(1) + \u529f\u80fd\u7801(1) + \u5730\u5740(2) + \u6570\u636e(2) + CRC(2)\n\n                    case 0x0F: \/\/ \u5199\u591a\u4e2a\u7ebf\u5708\n                    case 0x10: \/\/ \u5199\u591a\u4e2a\u5bc4\u5b58\u5668\n                        return 8; \/\/ \u5730\u5740(1) + \u529f\u80fd\u7801(1) + \u8d77\u59cb\u5730\u5740(2) + \u6570\u91cf(2) + CRC(2)\n\n                    case 0x01: \/\/ \u8bfb\u7ebf\u5708\n                    case 0x02: \/\/ \u8bfb\u79bb\u6563\u8f93\u5165\n                    case 0x03: \/\/ \u8bfb\u4fdd\u6301\u5bc4\u5b58\u5668\n                    case 0x04: \/\/ \u8bfb\u8f93\u5165\u5bc4\u5b58\u5668\n                        if (buffer.length < 3) {\n                            return -1;\n                        }\n                        const byteCount = buffer[2];\n                        return 5 + byteCount; \/\/ \u5730\u5740(1) + \u529f\u80fd\u7801(1) + \u5b57\u8282\u6570(1) + \u6570\u636e(N) + CRC(2)\n\n                    default:\n                        return -1; \/\/ \u672a\u77e5\u529f\u80fd\u7801\n                }\n            }\n\n            \/\/ \u89e3\u6790Modbus\u54cd\u5e94\n            function parseModbusResponse(bytes) {\n                if (bytes.length < 5) {\n                    return; \/\/ \u6570\u636e\u592a\u77ed\uff0c\u4e0d\u662f\u6709\u6548\u7684Modbus\u54cd\u5e94\n                }\n\n                const slaveId = bytes[0];\n                const funcCode = bytes[1];\n\n                \/\/ \u68c0\u67e5\u529f\u80fd\u7801\u5e76\u89e3\u6790\u54cd\u5e94\n                if (funcCode === 0x01) {\n                    \/\/ \u529f\u80fd\u780101\uff1a\u8bfb\u7ebf\u5708\u72b6\u6001\u7684\u54cd\u5e94\uff08\u8f93\u51fa\u72b6\u6001\uff09\n                    if (bytes.length >= 5) {\n                        const byteCount = bytes[2];\n                        if (bytes.length >= 3 + byteCount + 2) {\n                            \/\/ \u89e3\u6790\u7ebf\u5708\u72b6\u6001\u4f4d\uff08\u6ce8\u610f\uff1a\u7ee7\u7535\u5668\u6a21\u5757\u901a\u5e38\u4f7f\u7528\u5012\u5e8f\uff0cbit7\u5bf9\u5e94\u7ebf\u57081\uff09\n                            for (let byteIdx = 0; byteIdx < byteCount; byteIdx++) {\n                                const dataByte = bytes[3 + byteIdx];\n                                for (let bitIdx = 0; bitIdx < 8; bitIdx++) {\n                                    \/\/ \u4f7f\u7528\u5012\u5e8f\uff1abit7\u2192\u7ebf\u57081, bit6\u2192\u7ebf\u57082, ..., bit0\u2192\u7ebf\u57088\n                                    const coilNum = byteIdx * 8 + (7 - bitIdx) + 1;\n                                    if (coilNum <= relayState.outputCount) {\n                                        const state = (dataByte & (1 << bitIdx)) !== 0;\n                                        relayState.outputs[coilNum] = state;\n                                        updateRelayUI(coilNum, state);\n                                    }\n                                }\n                            }\n                            addLog('\u63a5\u6536', `\u8f93\u51fa\u72b6\u6001\u5df2\u66f4\u65b0 (${relayState.outputCount}\u4e2a)`, 'success');\n                        }\n                    }\n                } else if (funcCode === 0x02) {\n                    \/\/ \u529f\u80fd\u780102\uff1a\u8bfb\u79bb\u6563\u8f93\u5165\u7684\u54cd\u5e94\uff08\u8f93\u5165\u72b6\u6001\uff09\n                    if (bytes.length >= 5) {\n                        const byteCount = bytes[2];\n                        if (bytes.length >= 3 + byteCount + 2) {\n                            \/\/ \u89e3\u6790\u8f93\u5165\u72b6\u6001\u4f4d\uff08\u4f7f\u7528\u5012\u5e8f\uff09\n                            for (let byteIdx = 0; byteIdx < byteCount; byteIdx++) {\n                                const dataByte = bytes[3 + byteIdx];\n                                for (let bitIdx = 0; bitIdx < 8; bitIdx++) {\n                                    \/\/ \u4f7f\u7528\u5012\u5e8f\uff1abit7\u2192\u8f93\u51651, bit6\u2192\u8f93\u51652, ..., bit0\u2192\u8f93\u51658\n                                    const inputNum = byteIdx * 8 + (7 - bitIdx) + 1;\n                                    if (inputNum <= relayState.inputCount) {\n                                        const state = (dataByte & (1 << bitIdx)) !== 0;\n                                        relayState.inputs[inputNum] = state;\n                                    }\n                                }\n                            }\n                            renderInputs();\n                            addLog('\u63a5\u6536', `\u8f93\u5165\u72b6\u6001\u5df2\u66f4\u65b0 (${relayState.inputCount}\u4e2a)`, 'success');\n                        }\n                    }\n                } else if (funcCode === 0x05) {\n                    \/\/ \u529f\u80fd\u780105\uff1a\u5199\u5355\u4e2a\u7ebf\u5708\u7684\u54cd\u5e94\n                    if (bytes.length >= 8) {\n                        const address = (bytes[2] << 8) | bytes[3];\n                        const value = (bytes[4] << 8) | bytes[5];\n                        const relayNum = address + 1;\n                        const state = value === 0xFF00;\n\n                        \/\/ \u66f4\u65b0\u7ee7\u7535\u5668UI\u72b6\u6001\n                        if (relayNum >= 1 && relayNum <= relayState.outputCount) {\n                            relayState.outputs[relayNum] = state;\n                            updateRelayUI(relayNum, state);\n                        }\n                    }\n                } else if (funcCode === 0x0F) {\n                    \/\/ \u529f\u80fd\u780115\uff1a\u5199\u591a\u4e2a\u7ebf\u5708\u7684\u54cd\u5e94\n                    if (bytes.length >= 8) {\n                        const startAddress = (bytes[2] << 8) | bytes[3];\n                        const quantity = (bytes[4] << 8) | bytes[5];\n                        addLog('\u63a5\u6536', `\u6279\u91cf\u5199\u5165\u6210\u529f (\u8d77\u59cb=${startAddress}, \u6570\u91cf=${quantity})`, 'success');\n                    }\n                } else if ((funcCode & 0x80) !== 0) {\n                    \/\/ \u9519\u8bef\u54cd\u5e94\uff08\u529f\u80fd\u7801\u6700\u9ad8\u4f4d\u4e3a1\uff09\n                    const errorCode = bytes[2];\n                    const errorMsg = getModbusErrorMessage(errorCode);\n                    addLog('\u9519\u8bef', `Modbus\u9519\u8bef: ${errorMsg} (\u4ee3\u7801: ${errorCode})`, 'error');\n                    relayState.errors++;\n                    updateStats();\n                }\n            }\n\n            \/\/ \u83b7\u53d6Modbus\u9519\u8bef\u6d88\u606f\n            function getModbusErrorMessage(errorCode) {\n                const errors = {\n                    0x01: '\u975e\u6cd5\u529f\u80fd',\n                    0x02: '\u975e\u6cd5\u6570\u636e\u5730\u5740',\n                    0x03: '\u975e\u6cd5\u6570\u636e\u503c',\n                    0x04: '\u4ece\u7ad9\u8bbe\u5907\u6545\u969c',\n                    0x05: '\u786e\u8ba4',\n                    0x06: '\u4ece\u7ad9\u8bbe\u5907\u5fd9',\n                    0x08: '\u5b58\u50a8\u5668\u6821\u9a8c\u9519\u8bef'\n                };\n                return errors[errorCode] || '\u672a\u77e5\u9519\u8bef';\n            }\n\n            \/\/ \u66f4\u65b0\u7ee7\u7535\u5668UI\n            function updateRelayUI(relayNum, state) {\n                const $item = $(`.relay-output-item[data-relay=\"${relayNum}\"]`);\n                if (state) {\n                    $item.removeClass('relay-off').addClass('relay-on');\n                    $item.find('.relay-status').text('ON');\n                } else {\n                    $item.removeClass('relay-on').addClass('relay-off');\n                    $item.find('.relay-status').text('OFF');\n                }\n            }\n\n            \/\/ \u8bf7\u6c42\u4e32\u53e3\u6388\u6743\uff08\u53c2\u8003\u4e32\u53e3\u8c03\u8bd5\u5b9e\u73b0\uff09\n            async function requestRelaySerialPort() {\n                if (!('serial' in navigator)) {\n                    addLog('\u9519\u8bef', '\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301Web Serial API', 'error');\n                    return null;\n                }\n\n                try {\n                    addLog('\u7cfb\u7edf', '\u8bf7\u5728\u5f39\u51fa\u7a97\u53e3\u4e2d\u9009\u62e9\u4e32\u53e3\u8bbe\u5907...', 'info');\n                    const port = await navigator.serial.requestPort();\n                    addLog('\u7cfb\u7edf', '\u4e32\u53e3\u8bbe\u5907\u5df2\u83b7\u53d6\u6388\u6743', 'success');\n                    return port;\n                } catch (error) {\n                    if (error.name !== 'NotFoundError') {\n                        addLog('\u9519\u8bef', `\u4e32\u53e3\u6388\u6743\u5931\u8d25: ${error.message}`, 'error');\n                    }\n                    return null;\n                }\n            }\n\n            \/\/ \u6253\u5f00\u4e32\u53e3\n            async function openRelayPort() {\n                try {\n                    \/\/ \u83b7\u53d6\u9009\u4e2d\u7684\u4e32\u53e3\u7d22\u5f15\n                    const portIndex = $('#relay-port-select').val();\n\n                    \/\/ \u5982\u679c\u6ca1\u6709\u9009\u62e9\u4e32\u53e3\uff0c\u8bf7\u6c42\u6388\u6743\n                    if (!portIndex || portIndex === '') {\n                        const newPort = await requestRelaySerialPort();\n                        if (!newPort) return;\n\n                        relayState.port = newPort;\n                        \/\/ \u91cd\u65b0\u52a0\u8f7d\u4e32\u53e3\u5217\u8868\n                        await loadSerialPorts();\n\n                        \/\/ \u81ea\u52a8\u9009\u4e2d\u521a\u6388\u6743\u7684\u4e32\u53e3\n                        const ports = await navigator.serial.getPorts();\n                        const portIdx = ports.findIndex(p => p === newPort);\n                        if (portIdx >= 0) {\n                            $('#relay-port-select').val(portIdx.toString());\n                        }\n                    } else {\n                        \/\/ \u4f7f\u7528\u5df2\u9009\u62e9\u7684\u4e32\u53e3\n                        relayState.port = $('#relay-port-select option:selected').data('port');\n                    }\n\n                    if (!relayState.port) {\n                        addLog('\u9519\u8bef', '\u672a\u9009\u62e9\u4e32\u53e3\u8bbe\u5907', 'error');\n                        return;\n                    }\n\n                    \/\/ \u83b7\u53d6\u4e32\u53e3\u53c2\u6570\n                    const baudRate = parseInt($('#relay-baudrate').val());\n                    const dataBits = parseInt($('#relay-databits').val());\n                    const stopBits = parseInt($('#relay-stopbits').val());\n                    const parity = $('#relay-parity').val();\n\n                    \/\/ \u6253\u5f00\u4e32\u53e3\n                    await relayState.port.open({\n                        baudRate: baudRate,\n                        dataBits: dataBits,\n                        stopBits: stopBits,\n                        parity: parity\n                    });\n\n                    relayState.isConnected = true;\n\n                    \/\/ \u66f4\u65b0UI\u72b6\u6001\n                    $('#relay-status-indicator').removeClass('disconnected').addClass('connected');\n                    $('#relay-status-text').text('\u5df2\u8fde\u63a5');\n                    $('#relay-connect-btn').html('<i class=\"dashicons dashicons-no\"><\/i> \u65ad\u5f00\u8fde\u63a5')\n                                          .removeClass('relay-btn-primary').addClass('relay-btn-danger');\n                    $('.relay-port-config select').prop('disabled', true);\n\n                    addLog('\u7cfb\u7edf', `\u4e32\u53e3\u5df2\u8fde\u63a5: \u6ce2\u7279\u7387 ${baudRate} bps, \u6570\u636e\u4f4d ${dataBits}, \u505c\u6b62\u4f4d ${stopBits}, \u6821\u9a8c ${parity}`, 'success');\n\n                    \/\/ \u5f00\u59cb\u8bfb\u53d6\u6570\u636e\n                    readRelayData();\n\n                } catch (error) {\n                    addLog('\u9519\u8bef', `\u8fde\u63a5\u4e32\u53e3\u5931\u8d25: ${error.message}`, 'error');\n                    console.error('\u4e32\u53e3\u8fde\u63a5\u9519\u8bef:', error);\n                }\n            }\n\n            \/\/ \u5173\u95ed\u4e32\u53e3\n            async function closeRelayPort() {\n                if (!relayState.port || !relayState.isConnected) return;\n\n                try {\n                    \/\/ \u91ca\u653ewriter\u9501\n                    if (relayState.writer) {\n                        try {\n                            await relayState.writer.releaseLock();\n                        } catch (e) {\n                            console.error('\u91ca\u653ewriter\u9501\u5931\u8d25:', e);\n                        }\n                        relayState.writer = null;\n                    }\n\n                    \/\/ \u53d6\u6d88reader\n                    if (relayState.reader) {\n                        try {\n                            await relayState.reader.cancel();\n                        } catch (e) {\n                            console.error('\u53d6\u6d88reader\u5931\u8d25:', e);\n                        }\n                        relayState.reader = null;\n                    }\n\n                    \/\/ \u5173\u95ed\u4e32\u53e3\n                    await relayState.port.close();\n                    relayState.isConnected = false;\n\n                    \/\/ \u66f4\u65b0UI\u72b6\u6001\n                    $('#relay-status-indicator').removeClass('connected').addClass('disconnected');\n                    $('#relay-status-text').text('\u672a\u8fde\u63a5');\n                    $('#relay-connect-btn').html('<i class=\"dashicons dashicons-admin-plugins\"><\/i> \u8fde\u63a5\u4e32\u53e3')\n                                          .removeClass('relay-btn-danger').addClass('relay-btn-primary');\n                    $('.relay-port-config select').prop('disabled', false);\n\n                    addLog('\u7cfb\u7edf', '\u4e32\u53e3\u5df2\u65ad\u5f00', 'info');\n                } catch (error) {\n                    addLog('\u9519\u8bef', `\u65ad\u5f00\u4e32\u53e3\u5931\u8d25: ${error.message}`, 'error');\n                    console.error('\u65ad\u5f00\u4e32\u53e3\u9519\u8bef:', error);\n                }\n            }\n\n            \/\/ \u63a5\u6536\u7f13\u51b2\u533a\n            let relayReceiveBuffer = [];\n            let relayReceiveTimer = null;\n\n            \/\/ \u8bfb\u53d6\u4e32\u53e3\u6570\u636e\n            async function readRelayData() {\n                try {\n                    const reader = relayState.port.readable.getReader();\n                    relayState.reader = reader;\n\n                    while (true) {\n                        const { value, done } = await reader.read();\n                        if (done) {\n                            break;\n                        }\n\n                        \/\/ \u5c06\u63a5\u6536\u7684\u5b57\u8282\u6dfb\u52a0\u5230\u7f13\u51b2\u533a\n                        relayReceiveBuffer.push(...Array.from(value));\n\n                        \/\/ \u66f4\u65b0\u7edf\u8ba1\uff08\u5b57\u8282\u6570\uff09\n                        relayState.rxBytes += value.length;\n                        updateStats();\n\n                        \/\/ \u5c1d\u8bd5\u4ece\u7f13\u51b2\u533a\u63d0\u53d6\u5b8c\u6574\u7684Modbus\u5e27\n                        processRelayReceiveBuffer();\n\n                        \/\/ \u6e05\u9664\u4e4b\u524d\u7684\u5b9a\u65f6\u5668\n                        if (relayReceiveTimer) {\n                            clearTimeout(relayReceiveTimer);\n                        }\n\n                        \/\/ \u8bbe\u7f6e\u5b9a\u65f6\u5668\uff1a50ms\u5185\u6ca1\u6709\u65b0\u6570\u636e\uff0c\u5904\u7406\u5269\u4f59\u6570\u636e\n                        relayReceiveTimer = setTimeout(() => {\n                            if (relayReceiveBuffer.length > 0) {\n                                \/\/ \u5904\u7406\u7f13\u51b2\u533a\u4e2d\u5269\u4f59\u7684\u6570\u636e\n                                processRelayReceiveBuffer(true);\n                            }\n                        }, 50);\n                    }\n                } catch (error) {\n                    if (error.name !== 'NetworkError') {\n                        addLog('\u9519\u8bef', `\u8bfb\u53d6\u6570\u636e\u5931\u8d25: ${error.message}`, 'error');\n                        console.error('\u8bfb\u53d6\u9519\u8bef:', error);\n                    }\n                } finally {\n                    if (relayState.reader) {\n                        relayState.reader.releaseLock();\n                        relayState.reader = null;\n                    }\n                    \/\/ \u6e05\u9664\u5b9a\u65f6\u5668\n                    if (relayReceiveTimer) {\n                        clearTimeout(relayReceiveTimer);\n                    }\n                }\n            }\n\n            \/\/ \u5904\u7406\u63a5\u6536\u7f13\u51b2\u533a\uff0c\u63d0\u53d6\u5b8c\u6574\u7684Modbus\u5e27\n            function processRelayReceiveBuffer(forceFlush = false) {\n                while (relayReceiveBuffer.length > 0) {\n                    \/\/ Modbus RTU \u6700\u5c0f\u5e27\u957f\u5ea6\uff1a\u4ece\u7ad9\u5730\u5740(1) + \u529f\u80fd\u7801(1) + CRC(2) = 4\u5b57\u8282\n                    if (relayReceiveBuffer.length < 4 && !forceFlush) {\n                        break; \/\/ \u6570\u636e\u4e0d\u8db3\uff0c\u7b49\u5f85\u66f4\u591a\u6570\u636e\n                    }\n\n                    \/\/ \u5c1d\u8bd5\u8bc6\u522bModbus\u5e27\u7684\u957f\u5ea6\n                    const frameLength = getModbusFrameLength(relayReceiveBuffer);\n\n                    if (frameLength === -1) {\n                        \/\/ \u65e0\u6cd5\u8bc6\u522b\u5e27\u957f\u5ea6\n                        if (forceFlush) {\n                            \/\/ \u5f3a\u5236\u5237\u65b0\uff0c\u663e\u793a\u6240\u6709\u6570\u636e\n                            const hexData = relayReceiveBuffer\n                                .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                                .join(' ');\n                            relayState.rxFrames++;\n                            updateStats();\n                            addLog('\u63a5\u6536', hexData, 'success');\n                            relayReceiveBuffer = [];\n                        }\n                        break;\n                    }\n\n                    if (relayReceiveBuffer.length < frameLength) {\n                        if (forceFlush) {\n                            \/\/ \u6570\u636e\u4e0d\u5b8c\u6574\u4f46\u5f3a\u5236\u5237\u65b0\n                            const hexData = relayReceiveBuffer\n                                .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                                .join(' ');\n                            relayState.rxFrames++;\n                            updateStats();\n                            addLog('\u63a5\u6536', hexData + ' [\u4e0d\u5b8c\u6574]', 'success');\n                            relayReceiveBuffer = [];\n                        }\n                        break; \/\/ \u7b49\u5f85\u66f4\u591a\u6570\u636e\n                    }\n\n                    \/\/ \u63d0\u53d6\u5b8c\u6574\u7684\u5e27\n                    const frame = relayReceiveBuffer.slice(0, frameLength);\n                    relayReceiveBuffer = relayReceiveBuffer.slice(frameLength);\n\n                    \/\/ \u663e\u793a\u5e27\n                    const hexData = frame\n                        .map(b => b.toString(16).toUpperCase().padStart(2, '0'))\n                        .join(' ');\n\n                    relayState.rxFrames++;\n                    updateStats();\n                    addLog('\u63a5\u6536', hexData, 'success');\n\n                    \/\/ \u89e3\u6790Modbus\u54cd\u5e94\n                    parseModbusResponse(frame);\n                }\n            }\n\n            \/\/ \u5176\u4ed6\u6309\u94ae\u4e8b\u4ef6\n            $('#relay-reset-stats').on('click', function() {\n                relayState.txFrames = 0;\n                relayState.txBytes = 0;\n                relayState.rxFrames = 0;\n                relayState.rxBytes = 0;\n                relayState.errors = 0;\n                updateStats();\n                addLog('\u7cfb\u7edf', '\u7edf\u8ba1\u4fe1\u606f\u5df2\u91cd\u7f6e', 'info');\n            });\n\n            $('#relay-apply-config').on('click', function() {\n                initIO();\n            });\n\n            $('#relay-clear-log').on('click', function() {\n                $('#relay-log-output').empty();\n                addLog('\u7cfb\u7edf', '\u65e5\u5fd7\u5df2\u6e05\u7a7a', 'info');\n            });\n\n            $('#relay-template-send').on('click', function() {\n                const template = $('#relay-template-select').val();\n                const customCmd = $('#relay-custom-cmd').val().trim();\n\n                if (customCmd) {\n                    sendCommand(customCmd);\n                    addLog('\u53d1\u9001', `\u81ea\u5b9a\u4e49\u547d\u4ee4: ${customCmd}`, 'send');\n                } else if (template) {\n                    addLog('\u7cfb\u7edf', `\u6267\u884c\u6a21\u677f: ${template}`, 'info');\n                } else {\n                    addLog('\u9519\u8bef', '\u8bf7\u9009\u62e9\u6a21\u677f\u6216\u8f93\u5165\u81ea\u5b9a\u4e49\u547d\u4ee4', 'error');\n                }\n            });\n\n            \/\/ \u5237\u65b0\u4e32\u53e3\u5217\u8868\u6309\u94ae\n            $('#relay-refresh-ports').on('click', async function() {\n                if (!('serial' in navigator)) {\n                    addLog('\u9519\u8bef', '\u6d4f\u89c8\u5668\u4e0d\u652f\u6301 Web Serial API', 'error');\n                    return;\n                }\n\n                addLog('\u7cfb\u7edf', '\u6b63\u5728\u5237\u65b0\u4e32\u53e3\u5217\u8868...', 'info');\n\n                try {\n                    \/\/ \u8bf7\u6c42\u7528\u6237\u9009\u62e9\u65b0\u4e32\u53e3\uff08\u4f1a\u89e6\u53d1\u6388\u6743\uff09\n                    await navigator.serial.requestPort();\n                    \/\/ \u91cd\u65b0\u52a0\u8f7d\u4e32\u53e3\u5217\u8868\n                    await loadSerialPorts();\n                    addLog('\u7cfb\u7edf', '\u4e32\u53e3\u5217\u8868\u5df2\u66f4\u65b0', 'success');\n                } catch (error) {\n                    if (error.name === 'NotFoundError') {\n                        addLog('\u7cfb\u7edf', '\u7528\u6237\u53d6\u6d88\u9009\u62e9\u4e32\u53e3', 'info');\n                    } else {\n                        addLog('\u9519\u8bef', `\u5237\u65b0\u4e32\u53e3\u5217\u8868\u5931\u8d25: ${error.message}`, 'error');\n                    }\n                }\n            });\n\n            \/\/ \u521d\u59cb\u5316\n            loadSerialPorts();\n            initIO();\n\n            \/\/ \u5ef6\u8fdf\u52a0\u8f7d\u4e32\u53e3\u5217\u8868\uff08\u7b49\u5f85\u9875\u9762\u5b8c\u5168\u52a0\u8f7d\uff09\n            setTimeout(function() {\n                if ('serial' in navigator) {\n                    loadSerialPorts();\n                }\n            }, 500);\n\n            addLog('\u7cfb\u7edf', '\u7ee7\u7535\u5668\u63a7\u5236\u6a21\u5757\u521d\u59cb\u5316\u5b8c\u6210', 'success');\n        });\n        <\/script>\n                            <\/div>\r\n                            <\/div>\r\n        <\/div>\r\n        \n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n<span id=\"magicpostMarker\"><\/span>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":"","_members_access_role":[],"_members_access_error":""},"class_list":["post-35741","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/pages\/35741","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/comments?post=35741"}],"version-history":[{"count":0,"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/pages\/35741\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.modbus.cn\/en\/wp-json\/wp\/v2\/media?parent=35741"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}