gosdk/device/ustone_wifi_switch.go

234 lines
6.3 KiB
Go
Raw Permalink Normal View History

2024-05-21 20:45:32 +08:00
package device
import (
"encoding/json"
"errors"
"fmt"
mqtt "github.com/eclipse/paho.mqtt.golang"
log "github.com/sirupsen/logrus"
"github.com/spf13/cast"
"strings"
"sync"
"time"
)
var (
UWSTypeInfo1 = "info1"
UWSTypeInfo2 = "info2"
UWSTypeInfo3 = "info3"
UWSTypeState = "state"
UWSTypeSensor = "sensor"
UWSTypePower = "power"
UWSTypeResult = "result"
)
type UstoneWifiSwitch struct {
sync.Mutex
brand string
model string
deviceId string
client mqtt.Client
callback Callback
}
func NewUstoneWifiSwitch(deviceId string, mqtt mqtt.Client, callback Callback) *UstoneWifiSwitch {
u := &UstoneWifiSwitch{
brand: BrandUstone,
model: "wsp1",
client: mqtt,
deviceId: deviceId,
callback: callback,
}
if callback != nil {
if deviceId == "#" {
mqtt.Subscribe(fmt.Sprintf("v2/tele/%s/#", u.model), 2, u.Callback)
mqtt.Subscribe(fmt.Sprintf("v2/stat/%s/#", u.model), 2, u.Callback)
} else {
mqtt.Subscribe(fmt.Sprintf("v2/tele/%s/%s/#", u.model, u.deviceId), 2, u.Callback)
mqtt.Subscribe(fmt.Sprintf("v2/stat/%s/%s/#", u.model, u.deviceId), 2, u.Callback)
}
}
return u
}
func (u *UstoneWifiSwitch) TurnOn() error {
if u.deviceId == "#" {
return nil
}
topic := fmt.Sprintf("v2/cmnd/%s/%s/Power0", u.model, u.deviceId)
publishACK := u.client.Publish(topic, 0, false, "1")
publishACK.WaitTimeout(time.Second)
return publishACK.Error()
}
func (u *UstoneWifiSwitch) TurnOff() error {
if u.deviceId == "#" {
return nil
}
topic := fmt.Sprintf("v2/cmnd/%s/%s/Power0", u.model, u.deviceId)
publishACK := u.client.Publish(topic, 0, false, "0")
publishACK.WaitTimeout(time.Second)
return publishACK.Error()
}
func (u *UstoneWifiSwitch) TurnOver() error {
if u.deviceId == "#" {
return nil
}
topic := fmt.Sprintf("v2/cmnd/%s/%s/Power0", u.model, u.deviceId)
publishACK := u.client.Publish(topic, 0, false, "2")
publishACK.WaitTimeout(time.Second)
return publishACK.Error()
}
func (u *UstoneWifiSwitch) SetPeriod(sec int64) error {
if u.deviceId == "#" {
return nil
}
topic := fmt.Sprintf("v2/cmnd/%s/%s/TelePeriod", u.model, u.deviceId)
publishACK := u.client.Publish(topic, 0, false, cast.ToString(sec))
publishACK.WaitTimeout(time.Second)
return publishACK.Error()
}
func (u *UstoneWifiSwitch) Operate(cmd string) error {
cmd = strings.ToLower(cmd)
if cmd == "on" {
return u.TurnOn()
} else if cmd == "off" {
return u.TurnOff()
} else if cmd == "over" {
return u.TurnOver()
} else if cmd == "keepalive" {
return u.KeepAlive()
}
return errors.New("不支持的命令[on|off|over|keepalive]")
}
func (u *UstoneWifiSwitch) KeepAlive() error {
return nil
}
func (u *UstoneWifiSwitch) Callback(client mqtt.Client, message mqtt.Message) {
u.Lock()
defer u.Unlock()
topic := message.Topic()
payload := message.Payload()
log.Debugf("[USTONE][%s] deviceId[%s] topic[%s] payloyad[%s]",
u.model, u.deviceId, topic, string(payload))
if u.callback != nil {
msgId := cast.ToString(message.MessageID())
if strings.HasSuffix(topic, "STATE") {
u.updateState(msgId, topic, payload)
} else if strings.HasSuffix(topic, "SENSOR") {
u.updateSensor(msgId, topic, payload)
} else if strings.HasSuffix(topic, "INFO1") || strings.HasSuffix(topic, "INFO2") || strings.HasSuffix(topic, "INFO3") {
u.updateInfo(msgId, topic, payload)
}
}
}
func (u *UstoneWifiSwitch) getDeviceId(topic string) string {
devId := u.deviceId
if devId == "#" {
fields := strings.Split(topic, "/")
if len(fields) >= 4 {
devId = fields[3]
}
}
return devId
}
func (u *UstoneWifiSwitch) updateInfo(msgId, topic string, payload []byte) {
mp := make(map[string]interface{})
if err := json.Unmarshal(payload, &mp); err != nil {
log.Errorf("topic[%s] paylooad[%s] error :%s", topic, string(payload), err.Error())
return
}
devId := u.getDeviceId(topic)
message := &Message{}
message.DeviceId = devId
message.Topic = topic
message.MsgTime = time.Now().Unix()
message.MsgId = msgId
message.Data = make(map[string]interface{})
if strings.HasSuffix(topic, "INFO1") {
i := cast.ToStringMap(mp["Info1"])
message.MsgType = UWSTypeInfo1
message.Data["module"] = cast.ToString(i["Module"])
message.Data["version"] = cast.ToString(i["Version"])
message.Data["raw"] = i
} else if strings.HasSuffix(topic, "INFO2") {
i := cast.ToStringMap(mp["Info2"])
message.MsgType = UWSTypeInfo2
message.Data["hostname"] = cast.ToString(i["Hostname"])
message.Data["ip_address"] = cast.ToString(i["IPAddress"])
message.Data["raw"] = i
} else if strings.HasSuffix(topic, "INFO3") {
i := cast.ToStringMap(mp["Info3"])
message.MsgType = UWSTypeInfo3
message.Data["boot_count"] = cast.ToString(i["BootCount"])
message.Data["raw"] = i
}
u.callback(message)
}
func (u *UstoneWifiSwitch) updateState(msgId, topic string, payload []byte) {
mp := make(map[string]interface{})
if err := json.Unmarshal(payload, &mp); err != nil {
log.Errorf("paylooad[%s] error :%s", string(payload), err.Error())
return
}
wifi := cast.ToStringMap(mp["Wifi"])
message := &Message{}
message.DeviceId = u.getDeviceId(topic)
message.Topic = topic
message.MsgType = UWSTypeState
message.MsgTime = time.Now().Unix()
message.MsgId = msgId
message.Data = make(map[string]interface{})
message.Data["power"] = cast.ToString(mp["POWER"])
message.Data["bssid"] = cast.ToString(wifi["BSSId"])
message.Data["ssid"] = cast.ToString(wifi["SSId"])
message.Data["raw"] = mp
u.callback(message)
}
func (u *UstoneWifiSwitch) updateSensor(msgId, topic string, payload []byte) {
mp := make(map[string]interface{})
if err := json.Unmarshal(payload, &mp); err != nil {
log.Errorf("paylooad[%s] error :%s", string(payload), err.Error())
return
}
energy := cast.ToStringMap(mp["ENERGY"])
totalStartTime, _ := time.ParseInLocation("2006-01-02T15:04:05", cast.ToString(energy["TotalStartTime"]), time.Local)
message := &Message{}
message.DeviceId = u.getDeviceId(topic)
message.Topic = topic
message.MsgType = UWSTypeSensor
message.MsgTime = time.Now().Unix()
message.MsgId = msgId
message.Data = make(map[string]interface{})
message.Data["total_start_time"] = totalStartTime.Unix()
message.Data["total_energy"] = cast.ToFloat64(energy["Total"])
message.Data["today_energy"] = cast.ToFloat64(energy["Today"])
message.Data["yesterday_energy"] = cast.ToFloat64(energy["Yesterday"])
message.Data["raw"] = energy
u.callback(message)
}