234 lines
6.3 KiB
Go
234 lines
6.3 KiB
Go
|
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)
|
||
|
}
|