1. 導入 Go 語言撰寫的 MQTT Gateway (mqtt-gateway/),負責訊息接收並透過 Redis List 轉發至 Laravel。 2. 更新 compose.yaml 以包含 EMQX Broker 與 mqtt-gateway 服務,並配置相關環境變數。 3. 新增 ListenMqttQueue 指令與對應的異步處理 Job (ProcessHeartbeat, ProcessTransaction, ProcessMachineError)。 4. 實作 MqttSyncAuth 指令與 Machine Model Observer,支援自動化的機台認證資訊同步至 Redis。 5. 新增 MqttCommandService 用於處理雲端至機台的即時指令下發。 6. 更新專案規範文件 (framework.md 與 Skills) 以反映新的 MQTT 通訊機制與安全性規範。 7. 提供 simulate-heartbeat.sh 指令碼以供開發與測試使用。
63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
package bridge
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"log"
|
||
|
||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||
"github.com/redis/go-redis/v9"
|
||
)
|
||
|
||
type RedisConsumer struct {
|
||
rdb *redis.Client
|
||
mqttClient mqtt.Client
|
||
queueKey string
|
||
}
|
||
|
||
type CommandPayload struct {
|
||
Target string `json:"target"`
|
||
Command string `json:"command"`
|
||
Payload interface{} `json:"payload"`
|
||
MessageID string `json:"message_id"`
|
||
}
|
||
|
||
func NewRedisConsumer(rdb *redis.Client, mqttClient mqtt.Client, queueKey string) *RedisConsumer {
|
||
return &RedisConsumer{rdb: rdb, mqttClient: mqttClient, queueKey: queueKey}
|
||
}
|
||
|
||
func (c *RedisConsumer) Start(ctx context.Context) {
|
||
log.Printf("Redis Consumer started, listening on queue: %s", c.queueKey)
|
||
for {
|
||
select {
|
||
case <-ctx.Done():
|
||
return
|
||
default:
|
||
// 使用 BLPOP 阻塞式讀取,逾時設為 0 表示永久等待
|
||
result, err := c.rdb.BLPop(ctx, 0, c.queueKey).Result()
|
||
if err != nil {
|
||
if err != context.Canceled {
|
||
log.Printf("Redis BLPop error: %v", err)
|
||
}
|
||
continue
|
||
}
|
||
|
||
// result[0] 是 key,result[1] 是 value
|
||
var cmd CommandPayload
|
||
err = json.Unmarshal([]byte(result[1]), &cmd)
|
||
if err != nil {
|
||
log.Printf("Failed to unmarshal command: %v", err)
|
||
continue
|
||
}
|
||
|
||
topic := "machine/" + cmd.Target + "/command"
|
||
payload, _ := json.Marshal(cmd)
|
||
|
||
token := c.mqttClient.Publish(topic, 1, false, payload)
|
||
token.Wait()
|
||
|
||
log.Printf("Sent command [%s] to machine [%s] via topic: %s", cmd.Command, cmd.Target, topic)
|
||
}
|
||
}
|
||
}
|