This commit is contained in:
tfl
2024-08-21 17:35:50 +08:00
parent 34ea7472b7
commit dd5b38b4e3
24 changed files with 328 additions and 133 deletions

View File

@@ -11,6 +11,10 @@ func ComputeIfAbsentProductRule(key string, fun func(any) (any, error)) (any, er
return ProductCache.ComputeIfAbsent(key, fun)
}
func GetProductRule(key string) (any, bool) {
return ProductCache.Get(key)
}
func DelProductRule(key string) {
ProductCache.Delete(key)
}

35
pkg/device_rpc/rpc.go Normal file
View File

@@ -0,0 +1,35 @@
package devicerpc
import (
"errors"
"fmt"
"time"
"github.com/kakuilan/kgo"
)
type RpcPayload struct {
Method string `json:"method"`
Params any `json:"params"`
}
func (rp *RpcPayload) ToMap() map[string]any {
data, err := kgo.KConv.Struct2Map(rp, "")
if err != nil {
return nil
}
return data
}
// GetRequestResult 处理设备端请求服务端方法
func (rpc RpcPayload) GetRequestResult() (string, error) {
//TODO 此处处理设备的请求参数逻辑
//自己定义请求逻辑
if rpc.Params == "getCurrentTime" {
unix := time.Now().Unix()
msg := fmt.Sprintf("%d", unix)
return msg, nil
}
// 获取属性 ...
return "", errors.New("未获取到请求方法")
}

View File

