143 lines
3.9 KiB
Go
143 lines
3.9 KiB
Go
package device
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"src.dualinventive.com/go/cp3000-interface/internal/statusupdate"
|
|
"src.dualinventive.com/go/dinet/rpc"
|
|
"src.dualinventive.com/go/lib/cp3000"
|
|
)
|
|
|
|
// CrtmGateway is a ZKL 3000 RC device
|
|
type CrtmGateway struct {
|
|
*Base
|
|
|
|
children map[string]*cp3000.ChildRouter
|
|
versionKeyFW rpc.VersionKey
|
|
versionKeyHW rpc.VersionKey
|
|
}
|
|
|
|
func (z *CrtmGateway) construct() {
|
|
z.children = make(map[string]*cp3000.ChildRouter)
|
|
z.decoder = statusupdate.NewUpdateDecoder(z.dev.Logger())
|
|
z.dev.Subscribe(rpc.ClassMethodSensorInfo, rpc.MsgTypeRequest, z.sensorInfo)
|
|
z.dev.AddConfig(rpc.ConfigEndpoint, z.configGetEndpoint, z.configSetEndpoint, nil)
|
|
}
|
|
|
|
func (z *CrtmGateway) init() {
|
|
}
|
|
|
|
// Close closes the connection to DI-Net and also for its children
|
|
func (z *CrtmGateway) Close() error {
|
|
for _, dev := range z.children {
|
|
if err := dev.Close(); err != nil {
|
|
z.dev.Logger().WithError(err).Warning("cannot close child")
|
|
}
|
|
}
|
|
return z.Base.Close()
|
|
}
|
|
|
|
// Statusupdate is a callback for the status message
|
|
// Suppress the linter because statusUpdateCmd needs to satisfy the interface
|
|
//nolint: unparam
|
|
func (z *CrtmGateway) statusUpdateCmd(r cp3000.Router, args []string) error {
|
|
old := z.decoder.StatusUpdate()
|
|
err := z.decoder.Decode(args)
|
|
if err != nil {
|
|
z.dev.Logger().WithError(err).Warning("status-decoder failed")
|
|
return nil
|
|
}
|
|
s := z.decoder.StatusUpdate()
|
|
|
|
data := []*rpc.ResultValueItem{}
|
|
data = old.CheckBattery1(data, s)
|
|
data = old.CheckBattery1State(data, s)
|
|
data = old.CheckRSSI(data, s)
|
|
data = old.CheckBER(data, s)
|
|
data = old.CheckCRTMTemperature1(data, s)
|
|
|
|
if len(data) > 0 {
|
|
z.dev.Logger().WithField("count", len(data)).Debug("send sensor data")
|
|
err = z.dev.Send(&rpc.Msg{
|
|
ClassMethod: rpc.ClassMethodSensorData,
|
|
Type: rpc.MsgTypePublish,
|
|
Result: rpc.NewResult(data),
|
|
})
|
|
}
|
|
if pErr := z.dev.SendDeviceData(); pErr != nil {
|
|
return pErr
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (z *CrtmGateway) gatewayCmd(r cp3000.Router, args []string) error {
|
|
// We need at least the IMEI and a command
|
|
if len(args[0]) > 2 {
|
|
c, ok := z.children[args[0]]
|
|
if !ok {
|
|
var err error
|
|
z.dev.Logger().WithField("imei", args[0]).Info("registering child")
|
|
c = cp3000.NewChildRouter(z.dev.Logger(), args[0], r)
|
|
|
|
child, err := Register(z.dev, z.Base.repo, c, args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := child.RegisterCallbacks(); err != nil {
|
|
return err
|
|
}
|
|
|
|
z.children[args[0]] = c
|
|
}
|
|
return c.ChildCommand(cp3000.Command(args[1]), args[2:]...)
|
|
}
|
|
return errors.New("invalid usage")
|
|
}
|
|
|
|
// Versions returns the firmware and hardware versions
|
|
func (z *CrtmGateway) Versions() (rpc.VersionMap, rpc.ErrorCode) {
|
|
wcpu, rpcerr := z.requestVersion("FW-WCPU")
|
|
if rpcerr != rpc.Ok {
|
|
return nil, rpcerr
|
|
}
|
|
return rpc.VersionMap{
|
|
z.versionKeyFW: wcpu,
|
|
z.versionKeyHW: z.hwVersion,
|
|
}, rpc.Ok
|
|
}
|
|
|
|
// TimeoutDuration returns when the device should be considered offline
|
|
func (z *CrtmGateway) TimeoutDuration() time.Duration {
|
|
return time.Minute
|
|
}
|
|
|
|
// Transport returns the transportation type
|
|
func (z *CrtmGateway) Transport() (interface{}, rpc.ErrorCode) {
|
|
return z.cp3000Transport()
|
|
}
|
|
|
|
// sensorInfo returns all the sensor information
|
|
func (z *CrtmGateway) sensorInfo(req *rpc.Msg) *rpc.Msg {
|
|
rep := req.CreateReply()
|
|
rep.Result = rpc.NewResult([]rpc.ResultInfoItem{
|
|
rpc.SensorBattery1Voltage.Info(),
|
|
rpc.SensorBattery1State.Info(),
|
|
rpc.SensorRSSI.Info(),
|
|
rpc.SensorBER.Info(),
|
|
rpc.GatewaySensorTemperature1.Info(),
|
|
})
|
|
return rep
|
|
}
|
|
|
|
// RegisterCallbacks registers additional callbacks for CRTM 3000 devices once they authenticated
|
|
func (z *CrtmGateway) RegisterCallbacks() error {
|
|
z.client.Register(cp3000.CommandWatchdog, z.heartbeatCmd)
|
|
z.client.Register(cp3000.CommandGateway, z.gatewayCmd)
|
|
z.client.Register(cp3000.CommandUpdate, z.statusUpdateCmd)
|
|
z.client.Register(cp3000.CommandSync, z.syncCmd)
|
|
z.client.Register(cp3000.CommandExit, z.exitCmd)
|
|
return nil
|
|
}
|