FireLeave_tool/connect/gpio_connect.go
2025-12-03 14:12:38 +08:00

114 lines
2.8 KiB
Go

package connect
import (
"FireLeave_tool/logger"
"encoding/json"
"fmt"
"os"
"strconv"
"time"
)
const BuzzerGPIO = 109
// TriggerBuzzer 触发蜂鸣器响指定秒数
func TriggerBuzzer(seconds int) {
if seconds <= 0 {
seconds = 10
}
fmt.Printf("Buzzer starting to ring for %d seconds...\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("Failed to set GPIO high: %v\n", err)
} else {
fmt.Println("GPIO109 set high → Buzzer ringing!")
}
time.Sleep(time.Duration(seconds) * time.Second)
// 4. 拉低 → 停
if err := os.WriteFile(fmt.Sprintf("%s/value", gpioPath), []byte("0"), 0666); err != nil {
fmt.Printf("Failed to set GPIO low: %v\n", err)
} else {
fmt.Println("GPIO109 set low → Buzzer stopped")
}
}
func HandleBuzzerAlert(message []byte) {
logger.Logger.Printf("Received platform alert push → Raw message: %s", string(message))
type PublishMsg struct {
Topic string `json:"topic"`
Content json.RawMessage `json:"content"` // 保持原始字节
}
var pub PublishMsg
if err := json.Unmarshal(message, &pub); err != nil {
logger.Logger.Printf("Outer parsing failed: %v", err)
go TriggerBuzzer(3)
return
}
var realCmd struct {
Type int `json:"type"`
BuzzerDuration interface{} `json:"buzzer_duration,omitempty"`
}
if err := json.Unmarshal(pub.Content, &realCmd); err == nil {
} else {
var contentStr string
if json.Unmarshal(pub.Content, &contentStr) != nil {
logger.Logger.Printf("Content is neither string nor JSON → Using default 3 seconds")
go TriggerBuzzer(3)
return
}
logger.Logger.Printf("Detected escaped content → Second parsing: %s", contentStr)
if err := json.Unmarshal([]byte(contentStr), &realCmd); err != nil {
logger.Logger.Printf("Second parsing failed: %v → Using default 3 seconds", err)
go TriggerBuzzer(3)
return
}
}
if realCmd.Type != 1 {
logger.Logger.Printf("Not a sound/light alert command (type=%d), ignoring", realCmd.Type)
return
}
duration := 3
switch v := realCmd.BuzzerDuration.(type) {
case float64:
duration = int(v)
case string:
if n, err := strconv.Atoi(v); err == nil {
duration = n
}
case int:
duration = v
case nil:
duration = 3
}
if duration <= 0 || duration > 300 {
duration = 3
}
logger.Logger.Printf("Platform alert command → Local sound/light alarm ringing for %d seconds!!!", duration)
go TriggerBuzzer(duration)
}