88 lines
1.6 KiB
Go
88 lines
1.6 KiB
Go
package zendure
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
"dario.cat/mergo"
|
|
"github.com/evcc-io/evcc/plugin/mqtt"
|
|
"github.com/evcc-io/evcc/util"
|
|
)
|
|
|
|
var (
|
|
mu sync.Mutex
|
|
connections = make(map[string]*Connection)
|
|
)
|
|
|
|
type Connection struct {
|
|
log *util.Logger
|
|
data *util.Monitor[Data]
|
|
serial string
|
|
}
|
|
|
|
func NewConnection(region, account, serial string, timeout time.Duration) (*Connection, error) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
key := account + serial
|
|
if conn, ok := connections[key]; ok {
|
|
return conn, nil
|
|
}
|
|
|
|
log := util.NewLogger("zendure")
|
|
res, err := MqttCredentials(log, region, account, serial)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client, err := mqtt.NewClient(
|
|
log,
|
|
net.JoinHostPort(res.Data.MqttUrl, strconv.Itoa(res.Data.Port)), res.Data.AppKey, res.Data.Secret,
|
|
"", 0, false, "", "", "",
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
conn := &Connection{
|
|
log: log,
|
|
data: util.NewMonitor[Data](timeout),
|
|
serial: serial,
|
|
}
|
|
|
|
topic := res.Data.AppKey + "/#"
|
|
if err := client.Listen(topic, conn.handler); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
connections[key] = conn
|
|
|
|
return conn, nil
|
|
}
|
|
|
|
func (c *Connection) handler(data string) {
|
|
var res Payload
|
|
if err := json.Unmarshal([]byte(data), &res); err != nil {
|
|
c.log.ERROR.Println(err)
|
|
return
|
|
}
|
|
|
|
if res.Data == nil || res.Sn != c.serial {
|
|
return
|
|
}
|
|
|
|
c.data.SetFunc(func(v Data) Data {
|
|
if err := mergo.Merge(&v, res.Data, mergo.WithOverride); err != nil {
|
|
c.log.ERROR.Println(err)
|
|
}
|
|
|
|
return v
|
|
})
|
|
}
|
|
|
|
func (c *Connection) Data() (Data, error) {
|
|
return c.data.Get()
|
|
}
|