@@ -19,17 +19,19 @@ type RuleChainInstance struct {
}
func NewRuleChainInstance(ruleID string, data []byte) (*RuleChainInstance, error) {
instance := &RuleChainInstance{}
manifest, err := manifest.New(data)
if err != nil {
logrus.WithError(err).Errorf("invalid manifest file")
return nil, err
}
withManifest, err := newInstanceWithManifest(manifest)
instance, err = newInstanceWithManifest(manifest)
if err != nil {
return nil, err
}
withManifest.ruleID = ruleID
return withManifest, nil
instance.ruleID = ruleID
return instance, nil
}
func newInstanceWithManifest(m *manifest.Manifest) (*RuleChainInstance, error) {

View File

@@ -2,16 +2,22 @@ package nodes
import (
"errors"
"pandax/apps/device/services"
"pandax/iothub/client/mqttclient"
"pandax/iothub/client/tcpclient"
"pandax/iothub/client/udpclient"
"pandax/kit/utils"
devicerpc "pandax/pkg/device_rpc"
"pandax/pkg/global"
"pandax/pkg/global/model"
"pandax/pkg/rule_engine/message"
"time"
"github.com/kakuilan/kgo"
)
type rpcRequestFromDeviceNode struct {
bareNode
RequestId int `json:"requestId"`
RequestId string `json:"requestId"`
}
type rpcRequestFromDeviceFactory struct{}
@@ -34,42 +40,55 @@ func (n *rpcRequestFromDeviceNode) Handle(msg *message.Message) error {
if msg.Msg.GetValue("method") == nil || msg.Msg.GetValue("params") == nil {
return errors.New("指令请求格式错误")
}
var rpcp = model.RpcPayload{
var rpcp = devicerpc.RpcPayload{
Method: msg.Msg.GetValue("method").(string),
Params: msg.Msg.GetValue("params"),
}
result, err := rpcp.GetRequestResult()
if err != nil {
if failureLableNode != nil {
n.Debug(msg, message.DEBUGOUT, err.Error())
return failureLableNode.Handle(msg)
} else {
return err
var err error
// 指令下发响应
if rpcp.Method == "cmdResp" {
if requestId, ok := msg.Metadata.GetValue("requestId").(string); ok {
services.DeviceCmdLogModelDao.UpdateResp(requestId, kgo.KConv.ToStr(rpcp.Params), time.Now().Format("2006-01-02 15:04:05"))
}
}
// 判断设备协议,根据不通协议,发送不通内容
deviceProtocol := global.MQTTProtocol
if msg.Metadata.GetValue("deviceProtocol") != nil && msg.Metadata.GetValue("deviceProtocol").(string) != "" {
deviceProtocol = msg.Metadata.GetValue("deviceProtocol").(string)
}
deviceId := msg.Metadata.GetValue("deviceId").(string)
if deviceProtocol == global.MQTTProtocol {
rpc := &mqttclient.RpcRequest{}
RequestId := n.RequestId
if RequestId == 0 {
if msg.Metadata.GetValue("requestId") == nil {
rpc.GetRequestId()
} else {
result, err := rpcp.GetRequestResult()
if err != nil {
if failureLableNode != nil {
n.Debug(msg, message.DEBUGOUT, err.Error())
return failureLableNode.Handle(msg)
} else {
RequestId = int(msg.Metadata.GetValue("requestId").(float64))
return err
}
} else {
rpc.RequestId = RequestId
}
err = rpc.Pub(deviceId, result)
}
if deviceProtocol == global.TCPProtocol {
err = tcpclient.Send(deviceId, result)
// 判断设备协议,根据不通协议,发送不通内容
deviceProtocol := global.MQTTProtocol
if msg.Metadata.GetValue("deviceProtocol") != nil && msg.Metadata.GetValue("deviceProtocol").(string) != "" {
deviceProtocol = msg.Metadata.GetValue("deviceProtocol").(string)
}
deviceId := msg.Metadata.GetValue("deviceId").(string)
if deviceProtocol == global.MQTTProtocol || deviceProtocol == global.CoAPProtocol || deviceProtocol == global.LwM2MProtocol {
rpc := &mqttclient.RpcRequest{}
RequestId := n.RequestId
if RequestId == "" {
if msg.Metadata.GetValue("requestId") == nil {
rpc.RequestId = utils.GenerateID()
} else {
rpc.RequestId = msg.Metadata.GetValue("requestId").(string)
}
} else {
rpc.RequestId = RequestId
}
err = rpc.Pub(deviceId, result)
}
if deviceProtocol == global.TCPProtocol {
err = tcpclient.Send(deviceId, result)
}
if deviceProtocol == global.UDPProtocol {
err = udpclient.Send(deviceId, result)
}
}
if err != nil {
n.Debug(msg, message.DEBUGOUT, err.Error())
if failureLableNode != nil {

View File

@@ -3,11 +3,18 @@ package nodes
import (
"encoding/json"
"errors"
"pandax/apps/device/entity"
"pandax/apps/device/services"
"pandax/iothub/client/mqttclient"
"pandax/iothub/client/tcpclient"
"pandax/iothub/client/udpclient"
"pandax/kit/utils"
"pandax/pkg/global"
"pandax/pkg/global/model"
"pandax/pkg/rule_engine/message"
"time"
"github.com/kakuilan/kgo"
)
type rpcRequestToDeviceNode struct {
@@ -34,11 +41,24 @@ func (n *rpcRequestToDeviceNode) Handle(msg *message.Message) error {
if msg.Msg.GetValue("method") == nil || msg.Msg.GetValue("params") == nil {
return errors.New("指令下发格式错误")
}
deviceId := msg.Metadata.GetValue("deviceId").(string)
// 创建请求格式
var datas = model.RpcPayload{
Method: msg.Msg.GetValue("method").(string),
Params: msg.Msg.GetValue("params"),
}
payload, _ := json.Marshal(datas)
// 构建指令记录
var data entity.DeviceCmdLog
data.Id = utils.GenerateID()
data.DeviceId = deviceId
data.CmdName = datas.Method
data.CmdContent = kgo.KConv.ToStr(datas.Params)
data.Mode = msg.Metadata.GetValue("mode").(string)
data.State = "2"
data.RequestTime = time.Now().Format("2006-01-02 15:04:05")
mode := mqttclient.SingleMode
if n.Timeout > 0 {
mode = mqttclient.DoubleMode
@@ -49,16 +69,20 @@ func (n *rpcRequestToDeviceNode) Handle(msg *message.Message) error {
deviceProtocol = msg.Metadata.GetValue("deviceProtocol").(string)
}
var err error
deviceId := msg.Metadata.GetValue("deviceId").(string)
if deviceProtocol == global.MQTTProtocol {
var rpc = &mqttclient.RpcRequest{Mode: mode, Timeout: n.Timeout}
rpc.GetRequestId()
if deviceProtocol == global.MQTTProtocol || deviceProtocol == global.CoAPProtocol || deviceProtocol == global.LwM2MProtocol {
var rpc = &mqttclient.RpcRequest{Mode: mode, Timeout: n.Timeout, RequestId: data.Id}
err = rpc.RequestCmd(deviceId, string(payload))
}
if deviceProtocol == global.TCPProtocol {
err = tcpclient.Send(deviceId, string(payload))
}
if deviceProtocol == global.UDPProtocol {
err = udpclient.Send(deviceId, string(payload))
}
if err != nil {
data.State = "1"
services.DeviceCmdLogModelDao.Insert(data)
n.Debug(msg, message.DEBUGOUT, err.Error())
if failureLableNode != nil {
return failureLableNode.Handle(msg)
@@ -66,7 +90,10 @@ func (n *rpcRequestToDeviceNode) Handle(msg *message.Message) error {
return err
}
}
if successLableNode != nil {
data.State = "0"
services.DeviceCmdLogModelDao.Insert(data)
n.Debug(msg, message.DEBUGOUT, "")
return successLableNode.Handle(msg)
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
)
const connectTableName = "events"
const connectTableName = "device_events"
type Events struct {
Ts string `json:"ts"`

View File

@@ -7,7 +7,7 @@ import (
"github.com/kakuilan/kgo"
)
const logTableName = "logs"
const logTableName = "device_logs"
// 日志 TDengine
type TdLog struct {
@@ -39,7 +39,7 @@ func (s *TdEngine) InsertLog(log *TdLog) (err error) {
func (s *TdEngine) ClearLog() (err error) {
ts := time.Now().Add(-7 * 24 * time.Hour).Format("2006-01-02")
sql := fmt.Sprintf("DELETE FROM %s WHERE ts < ?", logTableName)
sql := fmt.Sprintf("DELETE FROM %s.%s WHERE ts < ?", s.dbName, logTableName)
_, err = s.db.Exec(sql, ts)
return

View File

@@ -3,12 +3,14 @@ package websocket
import (
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
"net/http"
"pandax/apps/device/entity"
"pandax/apps/device/util"
devicerpc "pandax/pkg/device_rpc"
"pandax/pkg/global"
"strings"
"github.com/gorilla/websocket"
)
var upGrader = websocket.Upgrader{
@@ -65,10 +67,11 @@ func OnMessage(ws *Websocket, msg string) {
return
}
//2. 根据设备下发属性更改
err = util.BuildRunDeviceRpc(vtsa.TwinId, "single", map[string]interface{}{
"method": "setAttributes",
"params": vtsa.Attrs,
})
rpc := devicerpc.RpcPayload{
Method: "setAttributes",
Params: vtsa.Attrs,
}
err = util.BuildRunDeviceRpc(vtsa.TwinId, "single", rpc)
if err != nil {
global.Log.Error("命令发送失败", err)
sendMessages("02", "命令发送失败", screenId)