128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
|
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
|
|||
|
}
|