package device import ( "errors" "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" log "github.com/sirupsen/logrus" "github.com/spf13/cast" "strings" "sync" "time" ) var ( EWSTypeRaw = "raw" ) type Esp8266WifiSwitch struct { sync.Mutex brand string model string deviceId string client mqtt.Client callback Callback } func NewEsp8266WifiSwitch(deviceId string, mqttClient mqtt.Client, callback Callback) *Esp8266WifiSwitch { u := &Esp8266WifiSwitch{ client: mqttClient, deviceId: deviceId, callback: callback, brand: BrandESP8266, model: "wsp8", } if callback != nil { var token mqtt.Token = nil if deviceId == "#" { token = mqttClient.Subscribe(fmt.Sprintf("%s/%s/%s", u.brand, u.model, deviceId), 2, u.Callback) } else { token = mqttClient.Subscribe(fmt.Sprintf("%s/%s/%s/#", u.brand, u.model, deviceId), 2, u.Callback) } if err := token.Error(); err != nil { log.Errorf("[%s:%s] device[%s] Subscribe error:%s", u.brand, u.model, deviceId, err.Error()) } } return u } func (u *Esp8266WifiSwitch) TurnOn(idx int) error { if u.deviceId == "#" { return nil } topic := fmt.Sprintf("%s/%s/%s/cmd", u.brand, u.model, u.deviceId) publishACK := u.client.Publish(topic, 0, false, fmt.Sprintf("a%d", idx+1)) publishACK.WaitTimeout(time.Second) return publishACK.Error() } func (u *Esp8266WifiSwitch) TurnOff(idx int) error { if u.deviceId == "#" { return nil } topic := fmt.Sprintf("%s/%s/%s/cmd", u.brand, u.model, u.deviceId) publishACK := u.client.Publish(topic, 0, false, fmt.Sprintf("c%d", idx+1)) publishACK.WaitTimeout(time.Second) return publishACK.Error() } func (u *Esp8266WifiSwitch) KeepAlive() error { if u.deviceId == "#" { return nil } topic := fmt.Sprintf("%s/%s/%s/cmd", u.brand, u.model, u.deviceId) publishACK := u.client.Publish(topic, 0, false, "qa") //查询继电器状态 publishACK.WaitTimeout(time.Second) return publishACK.Error() } func (u *Esp8266WifiSwitch) Operate(cmd string) error { if u.deviceId == "#" { return errors.New("不支持的操作#") } topic := fmt.Sprintf("%s/%s/%s/cmd", u.brand, u.model, u.deviceId) publishACK := u.client.Publish(topic, 0, false, cmd) //查询继电器状态 publishACK.WaitTimeout(time.Second) return publishACK.Error() } func (u *Esp8266WifiSwitch) Callback(client mqtt.Client, message mqtt.Message) { u.Lock() defer u.Unlock() topic := message.Topic() payload := message.Payload() // res的才回调,忽略cmd请求 if !strings.HasSuffix(topic, "res") { return } log.Debugf("[%s][%s] deviceId[%s] topic[%s] payloyad[%s]", u.brand, u.model, u.deviceId, topic, string(payload)) var callMsg Message callMsg.MsgType = EWSTypeRaw callMsg.MsgTime = time.Now().Unix() callMsg.MsgId = cast.ToString(message.MessageID()) callMsg.DeviceId = u.getDeviceId(topic) callMsg.Topic = topic callMsg.Data = make(map[string]interface{}) callMsg.Data["raw"] = string(payload) u.callback(&callMsg) } func (u *Esp8266WifiSwitch) getDeviceId(topic string) string { devId := u.deviceId if devId == "#" { fields := strings.Split(topic, "/") if len(fields) >= 2 { devId = fields[2] } } return devId }