diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..64c887a 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/README.md b/README.md
index d9dcf36..d9f67d9 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
"task_id": "6589",
"address": "房间南侧",
"type": "1",
- "facility": "02"
+ "facility": "02"
},
{
"host_uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm",
diff --git a/business/gpio_ctrl.go b/business/gpio_ctrl.go
new file mode 100644
index 0000000..37f3184
--- /dev/null
+++ b/business/gpio_ctrl.go
@@ -0,0 +1,47 @@
+// gpio_controller.go
+package business
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "time"
+)
+
+const BuzzerGPIO = 109
+
+// TriggerBuzzer 触发蜂鸣器响指定秒数
+func TriggerBuzzer(seconds int) {
+ if seconds <= 0 {
+ seconds = 10
+ }
+
+ // 必须用同步!异步 goroutine 在某些系统里会被静默丢弃
+ fmt.Printf("蜂鸣器开始响铃 %d 秒...\n", seconds)
+
+ gpioPath := fmt.Sprintf("/sys/class/gpio/gpio%d", BuzzerGPIO)
+
+ // 1. 强制导出(即使已经导出也没事)
+ os.WriteFile("/sys/class/gpio/export", []byte(strconv.Itoa(BuzzerGPIO)), 0666)
+ time.Sleep(50 * time.Millisecond)
+
+ // 2. 强制设为输出
+ os.WriteFile(fmt.Sprintf("%s/direction", gpioPath), []byte("out"), 0666)
+ time.Sleep(10 * time.Millisecond)
+
+ // 3. 拉高 → 响
+ if err := os.WriteFile(fmt.Sprintf("%s/value", gpioPath), []byte("1"), 0666); err != nil {
+ fmt.Printf("GPIO拉高失败: %v\n", err)
+ } else {
+ fmt.Println("GPIO109 已拉高 → 蜂鸣器响!")
+ }
+
+ time.Sleep(time.Duration(seconds) * time.Second)
+
+ // 4. 拉低 → 停
+ if err := os.WriteFile(fmt.Sprintf("%s/value", gpioPath), []byte("0"), 0666); err != nil {
+ fmt.Printf("GPIO拉低失败: %v\n", err)
+ } else {
+ fmt.Println("GPIO109 已拉低 → 蜂鸣器停止")
+ }
+}
diff --git a/connect/ws_channel.go b/connect/ws_channel.go
index 6d6ec2a..2fa13b4 100644
--- a/connect/ws_channel.go
+++ b/connect/ws_channel.go
@@ -17,6 +17,17 @@ var (
wsURL = "ws://172.17.0.1:18080/ws"
)
+type AlertMessage struct {
+ UUID string `json:"uuid"`
+ Topic string `json:"topic"`
+ QoS int `json:"qos"`
+ Content string `json:"content"`
+ Timeout int `json:"timeout"`
+}
+type AlertContent struct {
+ Type int `json:"type"` // 1=蜂鸣器告警
+ BuzzerDuration int `json:"buzzer_duration"` // 响多久(秒)
+}
type WSMessage struct {
ID int64 `json:"id,omitempty"`
Method string `json:"method"`
@@ -46,8 +57,9 @@ type MetricDataParams struct {
}
type PublishParams struct {
- Topic string `json:"topic"`
- Data json.RawMessage `json:"data,omitempty"`
+ Topic string `json:"topic"`
+ Data json.RawMessage `json:"data,omitempty"`
+ Content json.RawMessage `json:"content,omitempty"`
}
type WSClient struct {
@@ -65,15 +77,6 @@ type WSClient struct {
reconnectFlag bool
}
-// ==================== Public API ====================
-
-//// GetWSClient returns the global WebSocket client instance
-//func GetWSClient() *WSClient {
-// wsMutex.RLock()
-// defer wsMutex.RUnlock()
-// return wsClient
-//}
-
// InitWSChannel initializes WebSocket connection
func InitWSChannel() error {
wsMutex.Lock()
@@ -361,7 +364,9 @@ func (c *WSClient) handlePublishMessage(message WSMessage) {
logger.Logger.Printf("Failed to parse publish message parameters: %v", err)
return
}
-
+ // 加这一行!万能抓包,永不漏!
+ logger.Logger.Printf("WebSocket 收到 publish 消息 → Topic: %s | 原始数据: %s",
+ publishParams.Topic, string(publishParams.Data))
c.mutex.Lock()
callback, exists := c.subscribers[publishParams.Topic]
c.mutex.Unlock()
@@ -458,11 +463,11 @@ func (c *WSClient) autoReRegister() {
}
c.mutex.Unlock()
- for topic, callback := range subscribers {
- if err := SubscribeTopic(topic, callback); err != nil {
- logger.Logger.Printf("Failed to re-subscribe topic %s: %v", topic, err)
- }
- }
+ //for topic, callback := range subscribers {
+ // if err := SubscribeTopic(topic, callback); err != nil {
+ // logger.Logger.Printf("Failed to re-subscribe topic %s: %v", topic, err)
+ // }
+ //}
}
}
diff --git a/dthjjc b/dthjjc
index dfcf994..3354203 100644
Binary files a/dthjjc and b/dthjjc differ
diff --git a/main.go b/main.go
index cc49847..811b6bc 100644
--- a/main.go
+++ b/main.go
@@ -9,6 +9,7 @@ import (
"log"
"os"
"os/signal"
+ "strconv"
"syscall"
"time"
)
@@ -126,6 +127,13 @@ func runNormalMode() {
if err := connect.SubscribeTopic("device_updates", handleDeviceUpdates); err != nil {
log.Fatal("Topic subscription failed:", err)
}
+ logger.Logger.Printf("Subscribing to alert topic (/dthjjc/alert) for buzzer...")
+
+ if err := connect.SubscribeTopic("/dthjjc/alert", handleAlertMessage); err != nil {
+ logger.Logger.Printf("Failed to subscribe alert topic: %v (continue anyway)", err)
+ } else {
+ logger.Logger.Printf("Successfully subscribed to /dthjjc/alert → buzzer ready!")
+ }
// 8. 启动数据采集循环
logger.Logger.Printf("Starting data collection loop...")
@@ -171,3 +179,63 @@ func startDataCollectionLoop(businessManager *business.BusinessManager) {
}
}
+
+func handleAlertMessage(params *connect.PublishParams) {
+ payload := params.Content
+ if len(payload) == 0 {
+ payload = params.Data
+ }
+ if len(payload) == 0 {
+ logger.Logger.Printf("平台告警空包 → 强制响 3 秒")
+ business.TriggerBuzzer(3)
+ return
+ }
+
+ raw := string(payload)
+ logger.Logger.Printf("收到告警原始内容 → %s", raw)
+
+ type Cmd struct {
+ Type int `json:"type"`
+ BuzzerDuration json.RawMessage `json:"buzzer_duration"` // 万能类型!
+ }
+ var cmd Cmd
+
+ var outer string
+ if json.Unmarshal(payload, &outer) == nil {
+ logger.Logger.Printf("检测到外层是字符串 → %s", outer)
+ raw = outer
+ }
+
+ if err := json.Unmarshal([]byte(raw), &cmd); err != nil {
+ logger.Logger.Printf("最终解析失败: %v → 暴力识别", err)
+ } else if cmd.Type == 1 {
+
+ dur := 3
+ var temp interface{}
+ if json.Unmarshal(cmd.BuzzerDuration, &temp) == nil {
+ switch v := temp.(type) {
+ case string:
+ if n, err := strconv.Atoi(v); err == nil {
+ dur = n
+ }
+ case float64:
+ dur = int(v)
+ case int:
+ dur = v
+ }
+ }
+ if dur <= 0 {
+ dur = 3
+ }
+
+ logger.Logger.Printf("平台告警解析成功 → 蜂鸣器响 %d 秒!!!", dur)
+ business.TriggerBuzzer(dur)
+ return
+ }
+
+ // 终极兜底:只要包含 type 和 1 就响
+ //if strings.Contains(raw, "type") && strings.Contains(raw, "1") {
+ // logger.Logger.Printf("暴力识别告警指令 → 强制响 3 秒")
+ // business.TriggerBuzzer(3)
+ //}
+}
diff --git a/连接线路.drawio b/连接线路.drawio
new file mode 100644
index 0000000..3a6ef4f
--- /dev/null
+++ b/连接线路.drawio
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+