添加gpio控制
This commit is contained in:
parent
18205b02df
commit
d91e6e41e1
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/rk1808-yolov5-inference" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -18,7 +18,7 @@
|
||||
"task_id": "6589",
|
||||
"address": "房间南侧",
|
||||
"type": "1",
|
||||
"facility": "02"
|
||||
"facility": "02"
|
||||
},
|
||||
{
|
||||
"host_uuid": "qbxmjyzrkpntfgswaevodhluicqzxplkm",
|
||||
|
||||
47
business/gpio_ctrl.go
Normal file
47
business/gpio_ctrl.go
Normal file
@ -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 已拉低 → 蜂鸣器停止")
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
68
main.go
68
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)
|
||||
//}
|
||||
}
|
||||
|
||||
84
连接线路.drawio
Normal file
84
连接线路.drawio
Normal file
@ -0,0 +1,84 @@
|
||||
<mxfile host="Electron" modified="2025-11-26T09:09:40.277Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.0.4 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="c7_EBDN9ol-w24zU6wdL" version="24.0.4" type="device">
|
||||
<diagram name="第 1 页" id="tfFKj4gfuwo1-KzXBk_g">
|
||||
<mxGraphModel dx="1309" dy="999" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="CCi69vAXkhbXQBJSxABA-1" target="CCi69vAXkhbXQBJSxABA-8" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="CCi69vAXkhbXQBJSxABA-1" target="CCi69vAXkhbXQBJSxABA-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;startArrow=classic;startFill=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-1" target="CCi69vAXkhbXQBJSxABA-10" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="CCi69vAXkhbXQBJSxABA-1" target="CCi69vAXkhbXQBJSxABA-7" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="CCi69vAXkhbXQBJSxABA-1" target="CCi69vAXkhbXQBJSxABA-14" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-1" value="N2000" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="700" y="360" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-4" target="CCi69vAXkhbXQBJSxABA-14" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-4" target="CCi69vAXkhbXQBJSxABA-7" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-4" value="220V供电" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="730" y="280" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-5" target="CCi69vAXkhbXQBJSxABA-10" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-5" target="CCi69vAXkhbXQBJSxABA-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-5" target="CCi69vAXkhbXQBJSxABA-8" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;dashed=1;" parent="1" source="CCi69vAXkhbXQBJSxABA-5" target="CCi69vAXkhbXQBJSxABA-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="980" y="430" />
|
||||
<mxPoint x="820" y="430" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-5" value="12v" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="950" y="465" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-7" value="安卓<div>显示屏</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="890" y="370" width="60" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-8" value="温湿度<br>传感器" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="660" y="470" width="60" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-9" value="水浸<div>传感器</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="730" y="470" width="60" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-10" value="<div>烟雾</div><div>传感器</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="800" y="470" width="60" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-14" value="摄像头" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="370" width="60" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-15" value="485" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="760" y="418" width="40" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-17" value="HTTP" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="825" y="368" width="50" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-19" value="RTSP" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="640" y="368" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="CCi69vAXkhbXQBJSxABA-27" value="电表" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="730" y="310" width="60" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
Loading…
x
Reference in New Issue
Block a user