{"id":112347,"date":"2026-10-03T09:08:49","date_gmt":"2026-10-03T01:08:49","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/112347.html"},"modified":"2026-10-03T09:08:49","modified_gmt":"2026-10-03T01:08:49","slug":"mqtt%e6%99%ba%e8%83%bd%e6%8f%92%e5%ba%a7%e5%a6%82%e4%bd%95%e6%8e%a5%e5%85%a5home-assistant%ef%bc%8c%e4%bb%8e%e9%9b%b6%e5%bc%80%e5%a7%8b%e5%ae%8c%e6%95%b4%e5%b7%a5%e7%a8%8b%e5%ae%9e%e7%8e%b0%ef%bc%88ja","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/112347.html","title":{"rendered":"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09"},"content":{"rendered":"<h2>GemeOpen GSPM1B \u00d7 Home Assistant \u00d7 Java(Spring Boot) &#043; Angular Demo<\/h2>\n<p>\u628a GemeOpen GSPM1B \u667a\u80fd\u8f6c\u6362\u5668\u63d2\u5ea7 \u63a5\u5165 Home Assistant&#xff0c;\u5b9e\u73b0 \u901a\u65ad\u7535\u63a7\u5236 \u4e0e \u7535\u538b \/ \u7535\u6d41 \/ \u529f\u7387 \/ \u7d2f\u8ba1\u7528\u7535\u91cf \u91c7\u96c6&#xff1b;\u5e76\u9644\u4e00\u5957 Java(Spring Boot) &#043; Angular \u7684\u5b8c\u6574\u81ea\u7814 Demo\u3002<\/p>\n<p>\u9762\u5411\u7a0b\u5e8f\u5458\u521d\u5b66\u8005&#xff1a;\u6587\u6863\u4ece\u96f6\u8bb2\u8d77&#xff0c;\u6bcf\u4e00\u6b65\u90fd\u53ef\u76f4\u63a5\u590d\u5236\u6267\u884c\u3002 \u672c\u5de5\u7a0b\u4e0e Python &#043; React \u7248\u4e3a\u59ca\u59b9\u5de5\u7a0b&#xff0c;MQTT \u534f\u8bae\u4e0e\u63a5\u53e3\u5951\u7ea6\u5b8c\u5168\u4e00\u81f4\u3002<\/p>\n<hr \/>\n<h4>\u5f00\u53d1\u8005\u6587\u6863<\/h4>\n<p>https:\/\/www.smart-bird.cn\/doc\/product\/GSPM\/device\/GSPM1B\/command<\/p>\n<h4>\u6e90\u7801\u4e0b\u8f7d\u5730\u5740<\/h4>\n<p>https:\/\/smart-bird-oss.smart-bird.cn\/document\/2026\/09\/28\/1127495749059821.zip<\/p>\n<h3>\u2728 \u80fd\u529b\u4e00\u89c8<\/h3>\n<table>\n<tr>\u80fd\u529bHome Assistant\u81ea\u7814 Demo<\/tr>\n<tbody>\n<tr>\n<td>\u901a\u65ad\u7535\u5f00\u5173<\/td>\n<td align=\"center\">\u2705 switch<\/td>\n<td align=\"center\">\u2705 Web \u5f00\u5173<\/td>\n<\/tr>\n<tr>\n<td>\u5b9e\u65f6\u7535\u538b\/\u7535\u6d41\/\u529f\u7387<\/td>\n<td align=\"center\">\u2705 sensor<\/td>\n<td align=\"center\">\u2705 \u5b9e\u65f6\u5361\u7247<\/td>\n<\/tr>\n<tr>\n<td>\u7d2f\u8ba1\u7528\u7535\u91cf<\/td>\n<td align=\"center\">\u2705 sensor&#xff08;\u80fd\u6e90\u9762\u677f&#xff09;<\/td>\n<td align=\"center\">\u2705 \u5361\u7247<\/td>\n<\/tr>\n<tr>\n<td>\u5386\u53f2\u66f2\u7ebf<\/td>\n<td align=\"center\">\u2705 History graph<\/td>\n<td align=\"center\">\u2705 SVG \u6298\u7ebf<\/td>\n<\/tr>\n<tr>\n<td>\u5b9e\u65f6\u63a8\u9001<\/td>\n<td align=\"center\">\u2014<\/td>\n<td align=\"center\">\u2705 WebSocket<\/td>\n<\/tr>\n<tr>\n<td>\u9700\u8981\u5199\u4ee3\u7801<\/td>\n<td align=\"center\">\u274c \u4ec5 YAML<\/td>\n<td align=\"center\">\u2705 Java &#043; Angular<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>&#x1f3d7; \u67b6\u6784<\/h3>\n<p>GSPM1B \u2500\u2500MQTT\u2500\u2500\u25ba Mosquitto Broker \u25c4\u2500\u2500MQTT\u2500\u2500 Home Assistant (\u8def\u5f84 A, \u96f6\u4ee3\u7801)<br \/>\n                        \u25b2<br \/>\n                        \u2514\u2500\u2500MQTT\u2500\u2500 Java \u540e\u7aef(Spring Boot) \u2500\u2500REST\/WS\u2500\u2500 Angular \u524d\u7aef (\u8def\u5f84 B, \u81ea\u7814 Demo)<\/p>\n<h3>&#x1f9f0; \u6280\u672f\u6808<\/h3>\n<table>\n<tr>\u5c42\u6280\u672f<\/tr>\n<tbody>\n<tr>\n<td>\u8bbe\u5907\u901a\u4fe1<\/td>\n<td>MQTT&#xff08;Eclipse Paho Java Client&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u540e\u7aef<\/td>\n<td>Java 17 \u00b7 Spring Boot 3.2 \u00b7 \u539f\u751f WebSocket \u00b7 Maven<\/td>\n<\/tr>\n<tr>\n<td>\u524d\u7aef<\/td>\n<td>Angular 17&#xff08;standalone&#xff09;\u00b7 RxJS \u00b7 \u539f\u751f SVG \u56fe\u8868<\/td>\n<\/tr>\n<tr>\n<td>\u90e8\u7f72<\/td>\n<td>Docker Compose \u00b7 Nginx \u00b7 Eclipse Mosquitto 2<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>&#x1f4c1; \u76ee\u5f55\u7ed3\u6784<\/h3>\n<p>gemeopen-ha-java-demo\/<br \/>\n\u251c\u2500\u2500 README.md                     # \u672c\u6587\u4ef6<br \/>\n\u251c\u2500\u2500 docker-compose.yml            # \u4e00\u952e\u542f\u52a8 Mosquitto &#043; \u540e\u7aef &#043; \u524d\u7aef<br \/>\n\u251c\u2500\u2500 docs\/                         # \u5168\u90e8\u4e2d\u6587\u6587\u6863<br \/>\n\u2502   \u251c\u2500\u2500 00-architecture.md        # \u67b6\u6784\u4e0e\u63a5\u53e3\u5951\u7ea6&#xff08;\u57fa\u51c6&#xff09;<br \/>\n\u2502   \u251c\u2500\u2500 01-overview.md            # \u65b9\u6848\u603b\u89c8&#xff08;\u5148\u8bfb&#xff09;<br \/>\n\u2502   \u251c\u2500\u2500 02-device-setup.md        # \u8bbe\u5907\u7aef MQTT \u914d\u7f6e<br \/>\n\u2502   \u251c\u2500\u2500 03-homeassistant.md       # Home Assistant \u63a5\u5165<br \/>\n\u2502   \u251c\u2500\u2500 04-backend.md             # Java \u540e\u7aef\u8bf4\u660e<br \/>\n\u2502   \u251c\u2500\u2500 05-frontend.md            # Angular \u524d\u7aef\u8bf4\u660e<br \/>\n\u2502   \u251c\u2500\u2500 06-deploy-ops.md          # \u90e8\u7f72\u4e0e\u8fd0\u7ef4<br \/>\n\u2502   \u2514\u2500\u2500 07-troubleshooting.md     # \u6392\u9519\u624b\u518c<br \/>\n\u251c\u2500\u2500 homeassistant\/                # HA \u914d\u7f6e\u7247\u6bb5<br \/>\n\u2502   \u251c\u2500\u2500 mqtt-gspm1b.yaml          # switch &#043; sensor \u5b9e\u4f53<br \/>\n\u2502   \u2514\u2500\u2500 dashboard.yaml            # Lovelace \u4eea\u8868\u76d8<br \/>\n\u251c\u2500\u2500 backend\/                      # Java Spring Boot \u540e\u7aef<br \/>\n\u2502   \u2514\u2500\u2500 src\/main\/java\/com\/gemeopen\/demo\/<br \/>\n\u2502       \u251c\u2500\u2500 mqtt\/MqttClientService.java     # MQTT \u8fde\u63a5\/\u89e3\u6790\/\u4e0b\u53d1<br \/>\n\u2502       \u251c\u2500\u2500 store\/DeviceStore.java          # \u72b6\u6001\u4e0e\u5386\u53f2<br \/>\n\u2502       \u251c\u2500\u2500 ws\/TelemetryWebSocketHandler.java<br \/>\n\u2502       \u2514\u2500\u2500 web\/DeviceController.java       # REST \u7aef\u70b9<br \/>\n\u251c\u2500\u2500 frontend\/                     # Angular \u524d\u7aef<br \/>\n\u2502   \u2514\u2500\u2500 src\/app\/<br \/>\n\u2502       \u251c\u2500\u2500 services\/{api,telemetry}.service.ts<br \/>\n\u2502       \u2514\u2500\u2500 components\/{switch-control,realtime-metrics,energy-total,history-chart}\/<br \/>\n\u251c\u2500\u2500 scripts\/                      # \u8bbe\u5907\u914d\u7f6e\u811a\u672c<br \/>\n\u2502   \u251c\u2500\u2500 configure_device.py<br \/>\n\u2502   \u2514\u2500\u2500 device_switch.example.json<br \/>\n\u2514\u2500\u2500 mosquitto\/                    # MQTT Broker \u914d\u7f6e<br \/>\n    \u2514\u2500\u2500 mosquitto.conf<\/p>\n<h3>&#x1f680; \u5feb\u901f\u5f00\u59cb<\/h3>\n<p><span class=\"token comment\"># 1) \u542f\u52a8 Broker &#043; \u540e\u7aef &#043; \u524d\u7aef<\/span><br \/>\n<span class=\"token function\">docker<\/span> compose up <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">&#8211;build<\/span><\/p>\n<p><span class=\"token comment\"># 2) \u628a\u8bbe\u5907\u5207\u6362\u5230\u4f60\u7684 Broker&#xff08;\u7f16\u8f91 scripts\/device_switch.json \u540e\u6267\u884c&#xff09;<\/span><br \/>\n<span class=\"token builtin class-name\">cd<\/span> scripts <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">cp<\/span> device_switch.example.json device_switch.json<br \/>\npython3 configure_device.py <span class=\"token parameter variable\">&#8211;config<\/span> device_switch.json<br \/>\n<span class=\"token comment\">#   \u6210\u529f\u540e\u7ed9\u8bbe\u5907\u65ad\u7535\u91cd\u542f<\/span><\/p>\n<p><span class=\"token comment\"># 3) \u5f00\u542f\u8bbe\u5907\u5b9a\u65f6\u4e0a\u62a5&#xff08;\u793a\u4f8b 15 \u79d2&#xff09;<\/span><br \/>\nmosquitto_pub <span class=\"token parameter variable\">-h<\/span> <span class=\"token operator\">&lt;<\/span>\u4f60\u7684IP<span class=\"token operator\">&gt;<\/span> <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-t<\/span> <span class=\"token string\">&#039;gemeopen\/gspm1b\/&lt;MAC&gt;\/command&#039;<\/span> <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-m<\/span> <span class=\"token string\">&#039;{&#034;messageId&#034;:&#034;1&#034;,&#034;timerEnable&#034;:1,&#034;timerInterval&#034;:15,&#034;type&#034;:&#034;setting&#034;}&#039;<\/span><\/p>\n<p><span class=\"token comment\"># 4) \u6253\u5f00\u81ea\u7814 Demo<\/span><br \/>\n<span class=\"token comment\">#    http:\/\/&lt;\u4f60\u7684IP&gt;:8080<\/span><\/p>\n<p><span class=\"token comment\"># 5) \u63a5\u5165 Home Assistant&#xff1a;\u89c1 docs\/03-homeassistant.md<\/span><\/p>\n<h3>&#x1f4d6; \u6587\u6863\u8def\u7ebf&#xff08;\u5efa\u8bae\u987a\u5e8f&#xff09;<\/h3>\n<li>[01 \u00b7 \u65b9\u6848\u603b\u89c8] 01-overview.md<\/li>\n<li>[02 \u00b7 \u8bbe\u5907\u7aef\u914d\u7f6e] 02-device-setup.md<\/li>\n<li>\u6309\u9700\u9009\u62e9&#xff1a;\n<ul>\n<li>Home Assistant \u7528\u6237 \u2192 [03 \u00b7 HA \u63a5\u5165] 03-homeassistant.md<\/li>\n<li>Java \u5f00\u53d1\u8005 \u2192 [04 \u00b7 Java \u540e\u7aef] 04-backend.md\u3001[05 \u00b7 Angular \u524d\u7aef] 05-frontend.md<\/li>\n<\/ul>\n<\/li>\n<li>\u4e0a\u7ebf \u2192 [06 \u00b7 \u90e8\u7f72\u4e0e\u8fd0\u7ef4] 06-deploy-ops.md<\/li>\n<li>\u9047\u95ee\u9898 \u2192 [07 \u00b7 \u6392\u9519\u624b\u518c] 07-troubleshooting.md<\/li>\n<h3>\u26a0\ufe0f \u4e09\u4e2a\u6700\u91cd\u8981\u7684\u63d0\u9192<\/h3>\n<li>\u4e3b\u9898\u8bed\u4e49\u53cd\u76f4\u89c9&#xff1a;\u8bbe\u5907 publish \u4e3b\u9898\u662f\u4f60\u8981\u8ba2\u9605\u7684&#xff1b;\u8bbe\u5907 subcribe \u4e3b\u9898\u662f\u4f60\u8981\u53d1\u5e03\u6307\u4ee4\u7684\u3002<\/li>\n<li>Broker \u5730\u5740\u8bbe\u5907\u8981\u80fd\u8bbf\u95ee&#xff1a;\u8bbe\u5907\u7aef\u586b\u7684\u5fc5\u987b\u662f\u4f60\u670d\u52a1\u5668\u7684\u5c40\u57df\u7f51 IP \/ \u516c\u7f51\u57df\u540d&#xff0c;\u4e0d\u80fd\u662f localhost\u3002<\/li>\n<li>\u5207\u6362 MQTT \u540e\u9700\u91cd\u542f\u8bbe\u5907\u751f\u6548\u3002<\/li>\n<h3>&#x1f527; \u73af\u5883\u8981\u6c42<\/h3>\n<table>\n<tr>\u7ec4\u4ef6\u7248\u672c<\/tr>\n<tbody>\n<tr>\n<td>JDK<\/td>\n<td>17&#043;<\/td>\n<\/tr>\n<tr>\n<td>Maven<\/td>\n<td>3.8&#043;<\/td>\n<\/tr>\n<tr>\n<td>Node \/ npm<\/td>\n<td>18&#043; \/ 20&#043;&#xff08;Angular 17 \u8981\u6c42 Node \u2265 18.13&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>Docker \/ Compose<\/td>\n<td>24&#043;<\/td>\n<\/tr>\n<tr>\n<td>Home Assistant<\/td>\n<td>\u4efb\u610f\u8fd1\u671f\u7248\u672c<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>&#x1f4c4; \u8bf4\u660e<\/h3>\n<ul>\n<li>\u672c\u5de5\u7a0b\u4e3a\u6559\u5b66\u793a\u4f8b&#xff0c;\u751f\u4ea7\u4f7f\u7528\u8bf7\u53c2\u8003 [06 \u00b7 \u90e8\u7f72\u4e0e\u8fd0\u7ef4] 06-deploy-ops.md \u7684\u5b89\u5168\u6e05\u5355\u3002<\/li>\n<li>\u8bbe\u5907\u578b\u53f7\u534f\u8bae\u4ee5 GemeOpen \u5b98\u65b9\u5f00\u53d1\u6587\u6863\u4e3a\u51c6\u3002<\/li>\n<\/ul>\n<h4>00-architecture.md<\/h4>\n<h2>00 \u00b7 \u67b6\u6784\u4e0e\u63a5\u53e3\u5951\u7ea6&#xff08;\u57fa\u51c6\u6587\u6863&#xff09;<\/h2>\n<p>\u672c\u6587\u662f\u6574\u4e2a\u5de5\u7a0b\u7684\u57fa\u51c6\u5951\u7ea6\u3002\u6240\u6709\u5b50\u6a21\u5757&#xff08;Home Assistant \u914d\u7f6e\u3001Python \u540e\u7aef\u3001React \u524d\u7aef&#xff09;\u90fd\u5fc5\u987b\u4e25\u683c\u9075\u5b88\u672c\u6587\u4ef6\u5b9a\u4e49\u7684\u4e3b\u9898\u540d\u3001\u6d88\u606f\u683c\u5f0f\u4e0e API \u5b57\u6bb5\u540d\u3002<\/p>\n<h3>1. \u603b\u4f53\u67b6\u6784<\/h3>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   MQTT    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   MQTT    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502  GSPM1B     \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba \u2502  Mosquitto       \u2502 \u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502  Home Assistant      \u2502<br \/>\n\u2502  \u667a\u80fd\u63d2\u5ea7    \u2502 \u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502  (\u81ea\u5efa Broker)    \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba \u2502  MQTT \u96c6\u6210           \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518           \u2502                  \u2502           \u2502  switch &#043; sensor     \u2502<br \/>\n                          \u2502                  \u2502           \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n                          \u2502                  \u2502   MQTT    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n                          \u2502                  \u2502 \u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502  Python \u540e\u7aef (FastAPI)\u2502<br \/>\n                          \u2502                  \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba \u2502  MQTT \u21c4 REST\/WebSocket\u2502<br \/>\n                          \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518           \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n                                                                    \u2502 HTTP \/ WS<br \/>\n                                                         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n                                                         \u2502  React \u524d\u7aef (Vite)    \u2502<br \/>\n                                                         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<p>\u4e24\u6761\u5e76\u884c\u7684\u6d88\u8d39\u8def\u5f84&#xff08;\u4e92\u4e0d\u5f71\u54cd&#xff09;&#xff1a;<\/p>\n<ul>\n<li>\u8def\u5f84 A&#xff08;\u9762\u5411\u6700\u7ec8\u7528\u6237&#xff09;&#xff1a;Home Assistant \u76f4\u63a5\u901a\u8fc7 MQTT \u96c6\u6210\u63a5\u5165&#xff0c;\u65e0\u9700\u81ea\u7814\u4ee3\u7801\u3002<\/li>\n<li>\u8def\u5f84 B&#xff08;\u9762\u5411\u4e8c\u6b21\u5f00\u53d1&#xff09;&#xff1a;Python &#043; React Demo&#xff0c;\u6f14\u793a\u5982\u4f55\u81ea\u5efa\u4e00\u5957 Web \u63a7\u5236\u53f0\u3002<\/li>\n<\/ul>\n<h3>2. \u8bbe\u5907\u901a\u4fe1\u914d\u7f6e&#xff08;\u51fa\u5382\u9ed8\u8ba4 \u2192 \u81ea\u5efa Broker&#xff09;<\/h3>\n<p>\u8bbe\u5907\u51fa\u5382\u9ed8\u8ba4\u8fde\u63a5 GemeOpen \u5382\u5bb6 MQTT \u670d\u52a1\u5668\u3002\u63a5\u5165\u81ea\u5efa Broker \u9700\u5728\u539f\u5382\u901a\u9053\u4e0b\u53d1 setting-mqtt \u6307\u4ee4&#xff08;\u8be6\u89c1 docs\/02-device-setup.md&#xff09;\u3002<\/p>\n<p>setting-mqtt \u6307\u4ee4&#xff1a;<\/p>\n<p><span class=\"token punctuation\">{<\/span><br \/>\n  <span class=\"token string-property property\">&#034;clientId&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;gspm1b-28372fcbbbb8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;messageId&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;20260520120000001&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;password&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;device-pass&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;port&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;1883&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;protocol&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;mqtt&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;publish&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;gemeopen\/gspm1b\/28372fcbbbb8\/report&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;server&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;192.168.1.10&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;subcribe&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;gemeopen\/gspm1b\/28372fcbbbb8\/command&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;type&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;custom&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;username&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;device&#034;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u26a0\ufe0f \u8bed\u4e49&#xff08;\u6613\u9519&#xff0c;\u52a1\u5fc5\u6309\u6b64\u7406\u89e3&#xff09;<\/p>\n<ul>\n<li>publish &#061; \u8bbe\u5907\u53d1\u5e03\u6570\u636e\u7684\u4e3b\u9898 \u2192 \u670d\u52a1\u7aef\u8ba2\u9605\u5b83\u6765\u63a5\u6536\u4e0a\u62a5&#xff08;\u672c\u9879\u76ee\u8bb0\u4f5c reportTopic&#xff09;\u3002<\/li>\n<li>subcribe &#061; \u8bbe\u5907\u8ba2\u9605\u7684\u4e3b\u9898 \u2192 \u670d\u52a1\u7aef\u53d1\u5e03\u6307\u4ee4\u5230\u5b83\u6765\u63a7\u5236\u8bbe\u5907&#xff08;\u672c\u9879\u76ee\u8bb0\u4f5c commandTopic&#xff09;\u3002<\/li>\n<\/ul>\n<h3>3. MQTT \u4e3b\u9898\u7ea6\u5b9a<\/h3>\n<table>\n<tr>\u540d\u79f0\u9ed8\u8ba4\u503c\u65b9\u5411<\/tr>\n<tbody>\n<tr>\n<td>reportTopic<\/td>\n<td>gemeopen\/gspm1b\/{mac}\/report<\/td>\n<td>\u8bbe\u5907 \u2192 \u670d\u52a1\u7aef&#xff08;\u4e0a\u884c&#xff0c;\u670d\u52a1\u7aef\u8ba2\u9605&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>commandTopic<\/td>\n<td>gemeopen\/gspm1b\/{mac}\/command<\/td>\n<td>\u670d\u52a1\u7aef \u2192 \u8bbe\u5907&#xff08;\u4e0b\u884c&#xff0c;\u670d\u52a1\u7aef\u53d1\u5e03&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>HA \u4e0e Python \u540e\u7aef\u4f7f\u7528\u540c\u4e00\u5957\u4e3b\u9898&#xff1b;\u4e24\u8005\u5404\u81ea\u7528\u72ec\u7acb clientId \u8fde\u63a5 Broker\u3002<\/p>\n<h3>4. \u6307\u4ee4\u4e0e\u6d88\u606f\u5951\u7ea6&#xff08;JSON&#xff09;<\/h3>\n<h4>4.1 \u4e0b\u884c\u6307\u4ee4&#xff08;\u670d\u52a1\u7aef \u2192 \u8bbe\u5907&#xff0c;\u53d1\u5230 commandTopic&#xff09;<\/h4>\n<table>\n<tr>\u529f\u80fdpayload\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>\u901a\u65ad\u7535\u63a7\u5236<\/td>\n<td>{&#034;key&#034;:1,&#034;messageId&#034;:&#034;&lt;id&gt;&#034;,&#034;type&#034;:&#034;event&#034;}<\/td>\n<td>key&#061;1 \u901a\u7535&#xff0c;key&#061;0 \u65ad\u7535<\/td>\n<\/tr>\n<tr>\n<td>\u67e5\u8be2\u5b9e\u65f6\u7535\u91cf<\/td>\n<td>{&#034;messageId&#034;:&#034;&lt;id&gt;&#034;,&#034;type&#034;:&#034;statistic&#034;}<\/td>\n<td>\u89e6\u53d1\u4e00\u6b21\u5b9e\u65f6\u6570\u636e\u56de\u4f20<\/td>\n<\/tr>\n<tr>\n<td>\u8bbe\u7f6e\u4e0a\u62a5\u9891\u7387<\/td>\n<td>{&#034;messageId&#034;:&#034;&lt;id&gt;&#034;,&#034;timerEnable&#034;:1,&#034;timerInterval&#034;:15,&#034;type&#034;:&#034;setting&#034;}<\/td>\n<td>\u81ea\u52a8\u4e0a\u62a5\u5f00\u5173\u4e0e\u5468\u671f&#xff08;5~86400 \u79d2&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u83b7\u53d6\u8bbe\u5907\u4fe1\u606f<\/td>\n<td>{&#034;messageId&#034;:&#034;&lt;id&gt;&#034;,&#034;type&#034;:&#034;info&#034;}<\/td>\n<td>\u8fd4\u56de\u56fa\u4ef6\u3001IP\u3001\u4fe1\u53f7\u7b49<\/td>\n<\/tr>\n<tr>\n<td>\u6062\u590d\u51fa\u5382<\/td>\n<td>{&#034;messageId&#034;:&#034;&lt;id&gt;&#034;,&#034;system&#034;:&#034;reset&#034;,&#034;type&#034;:&#034;setting&#034;}<\/td>\n<td>\u8c28\u614e<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>4.2 \u4e0a\u884c\u6d88\u606f&#xff08;\u8bbe\u5907 \u2192 \u670d\u52a1\u7aef&#xff0c;\u6765\u81ea reportTopic&#xff09;<\/h4>\n<p>A. \u5b9a\u65f6\u81ea\u52a8\u4e0a\u62a5&#xff08;device-timer-task&#xff09;<\/p>\n<p><span class=\"token punctuation\">{<\/span><br \/>\n  <span class=\"token string-property property\">&#034;commandName&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;device-timer-task&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;mac&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;28372fcbbbb8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;messageId&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;source&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;auto&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;key&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;voltage&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">226.024<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;current&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">0.501<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;power&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">113.4<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;energy&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">25.047<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>B. \u6307\u4ee4\u54cd\u5e94&#xff08;controller-event \/ info-statistic \/ info-all&#xff09;<\/p>\n<p><span class=\"token punctuation\">{<\/span><br \/>\n  <span class=\"token string-property property\">&#034;commandName&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;info-statistic&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;mac&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;28372fcbbbb8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;messageId&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;20260520120000001&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;source&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;command&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;key&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;voltage&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">226.024<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;current&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">0.501<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;power&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">113.4<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;energy&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">25.047<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u5b57\u6bb5\u8bed\u4e49\u4e0e\u5355\u4f4d<\/p>\n<table>\n<tr>\u8bbe\u5907\u5b57\u6bb5\u542b\u4e49\u5355\u4f4d\u5f52\u4e00\u5316\u5b57\u6bb5&#xff08;\u672c\u9879\u76ee\u7edf\u4e00\u547d\u540d&#xff09;<\/tr>\n<tbody>\n<tr>\n<td>key<\/td>\n<td>\u901a\u65ad\u7535\u72b6\u6001&#xff08;1 \u901a\u7535 \/ 0 \u65ad\u7535&#xff09;<\/td>\n<td>\u2014<\/td>\n<td>relayOn (boolean)<\/td>\n<\/tr>\n<tr>\n<td>voltage<\/td>\n<td>\u7535\u538b<\/td>\n<td>V<\/td>\n<td>voltageV<\/td>\n<\/tr>\n<tr>\n<td>current<\/td>\n<td>\u7535\u6d41<\/td>\n<td>A<\/td>\n<td>currentA<\/td>\n<\/tr>\n<tr>\n<td>power<\/td>\n<td>\u6709\u529f\u529f\u7387<\/td>\n<td>W<\/td>\n<td>activePowerW<\/td>\n<\/tr>\n<tr>\n<td>energy<\/td>\n<td>\u7d2f\u8ba1\u7528\u7535\u91cf&#xff08;\u65ad\u7535\u4e0d\u5f52\u96f6&#xff09;<\/td>\n<td>kW\u00b7h<\/td>\n<td>energyKwh<\/td>\n<\/tr>\n<tr>\n<td>signal<\/td>\n<td>\u4fe1\u53f7\u5f3a\u5ea6<\/td>\n<td>dBm<\/td>\n<td>signalDbm<\/td>\n<\/tr>\n<tr>\n<td>commandName<\/td>\n<td>\u6307\u4ee4\u540d<\/td>\n<td>\u2014<\/td>\n<td>commandName<\/td>\n<\/tr>\n<tr>\n<td>source<\/td>\n<td>\u6765\u6e90 command\/auto\/button<\/td>\n<td>\u2014<\/td>\n<td>source<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>5. Python \u540e\u7aef API \u5951\u7ea6&#xff08;\u4f9b React \u524d\u7aef\u8c03\u7528&#xff09;<\/h3>\n<p>Base URL&#xff1a;http:\/\/&lt;host&gt;:8000<\/p>\n<h4>5.1 GET \/api\/health<\/h4>\n<p><span class=\"token punctuation\">{<\/span> <span class=\"token string-property property\">&#034;status&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;ok&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;mqttConnected&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;deviceOnline&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<h4>5.2 GET \/api\/device<\/h4>\n<p>\u8fd4\u56de\u5f53\u524d\u8bbe\u5907\u72b6\u6001\u5feb\u7167 DeviceState&#xff1a;<\/p>\n<p><span class=\"token punctuation\">{<\/span><br \/>\n  <span class=\"token string-property property\">&#034;mac&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;28372fcbbbb8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;online&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;relayOn&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;voltageV&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">226.024<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;currentA&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">0.501<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;activePowerW&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">113.4<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;energyKwh&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">25.047<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;signalDbm&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token number\">75<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;source&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;auto&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;lastUpdate&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">1787992225<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>lastUpdate \u4e3a\u79d2\u7ea7 Unix \u65f6\u95f4\u6233&#xff1b;\u65e0\u6570\u636e\u65f6\u5404\u6570\u503c\u5b57\u6bb5\u4e3a null\u3002<\/p>\n<h4>5.3 POST \/api\/device\/switch<\/h4>\n<p>\u8bf7\u6c42&#xff1a;{ &#034;on&#034;: true } \u2192 \u54cd\u5e94&#xff1a;{ &#034;success&#034;: true, &#034;state&#034;: &lt;DeviceState&gt; }<\/p>\n<h4>5.4 POST \/api\/device\/refresh<\/h4>\n<p>\u89e6\u53d1\u4e00\u8f6e info &#043; statistic \u67e5\u8be2&#xff0c;\u54cd\u5e94&#xff1a;{ &#034;success&#034;: true }<\/p>\n<h4>5.5 GET \/api\/device\/history?limit&#061;200<\/h4>\n<p>\u8fd4\u56de\u91c7\u6837\u5386\u53f2&#xff08;\u65f6\u95f4\u5347\u5e8f&#xff09;&#xff1a;<\/p>\n<p><span class=\"token punctuation\">[<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token string-property property\">&#034;ts&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">1787992225<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;voltageV&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">226.024<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;currentA&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">0.501<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;activePowerW&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">113.4<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;energyKwh&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token number\">25.047<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string-property property\">&#034;relayOn&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span> <span class=\"token punctuation\">}<\/span> <span class=\"token punctuation\">]<\/span><\/p>\n<h4>5.6 GET \/api\/config<\/h4>\n<p>\u8fd4\u56de\u975e\u654f\u611f\u8fd0\u884c\u914d\u7f6e&#xff1a;{ &#034;reportTopic&#034;: &#034;&#8230;&#034;, &#034;commandTopic&#034;: &#034;&#8230;&#034;, &#034;mac&#034;: &#034;&#8230;&#034; }<\/p>\n<h4>5.7 WS \/ws\/telemetry<\/h4>\n<p>WebSocket&#xff0c;\u6bcf\u6b21\u8bbe\u5907\u72b6\u6001\u66f4\u65b0\u65f6\u63a8\u9001\u4e00\u5e27 DeviceState&#xff08;\u4e0e 5.2 \u540c\u7ed3\u6784&#xff09;\u3002<\/p>\n<h3>6. \u540e\u7aef\u73af\u5883\u53d8\u91cf&#xff08;.env&#xff09;<\/h3>\n<table>\n<tr>\u53d8\u91cf\u9ed8\u8ba4\u503c\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>MQTT_HOST<\/td>\n<td>127.0.0.1<\/td>\n<td>Broker \u5730\u5740<\/td>\n<\/tr>\n<tr>\n<td>MQTT_PORT<\/td>\n<td>1883<\/td>\n<td>Broker \u7aef\u53e3<\/td>\n<\/tr>\n<tr>\n<td>MQTT_USERNAME<\/td>\n<td>backend<\/td>\n<td>\u540e\u7aef\u8fde\u63a5 Broker \u7684\u7528\u6237\u540d<\/td>\n<\/tr>\n<tr>\n<td>MQTT_PASSWORD<\/td>\n<td>backend-pass<\/td>\n<td>\u540e\u7aef\u5bc6\u7801<\/td>\n<\/tr>\n<tr>\n<td>MQTT_CLIENT_ID<\/td>\n<td>gemeopen-backend<\/td>\n<td>\u540e\u7aef clientId&#xff08;\u552f\u4e00&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>MQTT_REPORT_TOPIC<\/td>\n<td>gemeopen\/gspm1b\/&#043;\/report<\/td>\n<td>\u8ba2\u9605&#xff08;&#043; \u901a\u914d\u5355\u8bbe\u5907&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>MQTT_COMMAND_TOPIC<\/td>\n<td>gemeopen\/gspm1b\/{mac}\/command<\/td>\n<td>\u53d1\u5e03\u6307\u4ee4<\/td>\n<\/tr>\n<tr>\n<td>DEVICE_MAC<\/td>\n<td>28372fcbbbb8<\/td>\n<td>\u76ee\u6807\u8bbe\u5907 MAC<\/td>\n<\/tr>\n<tr>\n<td>HISTORY_SIZE<\/td>\n<td>2000<\/td>\n<td>\u5185\u5b58\u4e2d\u4fdd\u7559\u7684\u91c7\u6837\u6761\u6570<\/td>\n<\/tr>\n<tr>\n<td>CORS_ORIGINS<\/td>\n<td>*<\/td>\n<td>\u5141\u8bb8\u7684\u524d\u7aef\u6765\u6e90<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>7. \u524d\u7aef\u7ea6\u5b9a<\/h3>\n<ul>\n<li>\u6784\u5efa\u5de5\u5177&#xff1a;Vite &#043; React 18<\/li>\n<li>\u72b6\u6001\u6765\u6e90&#xff1a;REST \u8f6e\u8be2&#xff08;\/api\/device&#xff09;&#043; WebSocket&#xff08;\/ws\/telemetry&#xff09;\u5b9e\u65f6\u63a8\u9001<\/li>\n<li>API Base&#xff1a;\u73af\u5883\u53d8\u91cf VITE_API_BASE&#xff08;\u9ed8\u8ba4 http:\/\/localhost:8000&#xff09;<\/li>\n<li>\u5c55\u793a\u5185\u5bb9&#xff1a;\u901a\u65ad\u7535\u5f00\u5173\u3001\u7535\u538b\/\u7535\u6d41\/\u529f\u7387\u5b9e\u65f6\u503c\u3001\u7d2f\u8ba1\u7528\u7535\u91cf\u3001\u5728\u7ebf\u72b6\u6001\u3001\u7b80\u6613\u5386\u53f2\u66f2\u7ebf<\/li>\n<\/ul>\n<h3>8. \u76ee\u5f55\u7ed3\u6784<\/h3>\n<p>gemeopen-ha-demo\/<br \/>\n\u251c\u2500\u2500 README.md                 # \u603b\u89c8\u4e0e\u5feb\u901f\u5f00\u59cb<br \/>\n\u251c\u2500\u2500 docker-compose.yml        # Mosquitto &#043; \u540e\u7aef &#043; \u524d\u7aef<br \/>\n\u251c\u2500\u2500 docs\/<br \/>\n\u2502   \u251c\u2500\u2500 00-architecture.md    # \u672c\u6587\u4ef6&#xff08;\u5951\u7ea6&#xff09;<br \/>\n\u2502   \u251c\u2500\u2500 01-overview.md        # \u65b9\u6848\u603b\u89c8&#xff08;\u521d\u5b66\u8005\u5411&#xff09;<br \/>\n\u2502   \u251c\u2500\u2500 02-device-setup.md    # \u8bbe\u5907\u7aef MQTT \u914d\u7f6e<br \/>\n\u2502   \u251c\u2500\u2500 03-homeassistant.md   # Home Assistant \u63a5\u5165<br \/>\n\u2502   \u251c\u2500\u2500 04-backend.md         # Python \u540e\u7aef\u8bf4\u660e<br \/>\n\u2502   \u251c\u2500\u2500 05-frontend.md        # React \u524d\u7aef\u8bf4\u660e<br \/>\n\u2502   \u251c\u2500\u2500 06-deploy-ops.md      # \u90e8\u7f72\u4e0e\u8fd0\u7ef4<br \/>\n\u2502   \u2514\u2500\u2500 07-troubleshooting.md # \u6392\u9519\u624b\u518c<br \/>\n\u251c\u2500\u2500 homeassistant\/            # HA \u914d\u7f6e\u7247\u6bb5<br \/>\n\u251c\u2500\u2500 backend\/                  # Python FastAPI \u540e\u7aef<br \/>\n\u251c\u2500\u2500 frontend\/                 # React \u524d\u7aef<br \/>\n\u251c\u2500\u2500 scripts\/                  # \u8bbe\u5907\u914d\u7f6e\u811a\u672c<br \/>\n\u2514\u2500\u2500 mosquitto\/                # Broker \u914d\u7f6e<\/p>\n<h4>01-overview.md<\/h4>\n<h2>01 \u00b7 \u65b9\u6848\u603b\u89c8&#xff08;Java &#043; Angular \u7248&#xff09;<\/h2>\n<h3>1. \u8fd9\u4e2a\u9879\u76ee\u8981\u89e3\u51b3\u4ec0\u4e48&#xff1f;<\/h3>\n<p>\u628a GemeOpen GSPM1B \u667a\u80fd\u8f6c\u6362\u5668\u63d2\u5ea7 \u63a5\u5165 Home Assistant&#xff0c;\u5b9e\u73b0&#xff1a;<\/p>\n<ul>\n<li>\u2705 \u901a\u65ad\u7535\u63a7\u5236&#xff08;\u5f00 \/ \u5173&#xff09;<\/li>\n<li>\u2705 \u5b9e\u65f6\u7535\u538b\u3001\u7535\u6d41\u3001\u529f\u7387\u91c7\u96c6<\/li>\n<li>\u2705 \u7d2f\u8ba1\u7528\u7535\u91cf\u67e5\u8be2<\/li>\n<li>\u2705&#xff08;\u52a0\u5206&#xff09;\u4e00\u5957 Java(Spring Boot) &#043; Angular \u7684\u81ea\u7814 Demo<\/li>\n<\/ul>\n<p>\u672c\u5de5\u7a0b\u4e0e Python &#043; React \u7248\u662f\u300c\u59ca\u59b9\u5de5\u7a0b\u300d&#xff0c;MQTT \u534f\u8bae\u3001\u4e3b\u9898\u3001\u63a5\u53e3\u5951\u7ea6\u5b8c\u5168\u4e00\u81f4&#xff0c;\u53ea\u662f\u628a\u4e8c\u6b21\u5f00\u53d1\u7684\u6280\u672f\u6808\u6362\u6210\u4e86 Java &#043; Angular\u3002<\/p>\n<h3>2. \u4e24\u6761\u63a5\u5165\u8def\u5f84<\/h3>\n<p>                 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n   GSPM1B \u2500\u2500MQTT\u2500\u2524            Mosquitto Broker               \u2502<br \/>\n   (\u8bbe\u5907)         \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n                          \u2502 MQTT                  \u2502 MQTT<br \/>\n                 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n                 \u2502 \u8def\u5f84 A            \u2502    \u2502 \u8def\u5f84 B                 \u2502<br \/>\n                 \u2502 Home Assistant   \u2502    \u2502 Java \u540e\u7aef (Spring Boot)\u2502<br \/>\n                 \u2502 MQTT \u96c6\u6210        \u2502    \u2502   \u21c5 REST \/ WebSocket   \u2502<br \/>\n                 \u2502 switch &#043; sensor  \u2502    \u2502 Angular \u524d\u7aef           \u2502<br \/>\n                 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n                    \u65e0\u9700\u5199\u4ee3\u7801               \u9002\u5408 Java \u5f00\u53d1\u8005\u5b66\u4e60<\/p>\n<h3>3. \u6280\u672f\u6808<\/h3>\n<table>\n<tr>\u5c42\u6280\u672f<\/tr>\n<tbody>\n<tr>\n<td>\u8bbe\u5907\u901a\u4fe1<\/td>\n<td>MQTT&#xff08;Eclipse Paho Java Client&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u540e\u7aef<\/td>\n<td>Java 17 &#043; Spring Boot 3.2 &#043; Spring Web &#043; \u539f\u751f WebSocket<\/td>\n<\/tr>\n<tr>\n<td>\u524d\u7aef<\/td>\n<td>Angular 17&#xff08;standalone components&#xff09;&#043; RxJS &#043; \u539f\u751f SVG \u56fe\u8868<\/td>\n<\/tr>\n<tr>\n<td>Broker<\/td>\n<td>Eclipse Mosquitto 2<\/td>\n<\/tr>\n<tr>\n<td>\u90e8\u7f72<\/td>\n<td>Docker \/ Docker Compose &#043; Nginx<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>4. \u5feb\u901f\u5f00\u59cb&#xff08;5 \u6b65&#xff09;<\/h3>\n<p><span class=\"token comment\"># \u2460 \u542f\u52a8 Broker &#043; \u540e\u7aef &#043; \u524d\u7aef<\/span><br \/>\n<span class=\"token builtin class-name\">cd<\/span> gemeopen-ha-java-demo<br \/>\n<span class=\"token function\">docker<\/span> compose up <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">&#8211;build<\/span><\/p>\n<p><span class=\"token comment\"># \u2461 \u628a\u8bbe\u5907\u5207\u5230\u4f60\u7684 Broker&#xff08;\u7f16\u8f91 scripts\/device_switch.json \u540e\u6267\u884c&#xff09;<\/span><br \/>\n<span class=\"token builtin class-name\">cd<\/span> scripts <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">cp<\/span> device_switch.example.json device_switch.json<br \/>\npython3 configure_device.py <span class=\"token parameter variable\">&#8211;config<\/span> device_switch.json<br \/>\n<span class=\"token comment\">#   \u6210\u529f\u540e\u7ed9\u8bbe\u5907\u65ad\u7535\u91cd\u542f<\/span><\/p>\n<p><span class=\"token comment\"># \u2462 \u8ba9\u8bbe\u5907\u5b9a\u65f6\u4e0a\u62a5&#xff08;\u793a\u4f8b 15 \u79d2&#xff09;<\/span><br \/>\nmosquitto_pub <span class=\"token parameter variable\">-h<\/span> <span class=\"token operator\">&lt;<\/span>\u4f60\u7684IP<span class=\"token operator\">&gt;<\/span> <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token parameter variable\">-t<\/span> <span class=\"token string\">&#039;gemeopen\/gspm1b\/&lt;MAC&gt;\/command&#039;<\/span> <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-m<\/span> <span class=\"token string\">&#039;{&#034;messageId&#034;:&#034;1&#034;,&#034;timerEnable&#034;:1,&#034;timerInterval&#034;:15,&#034;type&#034;:&#034;setting&#034;}&#039;<\/span><\/p>\n<p><span class=\"token comment\"># \u2463 \u6253\u5f00\u81ea\u7814 Demo&#xff1a;\u6d4f\u89c8\u5668\u8bbf\u95ee http:\/\/&lt;\u4f60\u7684IP&gt;:8080<\/span><\/p>\n<p><span class=\"token comment\"># \u2464 \u63a5\u5165 Home Assistant&#xff1a;\u89c1 docs\/03-homeassistant.md<\/span><\/p>\n<h3>5. \u6587\u6863\u5bfc\u822a<\/h3>\n<table>\n<tr>\u6587\u6863\u5185\u5bb9<\/tr>\n<tbody>\n<tr>\n<td>[02 \u00b7 \u8bbe\u5907\u7aef\u914d\u7f6e] 02-device-setup.md<\/td>\n<td>\u628a\u8bbe\u5907\u6307\u5411\u81ea\u5efa Broker&#xff08;\u5fc5\u8bfb&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>[03 \u00b7 Home Assistant \u63a5\u5165] 03-homeassistant.md<\/td>\n<td>HA \u96c6\u6210 &#043; \u5b9e\u4f53 &#043; \u4eea\u8868\u76d8 &#043; \u81ea\u52a8\u5316<\/td>\n<\/tr>\n<tr>\n<td>[04 \u00b7 Java \u540e\u7aef] 04-backend.md<\/td>\n<td>Spring Boot &#043; MQTT \u4ee3\u7801\u8bf4\u660e<\/td>\n<\/tr>\n<tr>\n<td>[05 \u00b7 Angular \u524d\u7aef] 05-frontend.md<\/td>\n<td>\u7ec4\u4ef6\u7ed3\u6784\u3001\u670d\u52a1\u3001\u8fd0\u884c\u65b9\u5f0f<\/td>\n<\/tr>\n<tr>\n<td>[06 \u00b7 \u90e8\u7f72\u4e0e\u8fd0\u7ef4] 06-deploy-ops.md<\/td>\n<td>\u4e09\u79cd\u90e8\u7f72\u65b9\u5f0f\u3001\u5907\u4efd\u3001\u76d1\u63a7<\/td>\n<\/tr>\n<tr>\n<td>[07 \u00b7 \u6392\u9519\u624b\u518c] 07-troubleshooting.md<\/td>\n<td>\u6309\u75c7\u72b6\u6392\u67e5<\/td>\n<\/tr>\n<tr>\n<td>[00 \u00b7 \u67b6\u6784\u4e0e\u5951\u7ea6] 00-architecture.md<\/td>\n<td>\u4e3b\u9898\/\u6d88\u606f\/API \u5951\u7ea6&#xff08;\u57fa\u51c6&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>6. \u5173\u952e\u6982\u5ff5 30 \u79d2\u901f\u901a<\/h3>\n<ul>\n<li>MQTT&#xff1a;\u8f7b\u91cf\u53d1\u5e03\/\u8ba2\u9605\u534f\u8bae\u3002\u8bbe\u5907\u201c\u53d1\u5e03\u201d\u6570\u636e\u5230\u201c\u4e3b\u9898\u201d&#xff0c;\u7a0b\u5e8f\u201c\u8ba2\u9605\u201d\u8be5\u4e3b\u9898\u5373\u6536\u5230\u3002<\/li>\n<li>Broker&#xff08;Mosquitto&#xff09;&#xff1a;\u6d88\u606f\u4e2d\u8f6c\u7ad9&#xff1b;\u8bbe\u5907\u3001HA\u3001\u540e\u7aef\u90fd\u8fde\u5b83\u3002<\/li>\n<li>Topic&#xff1a;\u7c7b\u4f3c\u201c\u9891\u9053\u540d\u201d&#xff0c;\u672c\u9879\u76ee\u7528 gemeopen\/gspm1b\/&lt;mac&gt;\/report&#xff08;\u8bbe\u5907\u53d1&#xff09;\u4e0e &#8230;\/command&#xff08;\u8bbe\u5907\u6536&#xff09;\u3002<\/li>\n<li>Home Assistant&#xff1a;\u5f00\u6e90\u667a\u80fd\u5bb6\u5c45\u5e73\u53f0&#xff0c;\u901a\u8fc7 MQTT \u96c6\u6210\u628a\u8bbe\u5907\u53d8\u6210\u53ef\u63a7\u201c\u5b9e\u4f53\u201d\u3002<\/li>\n<\/ul>\n<p>\u26a0\ufe0f \u6700\u5bb9\u6613\u8e29\u7684\u5751&#xff1a;\u6587\u6863\u91cc publish \/ subcribe \u4e0e\u76f4\u89c9\u76f8\u53cd\u2014\u2014\u8bbe\u5907\u7684 publish \u4e3b\u9898\u662f\u4f60\u8981\u8ba2\u9605\u7684&#xff0c;subcribe \u4e3b\u9898\u662f\u4f60\u8981\u53d1\u5e03\u6307\u4ee4\u7684\u3002\u8be6\u89c1 [02] 02-device-setup.md \u3002<\/p>\n<hr \/>\n<h4>02-device-setup.md<\/h4>\n<h2>02 \u00b7 \u8bbe\u5907\u7aef MQTT \u914d\u7f6e&#xff08;\u628a GSPM1B \u6307\u5411\u81ea\u5efa Broker&#xff09;<\/h2>\n<p>\u76ee\u6807&#xff1a;\u8ba9 GSPM1B \u628a\u6570\u636e\u53d1\u5230\u4f60\u81ea\u5df1\u7684 MQTT Broker&#xff08;Mosquitto&#xff09;&#xff0c;\u8fd9\u6837 Home Assistant \u548c Python \u540e\u7aef\u624d\u80fd\u8bfb\u5230\u6570\u636e\u3001\u53d1\u51fa\u63a7\u5236\u6307\u4ee4\u3002<\/p>\n<h3>1. \u4e3a\u4ec0\u4e48\u9700\u8981\u8fd9\u4e00\u6b65&#xff1f;<\/h3>\n<p>GSPM1B \u51fa\u5382\u65f6\u9ed8\u8ba4\u8fde\u63a5 GemeOpen \u5382\u5bb6\u6d4b\u8bd5\u670d\u52a1\u5668&#xff08;mqtt.smart-bird.cn:1883&#xff09;&#xff0c;\u514d\u8d39\u4f9b\u8c03\u8bd5\u3002\u8981\u8ba9 HA \u63a5\u7ba1&#xff0c;\u5c31\u9700\u8981\u628a\u8bbe\u5907\u6539\u4e3a\u8fde\u63a5\u4f60\u81ea\u5df1\u7684 Broker\u3002<\/p>\n<p>\u8bbe\u5907\u63d0\u4f9b\u4e86\u4e13\u95e8\u7684\u6307\u4ee4 setting-mqtt&#xff08;\u81ea\u5b9a\u4e49 MQTT \u53c2\u6570&#xff09;\u6765\u5b8c\u6210\u8fd9\u4ef6\u4e8b\u3002<\/p>\n<h3>2. \u51c6\u5907\u5de5\u4f5c<\/h3>\n<p>\u4f60\u9700\u8981\u5148\u77e5\u9053\u8bbe\u5907\u5f53\u524d\u6240\u5728 Broker \u7684\u8fde\u63a5\u4fe1\u606f&#xff0c;\u901a\u8fc7\u8bbe\u5907\u6307\u4ee4 info-protocol \u83b7\u53d6&#xff1a;<\/p>\n<table>\n<tr>\u5b57\u6bb5\u542b\u4e49\u7528\u9014<\/tr>\n<tbody>\n<tr>\n<td>server \/ port<\/td>\n<td>\u5f53\u524d Broker \u5730\u5740\/\u7aef\u53e3<\/td>\n<td>\u8fde\u63a5\u5b83\u6765\u4e0b\u53d1\u5207\u6362\u6307\u4ee4<\/td>\n<\/tr>\n<tr>\n<td>username<\/td>\n<td>\u5f53\u524d Broker \u7528\u6237\u540d<\/td>\n<td>\u8fde\u63a5\u51ed\u636e<\/td>\n<\/tr>\n<tr>\n<td>publish<\/td>\n<td>\u8bbe\u5907\u53d1\u5e03\u4e3b\u9898&#xff08;\u670d\u52a1\u7aef\u8ba2\u9605\u5b83\u6536\u6570\u636e&#xff09;<\/td>\n<td>\u8bb0\u4e3a report_topic<\/td>\n<\/tr>\n<tr>\n<td>subcribe<\/td>\n<td>\u8bbe\u5907\u8ba2\u9605\u4e3b\u9898&#xff08;\u670d\u52a1\u7aef\u5411\u5b83\u53d1\u6307\u4ee4&#xff09;<\/td>\n<td>\u8bb0\u4e3a command_topic<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u26a0\ufe0f \u6ce8\u610f publish \/ subcribe&#xff08;\u539f\u6587\u62fc\u5199&#xff09;\u7684\u8bed\u4e49\u4e0e\u76f4\u89c9\u76f8\u53cd&#xff1a;<\/p>\n<ul>\n<li>\u8bbe\u5907\u628a\u6570\u636e publish \u5230 publish \u4e3b\u9898 \u2192 \u6240\u4ee5\u4f60\u8981\u8ba2\u9605\u5b83\u3002<\/li>\n<li>\u8bbe\u5907 subscribe \u4e86 subcribe \u4e3b\u9898 \u2192 \u6240\u4ee5\u4f60\u8981\u5f80\u5b83\u53d1\u5e03\u6307\u4ee4\u3002<\/li>\n<\/ul>\n<p>\u83b7\u53d6\u65b9\u5f0f&#xff1a;<\/p>\n<li>GemeOpen \u63a7\u5236\u53f0&#xff1a;\u767b\u5f55\u540e\u5728\u8bbe\u5907\u8be6\u60c5\u9875\u67e5\u770b&#xff1b;<\/li>\n<li>\u8bbe\u5907\u6307\u4ee4&#xff1a;\u5f80\u8bbe\u5907\u53d1 {&#034;type&#034;:&#034;info&#034;,&#034;messageId&#034;:&#034;&#8230;&#034;}&#xff08;info-protocol \u9700\u6309\u5176\u6587\u6863\u8bf4\u660e\u89e6\u53d1&#xff09;&#xff0c;\u8fd4\u56de\u91cc\u542b\u4e0a\u8ff0\u5b57\u6bb5&#xff1b;<\/li>\n<li>\u5411\u5382\u5bb6\/\u9500\u552e\u7d22\u53d6&#xff1a;\u6d4b\u8bd5\u670d\u52a1\u5668\u7684\u8fde\u63a5\u51ed\u636e&#xff08;username\/password&#xff09;\u901a\u5e38\u9700\u8981\u5382\u5bb6\u63d0\u4f9b\u3002<\/li>\n<h3>3. \u4e00\u952e\u5207\u6362\u811a\u672c<\/h3>\n<p>\u5de5\u7a0b\u63d0\u4f9b\u4e86\u811a\u672c scripts\/configure_device.py&#xff1a;<\/p>\n<p><span class=\"token builtin class-name\">cd<\/span> scripts<br \/>\n<span class=\"token function\">cp<\/span> device_switch.example.json device_switch.json<br \/>\n<span class=\"token comment\"># \u7f16\u8f91 device_switch.json&#xff0c;\u586b\u5165 current&#xff08;\u5f53\u524d Broker&#xff09;\u4e0e target&#xff08;\u4f60\u7684\u81ea\u5efa Broker&#xff09;<\/span><br \/>\npip <span class=\"token function\">install<\/span> paho-mqtt<span class=\"token operator\">&#061;&#061;<\/span><span class=\"token number\">2.1<\/span>.0<br \/>\npython3 configure_device.py <span class=\"token parameter variable\">&#8211;config<\/span> device_switch.json<\/p>\n<p>\u914d\u7f6e\u6a21\u677f\u5173\u952e\u5b57\u6bb5&#xff1a;<\/p>\n<p>{<br \/>\n  &#034;current&#034;: {                          \/\/ \u8bbe\u5907\u201c\u73b0\u5728\u201d\u6240\u5728\u7684 Broker<br \/>\n    &#034;server&#034;: &#034;mqtt.smart-bird.cn&#034;,<br \/>\n    &#034;port&#034;: 1883,<br \/>\n    &#034;username&#034;: &#034;&lt;\u5e73\u53f0\u7528\u6237\u540d&gt;&#034;,<br \/>\n    &#034;password&#034;: &#034;&lt;\u5e73\u53f0\u5bc6\u7801&gt;&#034;,<br \/>\n    &#034;report_topic&#034;: &#034;&lt;info-protocol \u7684 publish&gt;&#034;,<br \/>\n    &#034;command_topic&#034;: &#034;&lt;info-protocol \u7684 subcribe&gt;&#034;<br \/>\n  },<br \/>\n  &#034;target&#034;: {                           \/\/ \u8981\u5207\u6362\u5230\u7684\u201c\u81ea\u5efa\u201d Broker<br \/>\n    &#034;server&#034;: &#034;192.168.1.10&#034;,           \/\/ \u5fc5\u987b\u8bbe\u5907\u7f51\u7edc\u53ef\u8fbe<br \/>\n    &#034;port&#034;: 1883,<br \/>\n    &#034;username&#034;: &#034;device&#034;,<br \/>\n    &#034;password&#034;: &#034;device-pass&#034;,<br \/>\n    &#034;client_id&#034;: &#034;gspm1b-28372fcbbbb8&#034;,<br \/>\n    &#034;publish_topic&#034;: &#034;gemeopen\/gspm1b\/28372fcbbbb8\/report&#034;,<br \/>\n    &#034;subcribe_topic&#034;: &#034;gemeopen\/gspm1b\/28372fcbbbb8\/command&#034;<br \/>\n  }<br \/>\n}<\/p>\n<p>\u811a\u672c\u4f1a&#xff1a;\u8fde\u63a5\u5f53\u524d Broker \u2192 \u5411 command_topic \u53d1\u5e03 setting-mqtt \u2192 \u7b49\u5f85\u8bbe\u5907\u56de\u6267\u3002<\/p>\n<p>\u6210\u529f\u540e\u4f1a\u63d0\u793a&#xff1a;<\/p>\n<p>\u2705 \u8bbe\u5907\u5df2\u63a5\u53d7\u65b0\u7684 MQTT \u914d\u7f6e\u3002<br \/>\n   \u8bf7\u7ed9\u8bbe\u5907\u3010\u65ad\u7535\u91cd\u542f\u3011&#xff0c;\u6216\u53d1\u9001 controller-restart \u6307\u4ee4&#xff0c;\u4f7f\u914d\u7f6e\u751f\u6548\u3002<\/p>\n<h3>4. \u4f7f\u914d\u7f6e\u751f\u6548<\/h3>\n<p>setting-mqtt \u9700\u8981\u91cd\u542f\u624d\u751f\u6548&#xff1a;<\/p>\n<ul>\n<li>\u65ad\u7535\u91cd\u542f&#xff1a;\u62d4\u6389\u8bbe\u5907\u518d\u4e0a\u7535&#xff08;\u6700\u7b80\u5355&#xff09;&#xff1b;<\/li>\n<li>\u8f6f\u91cd\u542f&#xff1a;\u5411\u8bbe\u5907\u53d1 {&#034;messageId&#034;:&#034;&#8230;&#034;,&#034;system&#034;:&#034;restart&#034;,&#034;type&#034;:&#034;setting&#034;}&#xff08;controller-restart&#xff09;\u3002<\/li>\n<\/ul>\n<h3>5. \u9a8c\u8bc1\u8bbe\u5907\u5df2\u5207\u6362<\/h3>\n<p>\u5728\u4f60\u7684 Broker \u4e0a\u7528\u4efb\u610f MQTT \u5ba2\u6237\u7aef\u8ba2\u9605&#xff1a;<\/p>\n<p>mosquitto_sub <span class=\"token parameter variable\">-h<\/span> <span class=\"token number\">192.168<\/span>.1.10 <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token parameter variable\">-u<\/span> device <span class=\"token parameter variable\">-P<\/span> device-pass <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-t<\/span> <span class=\"token string\">&#039;gemeopen\/gspm1b\/28372fcbbbb8\/report&#039;<\/span> <span class=\"token parameter variable\">-v<\/span><\/p>\n<p>\u82e5\u8bbe\u5907\u6309\u4e0a\u62a5\u5468\u671f\u6301\u7eed\u5410\u51fa JSON&#xff08;\u542b voltage\/current\/power\/energy\/key&#xff09;&#xff0c;\u8bf4\u660e\u5207\u6362\u6210\u529f &#x1f389;\u3002<\/p>\n<h3>6. \u6ca1\u6709\u5382\u5bb6\u51ed\u636e\u600e\u4e48\u529e&#xff1f;<\/h3>\n<ul>\n<li>\u65b9\u6848 A&#xff08;\u63a8\u8350&#xff09;&#xff1a;\u8054\u7cfb GemeOpen \u83b7\u53d6\u6d4b\u8bd5\u670d\u52a1\u5668\u51ed\u636e&#xff0c;\u7528\u811a\u672c\u5207\u6362&#xff1b;<\/li>\n<li>\u65b9\u6848 B&#xff1a;\u8bbe\u5907\u652f\u6301\u5185\u7f51 HTTP \u63a7\u5236&#xff08;\u56fa\u4ef6 2.0.0&#043;&#xff09;&#xff0c;\u53ef\u5728\u8bbe\u5907\u6240\u5728\u5c40\u57df\u7f51\u5185\u76f4\u63a5\u914d\u7f6e&#xff08;\u5177\u4f53\u63a5\u53e3\u4ee5\u8bbe\u5907\u6587\u6863\u4e3a\u51c6&#xff09;&#xff1b;<\/li>\n<li>\u65b9\u6848 C&#xff1a;\u5148\u7528\u5382\u5bb6\u9ed8\u8ba4\u670d\u52a1\u5668\u8c03\u8bd5&#xff0c;\u8dd1\u901a scripts\/ \u4e0e\u540e\u7aef\u903b\u8f91\u540e&#xff0c;\u518d\u5207\u6362\u3002<\/li>\n<\/ul>\n<h3>7. \u4e3b\u9898\u4e0e\u8bbe\u5907 MAC \u7684\u5bf9\u5e94\u5173\u7cfb<\/h3>\n<p>\u5efa\u8bae\u6309\u8bbe\u5907 MAC \u89c4\u5212\u4e3b\u9898&#xff0c;\u4fbf\u4e8e\u591a\u8bbe\u5907\u7ba1\u7406&#xff1a;<\/p>\n<p>gemeopen\/gspm1b\/&lt;mac&gt;\/report     # \u8bbe\u5907\u4e0a\u62a5&#xff08;\u4f60\u8ba2\u9605&#xff09;<br \/>\ngemeopen\/gspm1b\/&lt;mac&gt;\/command    # \u8bbe\u5907\u6307\u4ee4&#xff08;\u4f60\u53d1\u5e03&#xff09;<\/p>\n<p>\u540e\u7aef\u7684 MQTT_REPORT_TOPIC \u9ed8\u8ba4\u7528\u901a\u914d\u7b26 gemeopen\/gspm1b\/&#043;\/report&#xff0c;\u53ef\u540c\u65f6\u63a5\u6536\u591a\u53f0\u8bbe\u5907\u3002<\/p>\n<hr \/>\n<h4>03-homeassistant.md<\/h4>\n<h2>03 \u00b7 Home Assistant \u63a5\u5165<\/h2>\n<p>\u9762\u5411\u521d\u5b66\u8005&#xff0c;\u4ece\u96f6\u628a GSPM1B \u63a5\u5165 Home Assistant&#xff0c;\u5b9e\u73b0\u901a\u65ad\u7535\u63a7\u5236 &#043; \u5b9e\u65f6\u7535\u6d41\/\u7535\u538b\/\u529f\u7387\u91c7\u96c6 &#043; \u7d2f\u8ba1\u7528\u7535\u91cf\u3002<\/p>\n<h3>1. \u6574\u4f53\u601d\u8def&#xff08;\u5148\u770b\u8fd9\u5f20\u56fe&#xff09;<\/h3>\n<p>GSPM1B \u2500\u2500MQTT\u2500\u2500\u25ba Mosquitto Broker \u25c4\u2500\u2500MQTT\u2500\u2500 Home Assistant<br \/>\n   (\u8bbe\u5907)          (\u4f60\u7684\u670d\u52a1\u5668)               (MQTT \u96c6\u6210)<\/p>\n<p>Home Assistant \u901a\u8fc7 MQTT \u96c6\u6210\u8fde\u63a5\u4f60\u7684 Mosquitto&#xff0c;\u518d\u7528\u4e00\u4efd YAML \u628a\u8bbe\u5907\u6d88\u606f\u6620\u5c04\u6210\u5b9e\u4f53&#xff1a;<\/p>\n<ul>\n<li>switch&#xff08;\u5f00\u5173&#xff09;\u2192 \u63a7\u5236\u901a\u65ad\u7535<\/li>\n<li>sensor&#xff08;\u4f20\u611f\u5668&#xff09;\u2192 \u7535\u538b \/ \u7535\u6d41 \/ \u529f\u7387 \/ \u7d2f\u8ba1\u7528\u7535\u91cf \/ \u4fe1\u53f7<\/li>\n<\/ul>\n<h3>2. \u524d\u7f6e\u6761\u4ef6<\/h3>\n<table>\n<tr>\u9879\u8981\u6c42<\/tr>\n<tbody>\n<tr>\n<td>Home Assistant<\/td>\n<td>\u4efb\u610f\u5b89\u88c5\u65b9\u5f0f&#xff08;HAOS \/ Docker \/ Supervised \/ Core&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>MQTT Broker<\/td>\n<td>Mosquitto&#xff08;\u672c\u5de5\u7a0b mosquitto\/ &#043; docker-compose.yml \u5df2\u63d0\u4f9b&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u8bbe\u5907<\/td>\n<td>GSPM1B \u5df2\u6309 [02 \u00b7 \u8bbe\u5907\u7aef\u914d\u7f6e] 02-device-setup.md \u6307\u5411\u4f60\u7684 Broker<\/td>\n<\/tr>\n<tr>\n<td>\u8bbe\u5907 MAC<\/td>\n<td>\u540e\u9762\u914d\u7f6e\u4e2d\u6240\u6709 &lt;MAC&gt; \u90fd\u8981\u66ff\u6362\u6210\u5b83<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>3. \u6b65\u9aa4\u4e00&#xff1a;\u51c6\u5907 Mosquitto Broker<\/h3>\n<h4>3.1 \u7528\u672c\u5de5\u7a0b\u4e00\u952e\u542f\u52a8&#xff08;\u63a8\u8350&#xff09;<\/h4>\n<p><span class=\"token builtin class-name\">cd<\/span> gemeopen-ha-demo<br \/>\n<span class=\"token function\">docker<\/span> compose up <span class=\"token parameter variable\">-d<\/span> mosquitto<\/p>\n<h4>3.2 \u6216\u4f7f\u7528 Home Assistant OS \u7684\u5b98\u65b9 Add-on<\/h4>\n<p>\u8bbe\u7f6e \u2192 \u52a0\u8f7d\u9879 \u2192 \u641c\u7d22 Mosquitto broker \u2192 \u5b89\u88c5 \u2192 \u542f\u52a8\u3002<\/p>\n<p>\u7528\u54ea\u79cd\u90fd\u884c&#xff0c;\u53ea\u8981\u8bbe\u5907\u3001HA \u90fd\u8fde\u540c\u4e00\u4e2a Broker\u3002<\/p>\n<h3>4. \u6b65\u9aa4\u4e8c&#xff1a;\u5728 HA \u4e2d\u6dfb\u52a0 MQTT \u96c6\u6210<\/h3>\n<li>\u8bbe\u7f6e \u2192 \u8bbe\u5907\u4e0e\u670d\u52a1 \u2192 \u6dfb\u52a0\u96c6\u6210 \u2192 \u641c\u7d22 MQTT&#xff1b;<\/li>\n<li>Broker \u586b mosquitto \u7684\u5730\u5740&#xff08;Docker \u573a\u666f\u586b\u5bbf\u4e3b\u673a IP&#xff0c;\u5982 192.168.1.10&#xff09;\u3001\u7aef\u53e3 1883&#xff1b;<\/li>\n<li>\u586b\u5165 Mosquitto \u7684\u7528\u6237\u540d\/\u5bc6\u7801&#xff08;\u89c1 mosquitto\/mosquitto.conf \u4e0e docker-compose.yml&#xff09;&#xff1b;<\/li>\n<li>\u63d0\u4ea4&#xff0c;\u96c6\u6210\u663e\u793a\u201c\u5df2\u8fde\u63a5\u201d\u3002<\/li>\n<h3>5. \u6b65\u9aa4\u4e09&#xff1a;\u6dfb\u52a0\u5b9e\u4f53\u914d\u7f6e<\/h3>\n<li>\u628a\u672c\u5de5\u7a0b\u7684 homeassistant\/mqtt-gspm1b.yaml \u590d\u5236\u5230 HA \u914d\u7f6e\u76ee\u5f55&#xff08;\u4e0e configuration.yaml \u540c\u7ea7&#xff09;&#xff1b;<\/li>\n<li>\u7f16\u8f91 mqtt-gspm1b.yaml&#xff0c;\u628a \u6240\u6709 &lt;MAC&gt; \u66ff\u6362\u4e3a\u4f60\u7684\u8bbe\u5907 MAC&#xff08;\u5c0f\u5199&#xff0c;\u4f8b\u5982 28372fcbbbb8&#xff09;&#xff1b;<\/li>\n<li>\u5728 configuration.yaml \u4e2d\u52a0\u5165\u4e00\u884c&#xff1a;<\/li>\n<p><span class=\"token key atrule\">mqtt<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token tag\">!include<\/span> mqtt<span class=\"token punctuation\">&#8211;<\/span>gspm1b.yaml<\/p>\n<li>\u5f00\u53d1\u8005\u5de5\u5177 \u2192 YAML \u2192 \u68c0\u67e5\u914d\u7f6e \u2192 \u91cd\u542f HA\u3002<\/li>\n<p>\u5982\u679c\u4f60\u66f4\u719f\u6089 UI&#xff1a;\u4e5f\u53ef\u5728\u8bbe\u7f6e \u2192 \u8bbe\u5907\u4e0e\u670d\u52a1 \u2192 MQTT \u2192 \u901a\u8fc7\u201c\u6dfb\u52a0\u5b9e\u4f53\u201d\u9010\u4e2a\u6dfb\u52a0&#xff0c;\u53c2\u6570\u4e0e YAML \u4e00\u81f4\u3002<\/p>\n<h3>6. \u6b65\u9aa4\u56db&#xff1a;\u9a8c\u8bc1\u5b9e\u4f53<\/h3>\n<p>\u91cd\u542f\u540e&#xff0c;\u8bbe\u7f6e \u2192 \u8bbe\u5907\u4e0e\u670d\u52a1 \u2192 \u5b9e\u4f53&#xff0c;\u5e94\u80fd\u770b\u5230&#xff1a;<\/p>\n<table>\n<tr>\u5b9e\u4f53 ID\u7c7b\u578b\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>switch.gspm1b_switch<\/td>\n<td>switch<\/td>\n<td>\u901a\u65ad\u7535\u5f00\u5173<\/td>\n<\/tr>\n<tr>\n<td>sensor.gspm1b_voltage<\/td>\n<td>sensor<\/td>\n<td>\u7535\u538b (V)<\/td>\n<\/tr>\n<tr>\n<td>sensor.gspm1b_current<\/td>\n<td>sensor<\/td>\n<td>\u7535\u6d41 (A)<\/td>\n<\/tr>\n<tr>\n<td>sensor.gspm1b_power<\/td>\n<td>sensor<\/td>\n<td>\u529f\u7387 (W)<\/td>\n<\/tr>\n<tr>\n<td>sensor.gspm1b_energy<\/td>\n<td>sensor<\/td>\n<td>\u7d2f\u8ba1\u7528\u7535\u91cf (kWh)<\/td>\n<\/tr>\n<tr>\n<td>sensor.gspm1b_signal<\/td>\n<td>sensor<\/td>\n<td>\u4fe1\u53f7\u5f3a\u5ea6 (dBm)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6d4b\u8bd5&#xff1a;<\/p>\n<ul>\n<li>\u70b9 switch.gspm1b_switch \u5f00\/\u5173&#xff0c;\u89c2\u5bdf\u5b9e\u7269\u63d2\u5ea7\u7ee7\u7535\u5668\u662f\u5426\u52a8\u4f5c&#xff1b;<\/li>\n<li>\u82e5\u4f20\u611f\u5668\u6570\u503c\u4e3a\u201c\u672a\u77e5\u201d&#xff0c;\u8bf4\u660e\u8bbe\u5907\u8fd8\u6ca1\u4e0a\u62a5\u2014\u2014\u68c0\u67e5&#xff1a;\n<li>\u8bbe\u5907\u662f\u5426\u5df2\u5207\u6362\u5230\u8be5 Broker&#xff08;\u89c1 02 \u6587\u6863&#xff09;&#xff1b;<\/li>\n<li>\u662f\u5426\u5df2\u5f00\u542f\u5b9a\u65f6\u4e0a\u62a5&#xff08;\u89c1\u4e0b\u8282&#xff09;\u3002<\/li>\n<\/li>\n<\/ul>\n<h3>7. \u6b65\u9aa4\u4e94&#xff1a;\u5f00\u542f\u8bbe\u5907\u5b9a\u65f6\u4e0a\u62a5&#xff08;\u8ba9\u4f20\u611f\u5668\u6301\u7eed\u66f4\u65b0&#xff09;<\/h3>\n<p>\u8bbe\u5907\u9ed8\u8ba4\u53ef\u80fd\u4e0d\u4e3b\u52a8\u6c47\u62a5\u3002\u7ed9\u5b83\u4e0b\u53d1\u4e00\u6b21\u201c\u8bbe\u7f6e\u4e0a\u62a5\u9891\u7387\u201d\u6307\u4ee4\u5373\u53ef&#xff08;\u793a\u4f8b\u95f4\u9694 15 \u79d2&#xff09;&#xff1a;<\/p>\n<p>mosquitto_pub <span class=\"token parameter variable\">-h<\/span> <span class=\"token number\">192.168<\/span>.1.10 <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token parameter variable\">-u<\/span> device <span class=\"token parameter variable\">-P<\/span> device-pass <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-t<\/span> <span class=\"token string\">&#039;gemeopen\/gspm1b\/28372fcbbbb8\/command&#039;<\/span> <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-m<\/span> <span class=\"token string\">&#039;{&#034;messageId&#034;:&#034;1&#034;,&#034;timerEnable&#034;:1,&#034;timerInterval&#034;:15,&#034;type&#034;:&#034;setting&#034;}&#039;<\/span><\/p>\n<p>\u4e4b\u540e report \u4e3b\u9898\u4f1a\u6bcf 15 \u79d2\u6536\u5230\u4e00\u6761 device-timer-task&#xff0c;HA \u4f20\u611f\u5668\u968f\u4e4b\u66f4\u65b0\u3002<\/p>\n<h3>8. \u6b65\u9aa4\u516d&#xff1a;\u6dfb\u52a0\u4eea\u8868\u76d8<\/h3>\n<li>\u8bbe\u7f6e \u2192 \u4eea\u8868\u76d8 \u2192 \u65b0\u5efa\u4eea\u8868\u76d8&#xff08;\u6807\u9898\u5982\u201c\u667a\u80fd\u63d2\u5ea7\u201d&#xff09;&#xff1b;<\/li>\n<li>\u6253\u5f00\u5b83 \u2192 \u53f3\u4e0a\u89d2\u7f16\u8f91 \u2192 \u6dfb\u52a0\u5361\u7247&#xff0c;\u6309 homeassistant\/dashboard.yaml \u7684\u5185\u5bb9\u6dfb\u52a0&#xff1a;\n<ul>\n<li>\u5f00\u5173&#xff1a;Entities \u5361\u7247 \u2192 switch.gspm1b_switch<\/li>\n<li>\u7535\u538b\/\u7535\u6d41&#xff1a;Gauge \u5361\u7247<\/li>\n<li>\u529f\u7387\/\u7535\u91cf&#xff1a;Sensor \u5361\u7247&#xff08;\u5e26\u8ff7\u4f60\u66f2\u7ebf&#xff09;<\/li>\n<li>\u5386\u53f2&#xff1a;History graph \u5361\u7247<\/li>\n<\/ul>\n<\/li>\n<p>\u4e5f\u53ef\u76f4\u63a5\u628a dashboard.yaml \u7684\u5185\u5bb9\u7c98\u8d34\u5230\u201c\u539f\u59cb\u914d\u7f6e\u7f16\u8f91\u5668\u201d\u3002<\/p>\n<h3>9. \u6b65\u9aa4\u4e03&#xff08;\u52a0\u5206\u9879&#xff09;&#xff1a;\u80fd\u6e90\u9762\u677f\u4e0e\u81ea\u52a8\u5316<\/h3>\n<p>\u80fd\u6e90\u9762\u677f&#xff1a;\u7d2f\u8ba1\u7528\u7535\u91cf\u5df2\u8bbe device_class: energy &#043; state_class: total_increasing&#xff0c;\u4f1a\u81ea\u52a8\u51fa\u73b0\u5728 \u8bbe\u7f6e \u2192 \u4eea\u8868\u76d8 \u2192 \u80fd\u6e90 \u2192 \u6dfb\u52a0\u7528\u7535\u8bbe\u5907\u3002<\/p>\n<p>\u81ea\u52a8\u5316\u793a\u4f8b&#xff1a;\u529f\u7387\u8d85\u8fc7 2000W \u65f6\u901a\u77e5&#xff08;configuration.yaml \u6216 UI \u81ea\u52a8\u5316&#xff09;&#xff1a;<\/p>\n<p><span class=\"token key atrule\">automation<\/span><span class=\"token punctuation\">:<\/span><br \/>\n  <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token key atrule\">alias<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;GSPM1B \u529f\u7387\u8fc7\u9ad8\u63d0\u9192&#034;<\/span><br \/>\n    <span class=\"token key atrule\">trigger<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token key atrule\">platform<\/span><span class=\"token punctuation\">:<\/span> numeric_state<br \/>\n        <span class=\"token key atrule\">entity_id<\/span><span class=\"token punctuation\">:<\/span> sensor.gspm1b_power<br \/>\n        <span class=\"token key atrule\">above<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">2000<\/span><br \/>\n        <span class=\"token key atrule\">for<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;00:01:00&#034;<\/span><br \/>\n    <span class=\"token key atrule\">action<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token key atrule\">service<\/span><span class=\"token punctuation\">:<\/span> persistent_notification.create<br \/>\n        <span class=\"token key atrule\">data<\/span><span class=\"token punctuation\">:<\/span><br \/>\n          <span class=\"token key atrule\">title<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;\u63d2\u5ea7\u529f\u7387\u8fc7\u9ad8&#034;<\/span><br \/>\n          <span class=\"token key atrule\">message<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;\u5f53\u524d\u529f\u7387 {{ states(&#039;sensor.gspm1b_power&#039;) }} W&#034;<\/span><\/p>\n<p>\u5b9a\u65f6\u65ad\u7535\u793a\u4f8b&#xff1a;<\/p>\n<p>  <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token key atrule\">alias<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;\u6bcf\u5929 23:30 \u81ea\u52a8\u65ad\u7535&#034;<\/span><br \/>\n    <span class=\"token key atrule\">trigger<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token key atrule\">platform<\/span><span class=\"token punctuation\">:<\/span> time<br \/>\n        <span class=\"token key atrule\">at<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;23:30:00&#034;<\/span><br \/>\n    <span class=\"token key atrule\">action<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token key atrule\">service<\/span><span class=\"token punctuation\">:<\/span> switch.turn_off<br \/>\n        <span class=\"token key atrule\">target<\/span><span class=\"token punctuation\">:<\/span><br \/>\n          <span class=\"token key atrule\">entity_id<\/span><span class=\"token punctuation\">:<\/span> switch.gspm1b_switch<\/p>\n<h3>10. \u5e38\u89c1\u95ee\u9898\u901f\u67e5<\/h3>\n<table>\n<tr>\u73b0\u8c61\u6392\u67e5<\/tr>\n<tbody>\n<tr>\n<td>switch \u663e\u793a\u4e0d\u53ef\u7528<\/td>\n<td>command_topic\/state_topic \u91cc\u7684 &lt;MAC&gt; \u662f\u5426\u66ff\u6362\u6b63\u786e&#xff1b;MQTT \u96c6\u6210\u662f\u5426\u8fde\u63a5<\/td>\n<\/tr>\n<tr>\n<td>\u5f00\u5173\u80fd\u70b9\u4f46\u5b9e\u7269\u65e0\u53cd\u5e94<\/td>\n<td>\u8bbe\u5907\u662f\u5426\u5df2\u5207\u5230\u8be5 Broker&#xff1b;command_topic \u662f\u5426\u4e3a\u8bbe\u5907\u7684 subcribe<\/td>\n<\/tr>\n<tr>\n<td>\u4f20\u611f\u5668\u4e00\u76f4\u201c\u672a\u77e5\u201d<\/td>\n<td>\u672a\u5f00\u542f\u5b9a\u65f6\u4e0a\u62a5&#xff1b;\u6216\u8bbe\u5907\u672a\u4e0a\u62a5&#xff1b;\u7528 mosquitto_sub \u6293\u5305\u786e\u8ba4<\/td>\n<\/tr>\n<tr>\n<td>\u6570\u503c\u4e0d\u53d8<\/td>\n<td>\u4e0a\u62a5\u95f4\u9694\u8fc7\u5927&#xff1b;\u6216\u672c\u5730\u7f13\u5b58\u672a\u89e6\u53d1\u4e0a\u62a5<\/td>\n<\/tr>\n<tr>\n<td>\u80fd\u6e90\u9762\u677f\u4e0d\u663e\u793a<\/td>\n<td>\u786e\u8ba4 state_class: total_increasing \u5df2\u751f\u6548\u5e76\u5df2\u4ea7\u751f\u6570\u636e<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u66f4\u591a\u6392\u9519\u89c1 [07 \u00b7 \u6392\u9519\u624b\u518c] 07-troubleshooting.md \u3002<\/p>\n<hr \/>\n<h4>04-backend.md<\/h4>\n<h2>04 \u00b7 Java \u540e\u7aef&#xff08;Spring Boot &#043; MQTT&#xff09;<\/h2>\n<p>\u8def\u5f84 B \u7684\u540e\u7aef&#xff1a;\u8ba2\u9605\u8bbe\u5907 MQTT \u6d88\u606f \u2192 \u5f52\u4e00\u5316 \u2192 \u901a\u8fc7 REST \/ WebSocket \u63d0\u4f9b\u7ed9 Angular \u524d\u7aef\u3002<\/p>\n<h3>1. \u6587\u4ef6\u7ed3\u6784<\/h3>\n<p>backend\/<br \/>\n\u251c\u2500\u2500 pom.xml                      # Maven \u4f9d\u8d56&#xff08;Spring Boot 3.2 &#043; Paho MQTT&#xff09;<br \/>\n\u251c\u2500\u2500 Dockerfile                   # \u591a\u9636\u6bb5&#xff1a;maven \u6784\u5efa \u2192 jre \u8fd0\u884c<br \/>\n\u251c\u2500\u2500 README.md<br \/>\n\u2514\u2500\u2500 src\/main\/<br \/>\n    \u251c\u2500\u2500 resources\/application.yml # \u7aef\u53e3\u4e0e\u5168\u90e8\u73af\u5883\u53d8\u91cf<br \/>\n    \u2514\u2500\u2500 java\/com\/gemeopen\/demo\/<br \/>\n        \u251c\u2500\u2500 GemeOpenApplication.java        # \u542f\u52a8\u7c7b<br \/>\n        \u251c\u2500\u2500 model\/<br \/>\n        \u2502   \u251c\u2500\u2500 DeviceState.java            # \u8bbe\u5907\u72b6\u6001\u5feb\u7167&#xff08;\u5951\u7ea6 5.2&#xff09;<br \/>\n        \u2502   \u251c\u2500\u2500 Sample.java                 # \u5386\u53f2\u91c7\u6837\u70b9&#xff08;\u5951\u7ea6 5.5&#xff09;<br \/>\n        \u2502   \u2514\u2500\u2500 SwitchRequest.java          # \u5f00\u5173\u8bf7\u6c42\u4f53&#xff08;\u5951\u7ea6 5.3&#xff09;<br \/>\n        \u251c\u2500\u2500 store\/DeviceStore.java          # \u7ebf\u7a0b\u5b89\u5168\u72b6\u6001 &#043; \u73af\u5f62\u5386\u53f2<br \/>\n        \u251c\u2500\u2500 mqtt\/MqttClientService.java     # MQTT \u8fde\u63a5\/\u8ba2\u9605\/\u89e3\u6790\/\u4e0b\u53d1<br \/>\n        \u251c\u2500\u2500 ws\/TelemetryWebSocketHandler.java # WebSocket \u5e7f\u64ad<br \/>\n        \u251c\u2500\u2500 config\/<br \/>\n        \u2502   \u251c\u2500\u2500 WebSocketConfig.java        # \u6ce8\u518c \/ws\/telemetry<br \/>\n        \u2502   \u2514\u2500\u2500 CorsConfig.java             # \u8de8\u57df\u914d\u7f6e<br \/>\n        \u2514\u2500\u2500 web\/DeviceController.java       # REST \u7aef\u70b9<\/p>\n<h3>2. \u8fd0\u884c<\/h3>\n<h4>\u672c\u5730&#xff08;\u9700 JDK 17&#043; \u4e0e Maven&#xff09;<\/h4>\n<p><span class=\"token builtin class-name\">cd<\/span> backend<br \/>\nmvn spring-boot:run<br \/>\n<span class=\"token comment\"># \u6216\u6784\u5efa\u540e\u8fd0\u884c<\/span><br \/>\nmvn <span class=\"token parameter variable\">-DskipTests<\/span> package<br \/>\n<span class=\"token function\">java<\/span> <span class=\"token parameter variable\">-jar<\/span> target\/gemeopen-demo.jar<\/p>\n<p>\u53ef\u7528\u73af\u5883\u53d8\u91cf\u8986\u76d6\u914d\u7f6e&#xff08;\u89c1 application.yml&#xff09;&#xff0c;\u4f8b\u5982&#xff1a;<\/p>\n<p><span class=\"token assign-left variable\">MQTT_HOST<\/span><span class=\"token operator\">&#061;<\/span><span class=\"token number\">192.168<\/span>.1.10 <span class=\"token assign-left variable\">DEVICE_MAC<\/span><span class=\"token operator\">&#061;<\/span>28372fcbbbb8 <span class=\"token function\">java<\/span> <span class=\"token parameter variable\">-jar<\/span> target\/gemeopen-demo.jar<\/p>\n<h4>Docker<\/h4>\n<p><span class=\"token function\">docker<\/span> build <span class=\"token parameter variable\">-t<\/span> gemeopen-backend-java .\/backend<br \/>\n<span class=\"token function\">docker<\/span> run <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">&#8211;name<\/span> gemeopen-backend-java <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">8000<\/span>:8000 <span class=\"token punctuation\">\\\\<\/span><br \/>\n  <span class=\"token parameter variable\">-e<\/span> <span class=\"token assign-left variable\">MQTT_HOST<\/span><span class=\"token operator\">&#061;<\/span><span class=\"token number\">192.168<\/span>.1.10 <span class=\"token parameter variable\">-e<\/span> <span class=\"token assign-left variable\">DEVICE_MAC<\/span><span class=\"token operator\">&#061;<\/span>28372fcbbbb8 <span class=\"token punctuation\">\\\\<\/span><br \/>\n  gemeopen-backend-java<\/p>\n<h3>3. API \u4e00\u89c8<\/h3>\n<table>\n<tr>\u65b9\u6cd5\u8def\u5f84\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>GET<\/td>\n<td>\/api\/health<\/td>\n<td>\u670d\u52a1\/Broker\/\u8bbe\u5907\u5728\u7ebf\u72b6\u6001<\/td>\n<\/tr>\n<tr>\n<td>GET<\/td>\n<td>\/api\/device<\/td>\n<td>\u5f53\u524d\u72b6\u6001\u5feb\u7167<\/td>\n<\/tr>\n<tr>\n<td>POST<\/td>\n<td>\/api\/device\/switch<\/td>\n<td>\u901a\u65ad\u7535&#xff0c;body {&#034;on&#034;: true}<\/td>\n<\/tr>\n<tr>\n<td>POST<\/td>\n<td>\/api\/device\/refresh<\/td>\n<td>\u89e6\u53d1\u4e00\u6b21 info &#043; statistic \u67e5\u8be2<\/td>\n<\/tr>\n<tr>\n<td>GET<\/td>\n<td>\/api\/device\/history?limit&#061;200<\/td>\n<td>\u91c7\u6837\u5386\u53f2&#xff08;\u7ed8\u56fe\u7528&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>GET<\/td>\n<td>\/api\/config<\/td>\n<td>\u975e\u654f\u611f\u8fd0\u884c\u914d\u7f6e<\/td>\n<\/tr>\n<tr>\n<td>WS<\/td>\n<td>\/ws\/telemetry<\/td>\n<td>\u5b9e\u65f6\u72b6\u6001\u63a8\u9001<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u5b57\u6bb5\u5b9a\u4e49\u89c1 [00 \u00b7 \u67b6\u6784\u4e0e\u5951\u7ea6] 00-architecture.md \u7b2c 5 \u8282\u3002<\/p>\n<h3>4. \u4ee3\u7801\u5bfc\u8bfb&#xff08;\u91cd\u70b9\u4e09\u5904&#xff09;<\/h3>\n<h4>4.1 MqttClientService&#xff1a;\u8fde\u63a5\u4e0e\u56de\u8c03<\/h4>\n<p>client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MqttClient<\/span><span class=\"token punctuation\">(<\/span>brokerUrl<span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MemoryPersistence<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\nclient<span class=\"token punctuation\">.<\/span><span class=\"token function\">setCallback<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MqttCallbackExtended<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">public<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">connectComplete<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">boolean<\/span> reconnect<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">String<\/span> serverURI<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        client<span class=\"token punctuation\">.<\/span><span class=\"token function\">subscribe<\/span><span class=\"token punctuation\">(<\/span>reportTopic<span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>          <span class=\"token comment\">\/\/ \u8ba2\u9605\u8bbe\u5907\u4e0a\u62a5<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">public<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">messageArrived<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">String<\/span> topic<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">MqttMessage<\/span> msg<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token class-name\">DeviceState<\/span> state <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">normalize<\/span><span class=\"token punctuation\">(<\/span>msg<span class=\"token punctuation\">.<\/span><span class=\"token function\">getPayload<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ \u5f52\u4e00\u5316\u5b57\u6bb5<\/span><br \/>\n        store<span class=\"token punctuation\">.<\/span><span class=\"token function\">update<\/span><span class=\"token punctuation\">(<\/span>state<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                              <span class=\"token comment\">\/\/ \u66f4\u65b0\u72b6\u6001\u4e0e\u5386\u53f2<\/span><br \/>\n        wsHandler<span class=\"token punctuation\">.<\/span><span class=\"token function\">broadcast<\/span><span class=\"token punctuation\">(<\/span>state<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                       <span class=\"token comment\">\/\/ \u63a8\u9001\u7ed9\u524d\u7aef<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<h4>4.2 \u5b57\u6bb5\u5f52\u4e00\u5316<\/h4>\n<table>\n<tr>\u8bbe\u5907\u539f\u59cb\u5b57\u6bb5\u5f52\u4e00\u5316\u5b57\u6bb5\u7c7b\u578b<\/tr>\n<tbody>\n<tr>\n<td>key (0\/1)<\/td>\n<td>relayOn<\/td>\n<td>Boolean<\/td>\n<\/tr>\n<tr>\n<td>voltage<\/td>\n<td>voltageV<\/td>\n<td>Double<\/td>\n<\/tr>\n<tr>\n<td>current<\/td>\n<td>currentA<\/td>\n<td>Double<\/td>\n<\/tr>\n<tr>\n<td>power<\/td>\n<td>activePowerW<\/td>\n<td>Double<\/td>\n<\/tr>\n<tr>\n<td>energy<\/td>\n<td>energyKwh<\/td>\n<td>Double<\/td>\n<\/tr>\n<tr>\n<td>signal<\/td>\n<td>signalDbm<\/td>\n<td>Integer<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>4.3 TelemetryWebSocketHandler&#xff1a;\u5e7f\u64ad<\/h4>\n<p>\u7ef4\u62a4 CopyOnWriteArraySet&lt;WebSocketSession&gt;&#xff0c;\u72b6\u6001\u66f4\u65b0\u65f6\u904d\u5386\u53d1\u9001&#xff1b;\u7531\u4e8e WebSocket \u4e0d\u80fd\u5e76\u53d1\u5199&#xff0c; \u53d1\u9001\u65f6\u7528 synchronized \u52a0\u9501\u4e32\u884c\u5316&#xff1a;<\/p>\n<p><span class=\"token keyword\">public<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">broadcast<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">Object<\/span> payload<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token class-name\">String<\/span> json <span class=\"token operator\">&#061;<\/span> mapper<span class=\"token punctuation\">.<\/span><span class=\"token function\">writeValueAsString<\/span><span class=\"token punctuation\">(<\/span>payload<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token class-name\">TextMessage<\/span> msg <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">TextMessage<\/span><span class=\"token punctuation\">(<\/span>json<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">synchronized<\/span> <span class=\"token punctuation\">(<\/span>sendLock<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token class-name\">WebSocketSession<\/span> s <span class=\"token operator\">:<\/span> sessions<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>s<span class=\"token punctuation\">.<\/span><span class=\"token function\">isOpen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> s<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendMessage<\/span><span class=\"token punctuation\">(<\/span>msg<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h3>5. \u4e8c\u6b21\u5f00\u53d1\u5efa\u8bae<\/h3>\n<li>\u6301\u4e45\u5316&#xff1a;\u628a DeviceStore \u7684\u5185\u5b58\u5386\u53f2\u6362\u6210 JPA &#043; PostgreSQL \/ InfluxDB&#xff1b;<\/li>\n<li>\u591a\u8bbe\u5907&#xff1a;MQTT_REPORT_TOPIC \u5df2\u7528 &#043; \u901a\u914d&#xff0c;\u53ef\u6309 MAC \u5efa\u7acb Map&lt;String, DeviceState&gt;&#xff1b;<\/li>\n<li>\u9274\u6743&#xff1a;\u5f15\u5165 Spring Security&#xff0c;\u4e3a\u524d\u7aef\u63a5\u53e3\u52a0 Token&#xff1b;<\/li>\n<li>\u914d\u7f6e\u5316\u9608\u503c&#xff1a;\u65b0\u589e\u544a\u8b66\u670d\u52a1&#xff0c;\u5bf9\u529f\u7387\/\u7535\u91cf\u505a\u8d8a\u9650\u56de\u8c03\u3002<\/li>\n<hr \/>\n<h4>05-frontend.md<\/h4>\n<h2>05 \u00b7 Angular \u524d\u7aef&#xff08;Angular 17&#xff09;<\/h2>\n<p>\u8def\u5f84 B \u7684\u524d\u7aef&#xff1a;\u5c55\u793a\u5b9e\u65f6\u7535\u538b\/\u7535\u6d41\/\u529f\u7387\/\u7d2f\u8ba1\u7535\u91cf&#xff0c;\u5e76\u63d0\u4f9b\u901a\u65ad\u7535\u5f00\u5173\u3002<\/p>\n<h3>1. \u6587\u4ef6\u7ed3\u6784<\/h3>\n<p>frontend\/<br \/>\n\u251c\u2500\u2500 package.json                 # \u4f9d\u8d56\u4e0e\u811a\u672c<br \/>\n\u251c\u2500\u2500 angular.json                 # \u6784\u5efa\u914d\u7f6e&#xff08;\u542b env \u66ff\u6362\u3001dev \u4ee3\u7406&#xff09;<br \/>\n\u251c\u2500\u2500 tsconfig.json \/ tsconfig.app.json<br \/>\n\u251c\u2500\u2500 proxy.conf.json              # \u5f00\u53d1\u4ee3\u7406 \/api\u3001\/ws \u2192 localhost:8000<br \/>\n\u251c\u2500\u2500 Dockerfile                   # \u591a\u9636\u6bb5&#xff1a;ng build \u2192 nginx<br \/>\n\u251c\u2500\u2500 nginx.conf                   # \u6258\u7ba1 dist &#043; \u53cd\u4ee3 \/api\u3001\/ws<br \/>\n\u251c\u2500\u2500 README.md<br \/>\n\u2514\u2500\u2500 src\/<br \/>\n    \u251c\u2500\u2500 index.html<br \/>\n    \u251c\u2500\u2500 main.ts                  # bootstrapApplication(AppComponent)<br \/>\n    \u251c\u2500\u2500 styles.css               # \u5168\u5c40\u6df1\u8272\u4e3b\u9898<br \/>\n    \u251c\u2500\u2500 environments\/<br \/>\n    \u2502   \u251c\u2500\u2500 environment.ts       # apiBase: http:\/\/localhost:8000&#xff08;\u5f00\u53d1&#xff09;<br \/>\n    \u2502   \u2514\u2500\u2500 environment.prod.ts  # apiBase: &#039;&#039;&#xff08;\u751f\u4ea7\u540c\u6e90&#xff0c;\u8d70 Nginx \u53cd\u4ee3&#xff09;<br \/>\n    \u2514\u2500\u2500 app\/<br \/>\n        \u251c\u2500\u2500 app.config.ts        # provideHttpClient()<br \/>\n        \u251c\u2500\u2500 app.component.ts\/.html\/.css   # \u6839\u5e03\u5c40<br \/>\n        \u251c\u2500\u2500 models\/device-state.ts        # \u7c7b\u578b\u4e0e\u7a7a\u503c\u515c\u5e95<br \/>\n        \u251c\u2500\u2500 services\/<br \/>\n        \u2502   \u251c\u2500\u2500 api.service.ts            # REST \u5c01\u88c5<br \/>\n        \u2502   \u2514\u2500\u2500 telemetry.service.ts      # \u72b6\u6001\u6d41&#xff1a;REST &#043; WebSocket &#043; \u964d\u7ea7\u8f6e\u8be2<br \/>\n        \u2514\u2500\u2500 components\/<br \/>\n            \u251c\u2500\u2500 switch-control\/           # \u901a\u65ad\u7535\u5f00\u5173<br \/>\n            \u251c\u2500\u2500 realtime-metrics\/         # \u7535\u538b\/\u7535\u6d41\/\u529f\u7387\/\u4fe1\u53f7<br \/>\n            \u251c\u2500\u2500 energy-total\/             # \u7d2f\u8ba1\u7528\u7535\u91cf<br \/>\n            \u2514\u2500\u2500 history-chart\/            # \u539f\u751f SVG \u6298\u7ebf\u56fe<\/p>\n<h3>2. \u8fd0\u884c<\/h3>\n<p><span class=\"token builtin class-name\">cd<\/span> frontend<br \/>\n<span class=\"token function\">npm<\/span> <span class=\"token function\">install<\/span><br \/>\n<span class=\"token function\">npm<\/span> start            <span class=\"token comment\"># http:\/\/localhost:4200&#xff08;\u81ea\u52a8\u5e26 proxy.conf.json \u4ee3\u7406\u5230 8000&#xff09;<\/span><br \/>\n<span class=\"token function\">npm<\/span> run build        <span class=\"token comment\"># \u751f\u4ea7\u6784\u5efa&#xff0c;\u4ea7\u7269\u5728 dist\/frontend\/browser\/<\/span><\/p>\n<h3>3. \u6570\u636e\u6d41\u4e0e\u5b9e\u65f6\u66f4\u65b0<\/h3>\n<p>\u6838\u5fc3\u5728 telemetry.service.ts&#xff1a;<\/p>\n<li>\u7528 BehaviorSubject&lt;DeviceState&gt; \u7ef4\u62a4\u72b6\u6001\u6d41 state$&#xff1b;<\/li>\n<li>\u9996\u5c4f GET \/api\/device \u53d6\u521d\u503c&#xff1b;<\/li>\n<li>\u8fde\u63a5 WebSocket \/ws\/telemetry&#xff0c;\u6bcf\u5e27\u66f4\u65b0 state$&#xff1b;<\/li>\n<li>\u65ad\u7ebf\u6307\u6570\u9000\u907f\u91cd\u8fde&#xff08;1s\u219230s \u5c01\u9876&#xff09;&#xff1b;<\/li>\n<li>WebSocket \u8fde\u7eed\u5931\u8d25\u5219\u964d\u7ea7\u4e3a 5 \u79d2\u8f6e\u8be2&#xff0c;\u6062\u590d\u540e\u81ea\u52a8\u505c\u6b62\u8f6e\u8be2\u3002<\/li>\n<p>\u7ec4\u4ef6\u901a\u8fc7 state$ | async \u8ba2\u9605&#xff0c;\u81ea\u52a8\u968f\u6570\u636e\u5237\u65b0\u3002<\/p>\n<h3>4. \u754c\u9762\u6784\u6210<\/h3>\n<table>\n<tr>\u533a\u57df\u7ec4\u4ef6\u5185\u5bb9<\/tr>\n<tbody>\n<tr>\n<td>\u9876\u90e8<\/td>\n<td>AppComponent<\/td>\n<td>\u6807\u9898\u3001\u8bbe\u5907\u5728\u7ebf\u5fbd\u6807\u3001\u8fde\u63a5\u72b6\u6001&#xff08;\u5b9e\u65f6\/\u8f6e\u8be2\/\u65ad\u5f00&#xff09;\u3001\u6700\u540e\u66f4\u65b0\u65f6\u95f4\u3001\u5237\u65b0\u6309\u94ae<\/td>\n<\/tr>\n<tr>\n<td>\u63a7\u5236<\/td>\n<td>SwitchControl<\/td>\n<td>\u901a\u7535\/\u65ad\u7535\u5f00\u5173&#xff08;\u8bf7\u6c42\u4e2d\u6001\u3001\u79bb\u7ebf\u7981\u7528\u3001\u9519\u8bef\u63d0\u793a&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u6307\u6807<\/td>\n<td>RealtimeMetrics<\/td>\n<td>\u7535\u538b V \/ \u7535\u6d41 A \/ \u529f\u7387 W \/ \u4fe1\u53f7 dBm<\/td>\n<\/tr>\n<tr>\n<td>\u7535\u91cf<\/td>\n<td>EnergyTotal<\/td>\n<td>\u7d2f\u8ba1\u7528\u7535\u91cf kWh<\/td>\n<\/tr>\n<tr>\n<td>\u8d8b\u52bf<\/td>\n<td>HistoryChart<\/td>\n<td>\u539f\u751f SVG \u53cc\u7ebf\u6298\u7ebf&#xff08;\u7535\u538b &#043; \u529f\u7387&#xff09;&#xff0c;\u542b\u7f51\u683c\u4e0e\u8303\u56f4\u7edf\u8ba1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>5. \u914d\u7f6e<\/h3>\n<table>\n<tr>\u73af\u5883API \u5730\u5740\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>\u5f00\u53d1<\/td>\n<td>http:\/\/localhost:8000<\/td>\n<td>\u4e5f\u53ef\u8d70 proxy.conf.json \u4ee3\u7406<\/td>\n<\/tr>\n<tr>\n<td>\u751f\u4ea7\u6784\u5efa<\/td>\n<td>&#039;&#039;&#xff08;\u540c\u6e90&#xff09;<\/td>\n<td>\u7531 nginx.conf \u628a \/api\u3001\/ws \u53cd\u4ee3\u5230 backend:8000<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6539\u540e\u7aef\u5730\u5740&#xff1a;\u7f16\u8f91 src\/environments\/environment.ts\u3002<\/p>\n<h3>6. \u6784\u5efa\u4e0e\u90e8\u7f72<\/h3>\n<p><span class=\"token function\">npm<\/span> run build<br \/>\n<span class=\"token comment\"># \u4ea7\u7269&#xff1a;dist\/frontend\/browser\/<\/span><\/p>\n<p><span class=\"token comment\"># Docker<\/span><br \/>\n<span class=\"token function\">docker<\/span> build <span class=\"token parameter variable\">-t<\/span> gemeopen-frontend-angular .\/frontend<br \/>\n<span class=\"token function\">docker<\/span> run <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">8080<\/span>:80 gemeopen-frontend-angular<\/p>\n<h3>7. \u4e8c\u6b21\u5f00\u53d1\u5efa\u8bae<\/h3>\n<li>\u6362 UI \u7ec4\u4ef6\u5e93&#xff1a;\u53ef\u63a5\u5165 Angular Material \/ PrimeNG&#xff1b;<\/li>\n<li>\u52a0\u8def\u7531&#xff1a;app.routes.ts \u62c6\u51fa\u300c\u5b9e\u65f6\u300d\u300c\u5386\u53f2\u300d\u300c\u8bbe\u7f6e\u300d\u591a\u9875&#xff1b;<\/li>\n<li>\u591a\u8bbe\u5907&#xff1a;\u9876\u90e8\u52a0\u8bbe\u5907\u5207\u6362&#xff0c;\u6309 MAC \u4f20\u53c2&#xff1b;<\/li>\n<li>\u544a\u8b66&#xff1a;\u8ba2\u9605\u540e\u7aef\u544a\u8b66\u6d41&#xff0c;\u505a Toast\/\u58f0\u97f3\u63d0\u793a\u3002<\/li>\n<hr \/>\n<h4>06-deploy-ops.md<\/h4>\n<h2>06 \u00b7 \u90e8\u7f72\u4e0e\u8fd0\u7ef4<\/h2>\n<p>\u8986\u76d6 \u672c\u5730\u5f00\u53d1 \u2192 Docker \u90e8\u7f72 \u2192 \u751f\u4ea7\u5efa\u8bae&#xff0c;\u4ee5\u53ca\u65e5\u5e38\u8fd0\u7ef4\u64cd\u4f5c\u3002<\/p>\n<h3>1. \u90e8\u7f72\u65b9\u5f0f\u603b\u89c8<\/h3>\n<table>\n<tr>\u65b9\u5f0f\u9002\u7528\u573a\u666f\u96be\u5ea6\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>A. \u672c\u5730\u5f00\u53d1<\/td>\n<td>\u5b66\u4e60\/\u8c03\u8bd5<\/td>\n<td>\u2605<\/td>\n<td>\u624b\u52a8\u8d77 Broker &#043; Java \u540e\u7aef &#043; Angular \u524d\u7aef<\/td>\n<\/tr>\n<tr>\n<td>B. Docker Compose<\/td>\n<td>\u5feb\u901f\u4e0a\u7ebf<\/td>\n<td>\u2605\u2605<\/td>\n<td>\u4e00\u6761\u547d\u4ee4\u8d77\u5168\u5957&#xff08;\u63a8\u8350&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>C. \u751f\u4ea7\u90e8\u7f72<\/td>\n<td>\u957f\u671f\u8fd0\u884c<\/td>\n<td>\u2605\u2605\u2605<\/td>\n<td>\u5bc6\u7801\u8ba4\u8bc1 &#043; HTTPS &#043; \u81ea\u52a8\u542f\u52a8 &#043; \u5907\u4efd<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>2. \u65b9\u5f0f A&#xff1a;\u672c\u5730\u5f00\u53d1<\/h3>\n<h4>2.1 \u542f\u52a8 MQTT Broker<\/h4>\n<p><span class=\"token builtin class-name\">cd<\/span> gemeopen-ha-java-demo<br \/>\n<span class=\"token function\">docker<\/span> compose up <span class=\"token parameter variable\">-d<\/span> mosquitto<\/p>\n<h4>2.2 \u542f\u52a8 Java \u540e\u7aef&#xff08;JDK 17&#043; \/ Maven&#xff09;<\/h4>\n<p><span class=\"token builtin class-name\">cd<\/span> backend<br \/>\nmvn spring-boot:run<br \/>\n<span class=\"token comment\"># \u6216<\/span><br \/>\nmvn <span class=\"token parameter variable\">-DskipTests<\/span> package <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">java<\/span> <span class=\"token parameter variable\">-jar<\/span> target\/gemeopen-demo.jar<\/p>\n<p>\u7528\u73af\u5883\u53d8\u91cf\u8986\u76d6\u914d\u7f6e&#xff1a;<\/p>\n<p><span class=\"token assign-left variable\">MQTT_HOST<\/span><span class=\"token operator\">&#061;<\/span><span class=\"token number\">192.168<\/span>.1.10 <span class=\"token assign-left variable\">DEVICE_MAC<\/span><span class=\"token operator\">&#061;<\/span>28372fcbbbb8 <span class=\"token function\">java<\/span> <span class=\"token parameter variable\">-jar<\/span> target\/gemeopen-demo.jar<\/p>\n<p>\u5065\u5eb7\u68c0\u67e5&#xff1a;curl http:\/\/localhost:8000\/api\/health \u63a5\u53e3\u6587\u6863&#xff08;\u5982\u542f\u7528&#xff09;&#xff1a;http:\/\/localhost:8000\/api\/device<\/p>\n<h4>2.3 \u542f\u52a8 Angular \u524d\u7aef&#xff08;Node 18&#043;&#xff09;<\/h4>\n<p><span class=\"token builtin class-name\">cd<\/span> frontend<br \/>\n<span class=\"token function\">npm<\/span> <span class=\"token function\">install<\/span><br \/>\n<span class=\"token function\">npm<\/span> start          <span class=\"token comment\"># http:\/\/localhost:4200&#xff08;\u5df2\u914d\u7f6e\u4ee3\u7406\u5230 8000&#xff09;<\/span><\/p>\n<hr \/>\n<h3>3. \u65b9\u5f0f B&#xff1a;Docker Compose&#xff08;\u63a8\u8350&#xff09;<\/h3>\n<h4>3.1 \u524d\u7f6e<\/h4>\n<ul>\n<li>\u5b89\u88c5 Docker \u4e0e Docker Compose \u63d2\u4ef6&#xff1b;<\/li>\n<li>\u4fee\u6539 docker-compose.yml \u4e2d DEVICE_MAC \u4e3a\u4f60\u7684\u8bbe\u5907 MAC\u3002<\/li>\n<\/ul>\n<h4>3.2 \u542f\u52a8<\/h4>\n<p><span class=\"token builtin class-name\">cd<\/span> gemeopen-ha-java-demo<br \/>\n<span class=\"token function\">docker<\/span> compose up <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">&#8211;build<\/span><br \/>\n<span class=\"token function\">docker<\/span> compose <span class=\"token function\">ps<\/span><\/p>\n<table>\n<tr>\u670d\u52a1\u5730\u5740<\/tr>\n<tbody>\n<tr>\n<td>Mosquitto<\/td>\n<td>mqtt:\/\/&lt;\u5bbf\u4e3b\u673aIP&gt;:1883<\/td>\n<\/tr>\n<tr>\n<td>Java \u540e\u7aef API<\/td>\n<td>http:\/\/localhost:8000\/api\/health<\/td>\n<\/tr>\n<tr>\n<td>Angular \u524d\u7aef<\/td>\n<td>http:\/\/localhost:8080<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>3.3 \u5173\u952e&#xff1a;\u8ba9\u8bbe\u5907\u80fd\u8bbf\u95ee\u5230 Broker<\/h4>\n<p>\u8bbe\u5907\u7aef setting-mqtt \u91cc\u7684 Broker \u5730\u5740\u5fc5\u987b\u586b \u5bbf\u4e3b\u673a\u5c40\u57df\u7f51 IP&#xff08;\u5982 192.168.1.10&#xff09;&#xff0c; \u4e0d\u80fd\u7528 localhost \/ mosquitto&#xff08;\u90a3\u662f\u5bb9\u5668\u5185\u90e8\u5730\u5740&#xff09;\u3002\u5e76\u786e\u8ba4\u9632\u706b\u5899\u653e\u884c 1883\u3002<\/p>\n<hr \/>\n<h3>4. \u65b9\u5f0f C&#xff1a;\u751f\u4ea7\u73af\u5883\u5efa\u8bae<\/h3>\n<h4>4.1 \u542f\u7528 Broker \u5bc6\u7801\u8ba4\u8bc1<\/h4>\n<p>\u6309 mosquitto\/mosquitto.conf \u672b\u5c3e\u8bf4\u660e\u751f\u6210 passwd \u5e76\u5f00\u542f\u8ba4\u8bc1&#xff0c;\u7136\u540e\u540c\u6b65\u66f4\u65b0&#xff1a; \u8bbe\u5907 setting-mqtt\u3001HA MQTT \u96c6\u6210\u3001\u540e\u7aef MQTT_USERNAME\/MQTT_PASSWORD\u3002<\/p>\n<h4>4.2 \u5b89\u5168\u6e05\u5355<\/h4>\n<ul>\n<li class=\"task-list-item\"> \u5173\u95ed\u533f\u540d\u8bbf\u95ee&#xff1b;\u8bbe\u5907\/HA\/\u540e\u7aef\u4f7f\u7528\u72ec\u7acb\u8d26\u53f7<\/li>\n<li class=\"task-list-item\"> MQTT \u7aef\u53e3\u4e0d\u66b4\u9732\u516c\u7f51&#xff1b;\u8fdc\u7a0b\u7528 VPN \u6216 TLS(8883)<\/li>\n<li class=\"task-list-item\"> \u524d\u7aef\u5bf9\u5916 HTTPS&#xff08;Nginx\/Caddy \u53cd\u4ee3 &#043; \u8bc1\u4e66&#xff09;<\/li>\n<li class=\"task-list-item\"> \u540e\u7aef CORS_ORIGINS \u7531 * \u6536\u7d27\u4e3a\u4f60\u7684\u57df\u540d<\/li>\n<li class=\"task-list-item\"> \u5bc6\u94a5\u7528\u73af\u5883\u53d8\u91cf\/\u5bc6\u94a5\u7ba1\u7406&#xff0c;\u4e0d\u5165\u5e93\u4e0d\u5165\u4ee3\u7801<\/li>\n<\/ul>\n<h4>4.3 \u5f00\u673a\u81ea\u542f<\/h4>\n<ul>\n<li>Docker&#xff1a;restart: unless-stopped \u5df2\u914d\u7f6e&#xff1b;<\/li>\n<li>\u88f8\u673a\u540e\u7aef\u7528 systemd&#xff1a;<\/li>\n<\/ul>\n<p># \/etc\/systemd\/system\/gemeopen-backend.service<br \/>\n[Unit]<br \/>\nDescription&#061;GemeOpen Java Backend<br \/>\nAfter&#061;network.target mosquitto.service<br \/>\n[Service]<br \/>\nWorkingDirectory&#061;\/opt\/gemeopen-ha-java-demo\/backend<br \/>\nExecStart&#061;\/usr\/bin\/java -jar \/opt\/gemeopen-ha-java-demo\/backend\/target\/gemeopen-demo.jar<br \/>\nEnvironment&#061;MQTT_HOST&#061;192.168.1.10<br \/>\nEnvironment&#061;DEVICE_MAC&#061;28372fcbbbb8<br \/>\nRestart&#061;always<br \/>\n[Install]<br \/>\nWantedBy&#061;multi-user.target<\/p>\n<p><span class=\"token function\">sudo<\/span> systemctl daemon-reload <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">sudo<\/span> systemctl <span class=\"token builtin class-name\">enable<\/span> <span class=\"token parameter variable\">&#8211;now<\/span> gemeopen-backend<\/p>\n<hr \/>\n<h3>5. \u65e5\u5e38\u8fd0\u7ef4<\/h3>\n<h4>5.1 \u770b\u65e5\u5fd7<\/h4>\n<p><span class=\"token function\">docker<\/span> compose logs <span class=\"token parameter variable\">-f<\/span> backend<br \/>\n<span class=\"token function\">docker<\/span> compose logs <span class=\"token parameter variable\">-f<\/span> mosquitto<br \/>\n<span class=\"token function\">docker<\/span> compose logs <span class=\"token parameter variable\">-f<\/span> frontend<\/p>\n<h4>5.2 \u5065\u5eb7\u68c0\u67e5<\/h4>\n<p><span class=\"token function\">curl<\/span> http:\/\/localhost:8000\/api\/health<br \/>\n<span class=\"token comment\"># {&#034;status&#034;:&#034;ok&#034;,&#034;mqttConnected&#034;:true,&#034;deviceOnline&#034;:true}<\/span><\/p>\n<h4>5.3 \u66f4\u65b0<\/h4>\n<p><span class=\"token function\">docker<\/span> compose up <span class=\"token parameter variable\">-d<\/span> <span class=\"token parameter variable\">&#8211;build<\/span>       <span class=\"token comment\"># Docker \u65b9\u5f0f<\/span><br \/>\n<span class=\"token comment\"># \u6216\u88f8\u673a&#xff1a;\u91cd\u65b0 mvn package \u540e\u91cd\u542f\u670d\u52a1<\/span><br \/>\n<span class=\"token function\">sudo<\/span> systemctl restart gemeopen-backend<\/p>\n<h4>5.4 \u5907\u4efd<\/h4>\n<ul>\n<li>Broker \u6570\u636e&#xff1a;mosquitto-data \u5377&#xff1b;<\/li>\n<li>\u5386\u53f2\u6570\u636e&#xff1a;\u5f53\u524d Demo \u5b58\u4e8e\u5185\u5b58&#xff0c;\u91cd\u542f\u5373\u6e05\u7a7a\u3002\u751f\u4ea7\u5efa\u8bae\u6539\u63a5 PostgreSQL \/ InfluxDB \/ TimescaleDB\u3002<\/li>\n<\/ul>\n<h4>5.5 \u76d1\u63a7\u5efa\u8bae<\/h4>\n<table>\n<tr>\u6307\u6807\u65b9\u5f0f<\/tr>\n<tbody>\n<tr>\n<td>\u540e\u7aef\u5b58\u6d3b<\/td>\n<td>\/api\/health &#043; Uptime Kuma \/ \u5b9a\u65f6 curl<\/td>\n<\/tr>\n<tr>\n<td>JVM \u6307\u6807<\/td>\n<td>Spring Boot Actuator &#043; Prometheus &#043; Grafana<\/td>\n<\/tr>\n<tr>\n<td>MQTT \u8fde\u63a5\u6570<\/td>\n<td>mosquitto_sub -t &#039;$SYS\/broker\/clients\/connected&#039;<\/td>\n<\/tr>\n<tr>\n<td>\u8bbe\u5907\u5728\u7ebf<\/td>\n<td>\u540e\u7aef online \u5b57\u6bb5&#xff0c;\u53ef\u52a0 HA \u81ea\u52a8\u5316\u544a\u8b66<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>5.6 JVM \u8c03\u4f18&#xff08;\u53ef\u9009&#xff09;<\/h4>\n<p><span class=\"token function\">java<\/span> <span class=\"token parameter variable\">-Xms256m<\/span> <span class=\"token parameter variable\">-Xmx512m<\/span> <span class=\"token parameter variable\">-jar<\/span> target\/gemeopen-demo.jar<\/p>\n<p>\u5355\u8bbe\u5907\u4f4e\u9891\u4e0a\u62a5\u573a\u666f\u5185\u5b58\u5360\u7528\u5f88\u5c0f&#xff1b;\u53ef\u7ed3\u5408 Actuator \u89c2\u5bdf\u5806\u4f7f\u7528\u3002<\/p>\n<hr \/>\n<h3>6. \u914d\u7f6e\u901f\u67e5&#xff08;\u540e\u7aef\u73af\u5883\u53d8\u91cf&#xff09;<\/h3>\n<p>\u89c1 [00 \u00b7 \u67b6\u6784\u4e0e\u5951\u7ea6] 00-architecture.md \u7b2c 6 \u8282&#xff0c;\u6216 backend\/src\/main\/resources\/application.yml\u3002<\/p>\n<hr \/>\n<h4>07-troubleshooting.md<\/h4>\n<h2>07 \u00b7 \u6392\u9519\u624b\u518c<\/h2>\n<p>\u6309\u201c\u75c7\u72b6\u201d\u67e5\u201c\u539f\u56e0\/\u89e3\u51b3\u201d\u3002\u968f\u8eab\u5907\u597d\u4e24\u6761\u6293\u5305\u547d\u4ee4&#xff1a;<\/p>\n<p><span class=\"token comment\"># \u770b\u8bbe\u5907\u662f\u5426\u5728\u53d1\u6570\u636e&#xff08;\u8ba2\u9605\u8bbe\u5907\u4e0a\u62a5\u4e3b\u9898&#xff09;<\/span><br \/>\nmosquitto_sub <span class=\"token parameter variable\">-h<\/span> <span class=\"token number\">192.168<\/span>.1.10 <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token parameter variable\">-t<\/span> <span class=\"token string\">&#039;gemeopen\/gspm1b\/&#043;\/report&#039;<\/span> <span class=\"token parameter variable\">-v<\/span><\/p>\n<p><span class=\"token comment\"># \u770b\u662f\u5426\u6709\u4eba\u7ed9\u8bbe\u5907\u53d1\u6307\u4ee4&#xff08;\u8ba2\u9605\u8bbe\u5907\u6307\u4ee4\u4e3b\u9898&#xff09;<\/span><br \/>\nmosquitto_sub <span class=\"token parameter variable\">-h<\/span> <span class=\"token number\">192.168<\/span>.1.10 <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token parameter variable\">-t<\/span> <span class=\"token string\">&#039;gemeopen\/gspm1b\/&#043;\/command&#039;<\/span> <span class=\"token parameter variable\">-v<\/span><\/p>\n<hr \/>\n<h3>\u4e00\u3001\u8bbe\u5907\u4fa7<\/h3>\n<table>\n<tr>\u75c7\u72b6\u53ef\u80fd\u539f\u56e0\u89e3\u51b3<\/tr>\n<tbody>\n<tr>\n<td>\u8bbe\u5907\u4e0d\u4e0a\u62a5<\/td>\n<td>\u672a\u5207\u6362\u5230\u81ea\u5efa Broker<\/td>\n<td>\u8fd0\u884c scripts\/configure_device.py \u6267\u884c setting-mqtt&#xff0c;\u518d\u65ad\u7535\u91cd\u542f<\/td>\n<\/tr>\n<tr>\n<td>\u5207\u6362\u540e\u5f7b\u5e95\u6ca1\u6570\u636e<\/td>\n<td>\u76ee\u6807 Broker \u8bbe\u5907\u4e0d\u53ef\u8fbe<\/td>\n<td>\u5730\u5740\u7528\u5c40\u57df\u7f51 IP\/\u516c\u7f51\u57df\u540d&#xff0c;\u653e\u884c 1883<\/td>\n<\/tr>\n<tr>\n<td>\u4e0a\u62a5\u95f4\u9694\u5f88\u957f<\/td>\n<td>\u7535\u6c60\/\u7f13\u5b58\u7b56\u7565<\/td>\n<td>\u628a timerInterval \u8c03\u5c0f&#xff08;\u5982 15s&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u901a\u7535\u540e\u6570\u636e\u4e0d\u5237\u65b0<\/td>\n<td>\u672a\u5f00\u5b9a\u65f6\u4e0a\u62a5<\/td>\n<td>\u53d1 {&#034;timerEnable&#034;:1,&#034;timerInterval&#034;:15,&#034;type&#034;:&#034;setting&#034;}<\/td>\n<\/tr>\n<tr>\n<td>\u6539\u4e86\u53c2\u6570\u4e0d\u751f\u6548<\/td>\n<td>\u90e8\u5206\u8bbe\u7f6e\u9700\u91cd\u542f<\/td>\n<td>\u65ad\u7535\u91cd\u542f\u6216\u53d1 {&#034;system&#034;:&#034;restart&#034;,&#034;type&#034;:&#034;setting&#034;}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>\u4e8c\u3001MQTT Broker<\/h3>\n<table>\n<tr>\u75c7\u72b6\u53ef\u80fd\u539f\u56e0\u89e3\u51b3<\/tr>\n<tbody>\n<tr>\n<td>\u5ba2\u6237\u7aef\u8fde\u4e0d\u4e0a<\/td>\n<td>\u7aef\u53e3\/\u5730\u5740\/\u9632\u706b\u5899<\/td>\n<td>docker compose ps\u3001docker compose logs mosquitto<\/td>\n<\/tr>\n<tr>\n<td>not authorised<\/td>\n<td>\u5f00\u4e86\u8ba4\u8bc1\u4f46\u51ed\u636e\u9519<\/td>\n<td>\u6838\u5bf9 passwd&#xff0c;\u6216\u4e34\u65f6\u6539\u56de allow_anonymous true \u9a8c\u8bc1<\/td>\n<\/tr>\n<tr>\n<td>\u8ba2\u9605\u6536\u4e0d\u5230<\/td>\n<td>\u4e3b\u9898\u62fc\u5199\u9519<\/td>\n<td>\u7528 &#043; \u901a\u914d\u6d4b\u8bd5 gemeopen\/gspm1b\/&#043;\/report<\/td>\n<\/tr>\n<tr>\n<td>\u5bb9\u5668\u8d77\u4e0d\u6765<\/td>\n<td>\u914d\u7f6e\u8bed\u6cd5\u9519<\/td>\n<td>\u67e5\u770b mosquitto \u65e5\u5fd7<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>\u4e09\u3001Home Assistant<\/h3>\n<table>\n<tr>\u75c7\u72b6\u53ef\u80fd\u539f\u56e0\u89e3\u51b3<\/tr>\n<tbody>\n<tr>\n<td>MQTT \u96c6\u6210\u6dfb\u52a0\u5931\u8d25<\/td>\n<td>Broker \u5730\u5740\/\u51ed\u636e\u9519<\/td>\n<td>Docker \u573a\u666f\u7528\u5bbf\u4e3b\u673a IP<\/td>\n<\/tr>\n<tr>\n<td>switch \u4e0d\u53ef\u7528<\/td>\n<td>state_topic \u65e0\u6570\u636e<\/td>\n<td>\u5148\u786e\u4fdd\u8bbe\u5907\u5728\u62a5\u6570\u636e&#xff1b;\u68c0\u67e5 &lt;MAC&gt; \u662f\u5426\u66ff\u6362<\/td>\n<\/tr>\n<tr>\n<td>\u70b9\u5f00\u5173\u6ca1\u53cd\u5e94<\/td>\n<td>command_topic \u586b\u6210 report<\/td>\n<td>\u5fc5\u987b\u662f\u8bbe\u5907 subcribe \u4e3b\u9898&#xff08;&#8230;\/command&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u4f20\u611f\u5668\u4e00\u76f4\u201c\u672a\u77e5\u201d<\/td>\n<td>\u672a\u5f00\u5b9a\u65f6\u4e0a\u62a5<\/td>\n<td>\u5f00\u542f\u4e0a\u62a5&#xff1b;\u6293\u5305\u786e\u8ba4\u5b57\u6bb5\u540d<\/td>\n<\/tr>\n<tr>\n<td>\u80fd\u6e90\u9762\u677f\u65e0\u6570\u636e<\/td>\n<td>\u7f3a state_class<\/td>\n<td>\u786e\u8ba4 energy \u4f20\u611f\u5668 total_increasing<\/td>\n<\/tr>\n<tr>\n<td>\u6539 YAML \u4e0d\u751f\u6548<\/td>\n<td>\u672a\u91cd\u8f7d<\/td>\n<td>\u5f00\u53d1\u8005\u5de5\u5177 \u2192 YAML \u2192 \u68c0\u67e5\u914d\u7f6e \u2192 \u91cd\u542f HA<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>\u56db\u3001Java \u540e\u7aef&#xff08;Spring Boot&#xff09;<\/h3>\n<table>\n<tr>\u75c7\u72b6\u53ef\u80fd\u539f\u56e0\u89e3\u51b3<\/tr>\n<tbody>\n<tr>\n<td>\u542f\u52a8\u62a5 Port 8000 already in use<\/td>\n<td>\u7aef\u53e3\u88ab\u5360\u7528<\/td>\n<td>\u6539 server.port \u6216\u505c\u6389\u5360\u7528\u8fdb\u7a0b<\/td>\n<\/tr>\n<tr>\n<td>\/api\/health \u91cc mqttConnected:false<\/td>\n<td>\u8fde\u4e0d\u4e0a Broker<\/td>\n<td>\u68c0\u67e5 MQTT_HOST\/PORT\/USERNAME\/PASSWORD<\/td>\n<\/tr>\n<tr>\n<td>\/api\/device \u5168\u4e3a null<\/td>\n<td>\u6ca1\u6536\u5230\u8bbe\u5907\u4e0a\u62a5<\/td>\n<td>\u7528 mosquitto_sub \u9a8c\u8bc1\u8bbe\u5907\u5728\u53d1<\/td>\n<\/tr>\n<tr>\n<td>\u5f00\u5173\u63a5\u53e3 success:true \u4f46\u5b9e\u7269\u65e0\u53cd\u5e94<\/td>\n<td>MQTT_COMMAND_TOPIC \u7684 {mac} \u672a\u66ff\u6362<\/td>\n<td>\u68c0\u67e5 DEVICE_MAC \u4e0e topic \u6a21\u677f<\/td>\n<\/tr>\n<tr>\n<td>\u7f16\u8bd1\u62a5\u4f9d\u8d56\u4e0b\u8f7d\u5931\u8d25<\/td>\n<td>\u7f51\u7edc\u6296\u52a8<\/td>\n<td>\u91cd\u8bd5 mvn -DskipTests package&#xff1b;\u914d\u7f6e\u955c\u50cf<\/td>\n<\/tr>\n<tr>\n<td>\u60f3\u8c03\u65e5\u5fd7\u7ea7\u522b<\/td>\n<td>\u2014<\/td>\n<td>application.yml \u91cc logging.level.com.gemeopen&#061;DEBUG<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u5c0f\u6280\u5de7&#xff1a;mvn -DskipTests package \u6253\u5305\u540e java -jar target\/gemeopen-demo.jar \u6700\u63a5\u8fd1\u751f\u4ea7\u8fd0\u884c\u65b9\u5f0f\u3002<\/p>\n<hr \/>\n<h3>\u4e94\u3001Angular \u524d\u7aef<\/h3>\n<table>\n<tr>\u75c7\u72b6\u53ef\u80fd\u539f\u56e0\u89e3\u51b3<\/tr>\n<tbody>\n<tr>\n<td>\u9875\u9762\u4e00\u76f4\u201c\u79bb\u7ebf\u201d<\/td>\n<td>\u540e\u7aef\u672a\u8d77\/\u5730\u5740\u9519<\/td>\n<td>\u6253\u5f00 http:\/\/localhost:8000\/api\/health&#xff1b;\u68c0\u67e5 environment.ts<\/td>\n<\/tr>\n<tr>\n<td>\u6709\u6570\u636e\u4f46\u4e0d\u5237\u65b0<\/td>\n<td>WebSocket \u88ab\u4ee3\u7406\u62e6\u622a<\/td>\n<td>\u5f00\u53d1\u7528 proxy.conf.json&#xff1b;\u751f\u4ea7\u7528 nginx.conf \u7684 \/ws \u6bb5<\/td>\n<\/tr>\n<tr>\n<td>\u8de8\u57df\u62a5\u9519<\/td>\n<td>\u540e\u7aef\u672a\u5141\u8bb8\u6765\u6e90<\/td>\n<td>\u540e\u7aef CORS_ORIGINS \u8bbe\u4e3a\u524d\u7aef\u5730\u5740<\/td>\n<\/tr>\n<tr>\n<td>\u56fe\u8868\u4e3a\u7a7a<\/td>\n<td>\/api\/device\/history \u65e0\u6570\u636e<\/td>\n<td>\u9700\u5148\u79ef\u7d2f\u82e5\u5e72\u6761\u4e0a\u62a5<\/td>\n<\/tr>\n<tr>\n<td>npm install \u5f88\u6162<\/td>\n<td>\u7f51\u7edc\/\u955c\u50cf<\/td>\n<td>\u6362 npm \u955c\u50cf\u6e90&#xff0c;\u6216\u4f7f\u7528 Docker \u6784\u5efa<\/td>\n<\/tr>\n<tr>\n<td>\u6784\u5efa\u540e\u63a5\u53e3 404<\/td>\n<td>\u751f\u4ea7 apiBase \u672a\u8d70\u540c\u6e90<\/td>\n<td>\u751f\u4ea7\u6784\u5efa\u7528 environment.prod.ts&#xff08;apiBase: &#039;&#039;&#xff09;&#043; Nginx \u53cd\u4ee3<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>\u516d\u3001\u7f51\u7edc\u8fde\u901a\u6027\u81ea\u67e5&#xff08;\u4e07\u80fd\u56db\u8fde&#xff09;<\/h3>\n<p><span class=\"token comment\"># 1) \u80fd\u5426\u5411 Broker \u53d1\u5e03\u6d4b\u8bd5\u6d88\u606f<\/span><br \/>\nmosquitto_pub <span class=\"token parameter variable\">-h<\/span> <span class=\"token number\">192.168<\/span>.1.10 <span class=\"token parameter variable\">-p<\/span> <span class=\"token number\">1883<\/span> <span class=\"token parameter variable\">-t<\/span> <span class=\"token builtin class-name\">test<\/span> <span class=\"token parameter variable\">-m<\/span> hello<\/p>\n<p><span class=\"token comment\"># 2) \u540e\u7aef \u2192 Broker \u914d\u7f6e<\/span><br \/>\n<span class=\"token function\">docker<\/span> compose <span class=\"token builtin class-name\">exec<\/span> backend <span class=\"token function\">sh<\/span> <span class=\"token parameter variable\">-c<\/span> <span class=\"token string\">&#039;echo $MQTT_HOST&#039;<\/span><\/p>\n<p><span class=\"token comment\"># 3) \u6d4f\u89c8\u5668\/\u547d\u4ee4\u884c \u2192 \u540e\u7aef<\/span><br \/>\n<span class=\"token function\">curl<\/span> http:\/\/192.168.1.10:8000\/api\/health<\/p>\n<p><span class=\"token comment\"># 4) HA \u2192 Broker&#xff08;MQTT \u96c6\u6210\u9875\u9762\u770b\u201c\u5df2\u8fde\u63a5\u201d&#xff09;<\/span><\/p>\n<p>\u7edd\u5927\u591a\u6570\u95ee\u9898\u90fd\u80fd\u901a\u8fc7\u300c\u786e\u8ba4\u6570\u636e\u662f\u5426\u5230\u8fbe Broker\u300d\u5feb\u901f\u5b9a\u4f4d\u662f\u8bbe\u5907\u4fa7\u3001Broker \u4fa7\u8fd8\u662f\u5e94\u7528\u4fa7\u3002<\/p>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>GemeOpen GSPM1B \u00d7 Home Assistant \u00d7 Java(Spring Boot)  Angular Demo<br \/>\n\u628a GemeOpen GSPM1B \u667a\u80fd\u8f6c\u6362\u5668\u63d2\u5ea7 \u63a5\u5165 Home Assistant&#xff0c;\u5b9e\u73b0 \u901a\u65ad\u7535\u63a7\u5236 \u4e0e \u7535\u538b \/ \u7535\u6d41 \/ \u529f\u7387 \/ \u7d2f\u8ba1\u7528\u7535\u91cf \u91c7\u96c6&#xff1b;\u5e76\u9644\u4e00\u5957 Java(Spring Boot)  Angular \u7684\u5b8c\u6574\u81ea\u7814 Demo\u3002 \u9762\u5411\u7a0b\u5e8f\u5458\u521d\u5b66\u8005&#xff1a;\u6587\u6863\u4ece\u96f6\u8bb2\u8d77&#xff0c;\u6bcf\u4e00\u6b65\u90fd\u53ef<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[5120,99,190],"topic":[],"class_list":["post-112347","post","type-post","status-publish","format-standard","hentry","category-server","tag-angular-js","tag-java","tag-190"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/112347.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"GemeOpen GSPM1B \u00d7 Home Assistant \u00d7 Java(Spring Boot) Angular Demo \u628a GemeOpen GSPM1B \u667a\u80fd\u8f6c\u6362\u5668\u63d2\u5ea7 \u63a5\u5165 Home Assistant&#xff0c;\u5b9e\u73b0 \u901a\u65ad\u7535\u63a7\u5236 \u4e0e \u7535\u538b \/ \u7535\u6d41 \/ \u529f\u7387 \/ \u7d2f\u8ba1\u7528\u7535\u91cf \u91c7\u96c6&#xff1b;\u5e76\u9644\u4e00\u5957 Java(Spring Boot) Angular \u7684\u5b8c\u6574\u81ea\u7814 Demo\u3002 \u9762\u5411\u7a0b\u5e8f\u5458\u521d\u5b66\u8005&#xff1a;\u6587\u6863\u4ece\u96f6\u8bb2\u8d77&#xff0c;\u6bcf\u4e00\u6b65\u90fd\u53ef\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/112347.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-03T01:08:49+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/112347.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/112347.html\",\"name\":\"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-10-03T01:08:49+00:00\",\"dateModified\":\"2026-10-03T01:08:49+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/112347.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/112347.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/112347.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/112347.html","og_locale":"zh_CN","og_type":"article","og_title":"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"GemeOpen GSPM1B \u00d7 Home Assistant \u00d7 Java(Spring Boot) Angular Demo \u628a GemeOpen GSPM1B \u667a\u80fd\u8f6c\u6362\u5668\u63d2\u5ea7 \u63a5\u5165 Home Assistant&#xff0c;\u5b9e\u73b0 \u901a\u65ad\u7535\u63a7\u5236 \u4e0e \u7535\u538b \/ \u7535\u6d41 \/ \u529f\u7387 \/ \u7d2f\u8ba1\u7528\u7535\u91cf \u91c7\u96c6&#xff1b;\u5e76\u9644\u4e00\u5957 Java(Spring Boot) Angular \u7684\u5b8c\u6574\u81ea\u7814 Demo\u3002 \u9762\u5411\u7a0b\u5e8f\u5458\u521d\u5b66\u8005&#xff1a;\u6587\u6863\u4ece\u96f6\u8bb2\u8d77&#xff0c;\u6bcf\u4e00\u6b65\u90fd\u53ef","og_url":"https:\/\/www.wsisp.com\/helps\/112347.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-10-03T01:08:49+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"14 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/112347.html","url":"https:\/\/www.wsisp.com\/helps\/112347.html","name":"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-10-03T01:08:49+00:00","dateModified":"2026-10-03T01:08:49+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/112347.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/112347.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/112347.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"MQTT\u667a\u80fd\u63d2\u5ea7\u5982\u4f55\u63a5\u5165Home Assistant\uff0c\u4ece\u96f6\u5f00\u59cb\u5b8c\u6574\u5de5\u7a0b\u5b9e\u73b0\uff08Java+Angular\uff09"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/112347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=112347"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/112347\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=112347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=112347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=112347"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=112347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}