package device import ( "encoding/json" "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" log "github.com/sirupsen/logrus" "github.com/spf13/cast" "strings" "sync" "time" ) var ( FSTypeGetinfo = "getinfo" ) type FsVoice struct { sync.Mutex deviceId string client mqtt.Client callback Callback brand string model string } func NewFushuaVoice(deviceId string, client mqtt.Client, callback Callback) *FsVoice { s := &FsVoice{ deviceId: deviceId, client: client, callback: callback, brand: BrandFushua, model: "voice", } if callback != nil { client.Subscribe(fmt.Sprintf("%s/%s/%s", s.brand, s.model, deviceId), 2, s.Callback) } return s } func (s *FsVoice) Operate(cmd string) error { return s.Play(cmd) } func (s *FsVoice) KeepAlive() error { if s.deviceId == "#" { return nil } topic := fmt.Sprintf("%s/%s/%s/cmd", s.brand, s.model, s.deviceId) payload := fmt.Sprintf(`{"cmd":"getinfo","msgid":"%s"}`, cast.ToString(time.Now().UnixMilli())) publishACK := s.client.Publish(topic, 2, false, payload) publishACK.WaitTimeout(time.Second) return publishACK.Error() } func (s *FsVoice) Play(tts string) error { if s.deviceId == "#" { return nil } topic := fmt.Sprintf("%s/%s/%s/cmd", s.brand, s.model, s.deviceId) payload := fmt.Sprintf(`{"cmd":"voice","msgid":"%s","msg":"%s"}`, cast.ToString(time.Now().UnixMilli()), tts) publishACK := s.client.Publish(topic, 2, false, payload) publishACK.WaitTimeout(time.Second) return publishACK.Error() } func (s *FsVoice) getDeviceId(topic string) string { devId := s.deviceId if devId == "#" { fields := strings.Split(topic, "/") if len(fields) >= 3 { devId = fields[2] } } return devId } func (s *FsVoice) Callback(client mqtt.Client, message mqtt.Message) { s.Lock() defer s.Unlock() topic := message.Topic() payload := message.Payload() if strings.HasSuffix(topic, "cmd") { return } log.Debugf("[%s][%s] deviceId[%s] topic[%s] payloyad[%s]", s.brand, s.model, s.deviceId, topic, string(payload)) var callMsg Message callMsg.MsgType = FSTypeGetinfo callMsg.MsgTime = time.Now().Unix() callMsg.MsgId = cast.ToString(message.MessageID()) callMsg.DeviceId = s.getDeviceId(topic) callMsg.Topic = topic callMsg.Data = make(map[string]interface{}) json.Unmarshal([]byte(payload), &callMsg.Data) s.callback(&callMsg) }