From 195c22a8bf97b190d3e16a360219e48d92b5ec12 Mon Sep 17 00:00:00 2001 From: Gary Date: Tue, 25 Jul 2023 23:25:51 +0800 Subject: [PATCH 1/3] feat: support list network interfaces --- plugin/http_server/http_api_server.go | 4 +++ plugin/http_server/model/dto.go | 8 +++++ plugin/http_server/system_api.go | 46 +++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 plugin/http_server/model/dto.go diff --git a/plugin/http_server/http_api_server.go b/plugin/http_server/http_api_server.go index 29b1ec42f..d177c0a09 100644 --- a/plugin/http_server/http_api_server.go +++ b/plugin/http_server/http_api_server.go @@ -271,6 +271,10 @@ func (hs *HttpApiServer) LoadRoute() { // hs.ginEngine.GET(url("uarts"), hs.addRoute(GetUarts)) // + // 网络适配器列表 + // + hs.ginEngine.GET(url("netInterfaces"), hs.addRoute(GetNetInterfaces)) + // // 获取服务启动时间 // hs.ginEngine.GET(url("startedAt"), hs.addRoute(StartedAt)) diff --git a/plugin/http_server/model/dto.go b/plugin/http_server/model/dto.go new file mode 100644 index 000000000..f707f6d94 --- /dev/null +++ b/plugin/http_server/model/dto.go @@ -0,0 +1,8 @@ +package model + +// NetInterfaceInfo 网络适配器信息 +type NetInterfaceInfo struct { + Name string `json:"name,omitempty"` + Mac string `json:"mac,omitempty"` + Addr string `json:"addr,omitempty"` +} diff --git a/plugin/http_server/system_api.go b/plugin/http_server/system_api.go index 6172d45e6..d137ad8b1 100644 --- a/plugin/http_server/system_api.go +++ b/plugin/http_server/system_api.go @@ -2,6 +2,8 @@ package httpserver import ( "fmt" + "github.com/hootrhino/rulex/plugin/http_server/model" + "net" "runtime" "strconv" "time" @@ -250,6 +252,15 @@ func GetUarts(c *gin.Context, hh *HttpApiServer) { c.JSON(common.HTTP_OK, common.OkWithData(ports)) } +func GetNetInterfaces(c *gin.Context, hh *HttpApiServer) { + interfaces, err := getAvailableInterfaces() + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + } else { + c.JSON(common.HTTP_OK, common.OkWithData(interfaces)) + } +} + /* * * 计算开机时间 @@ -274,3 +285,38 @@ func calculateCpuPercent(cpus []float64) float64 { value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", acc/float64(len(cpus))), 64) return value } + +func getAvailableInterfaces() ([]*model.NetInterfaceInfo, error) { + interfaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + netInterfaces := make([]*model.NetInterfaceInfo, 0, len(interfaces)) + for _, inter := range interfaces { + info := &model.NetInterfaceInfo{ + Name: inter.Name, + Mac: inter.HardwareAddr.String(), + } + addrs, err := inter.Addrs() + if err != nil { + continue + } + for i := range addrs { + addr := addrs[i].String() + cidr, _, _ := net.ParseCIDR(addr) + if cidr == nil { + continue + } + if cidr.To4() != nil { + // 找到第一个ipv4地址 + info.Addr = addr + break + } + } + netInterfaces = append(netInterfaces, info) + + } + + return netInterfaces, nil +} From c675a1232b38c2090af483489df67336c8b54135 Mon Sep 17 00:00:00 2001 From: Gary Date: Thu, 27 Jul 2023 01:04:24 +0800 Subject: [PATCH 2/3] feat: support BACnetIP Device --- device/generic_bacnetip_device.go | 203 ++++++++++++++++++++++++++++++ engine/engine.go | 6 + go.mod | 9 +- go.sum | 17 ++- typex/xdevice.go | 2 +- 5 files changed, 227 insertions(+), 10 deletions(-) create mode 100644 device/generic_bacnetip_device.go diff --git a/device/generic_bacnetip_device.go b/device/generic_bacnetip_device.go new file mode 100644 index 000000000..e857c3367 --- /dev/null +++ b/device/generic_bacnetip_device.go @@ -0,0 +1,203 @@ +package device + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "github.com/BeatTime/bacnet" + "github.com/BeatTime/bacnet/btypes" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" + "time" +) + +type bacnetIpCommonConfig struct { + Ip string `json:"ip,omitempty" title:"bacnet设备ip"` + Port int `json:"port,omitempty" title:"bacnet端口,通常是47808"` + LocalPort int `json:"localPort" title:"本地监听端口,填0表示默认47808(有的模拟器必须本地监听47808才能正常交互)"` +} + +type bacnetIpNodeConfig struct { + //IsMstp int `json:"isMstp,omitempty" title:"是否为mstp设备,若是则设备id和子网号必须填写"` + //DeviceId int `json:"deviceId,omitempty" title:"设备id"` + //Subnet int `json:"subnet,omitempty" title:"子网号"` + Tag string `json:"tag" validate:"required" title:"数据Tag" info:""` + Type int `json:"type,omitempty" title:"object类型"` + Id int `json:"id,omitempty" title:"object的id"` + + property btypes.PropertyData `json:"ignore"` +} + +type BacnetIpConfig struct { + CommonConfig bacnetIpCommonConfig `json:"commonConfig"` + NodeConfig []bacnetIpNodeConfig `json:"nodeConfig"` +} + +type GenericBacnetIpDevice struct { + typex.XStatus + status typex.DeviceState + RuleEngine typex.RuleX + bacnetIpConfig BacnetIpConfig + devId string + + // Bacnet + bacnetClient bacnet.Client + remoteDev btypes.Device +} + +func NewGenericBacnetIpDevice(e typex.RuleX) typex.XDevice { + g := new(GenericBacnetIpDevice) + g.RuleEngine = e + g.bacnetIpConfig = BacnetIpConfig{ + CommonConfig: bacnetIpCommonConfig{}, + NodeConfig: make([]bacnetIpNodeConfig, 0), + } + return g +} + +func (dev *GenericBacnetIpDevice) Init(devId string, configMap map[string]interface{}) error { + dev.devId = devId + err := utils.BindSourceConfig(configMap, &dev.bacnetIpConfig) + if err != nil { + return err + } + return nil +} + +func (dev *GenericBacnetIpDevice) Start(cctx typex.CCTX) error { + // 创建一个bacnetip的本地网络 + client, err := bacnet.NewClient(&bacnet.ClientBuilder{ + Ip: "0.0.0.0", + Port: dev.bacnetIpConfig.CommonConfig.LocalPort, + SubnetCIDR: 10, // 随便填一个,主要为了能够创建Client + }) + if err != nil { + return err + } + dev.bacnetClient = client + go client.ClientRun() + + // 将nodeConfig对应的配置信息 + for idx, v := range dev.bacnetIpConfig.NodeConfig { + tmp := btypes.PropertyData{ + Object: btypes.Object{ + ID: btypes.ObjectID{ + Type: btypes.ObjectType(v.Type), + Instance: btypes.ObjectInstance(v.Id), + }, + Properties: []btypes.Property{ + { + Type: btypes.PropPresentValue, // Present value + ArrayIndex: btypes.ArrayAll, + }, + }, + }, + } + dev.bacnetIpConfig.NodeConfig[idx].property = tmp + } + + mac := make([]byte, 6) + fmt.Sscanf(dev.bacnetIpConfig.CommonConfig.Ip, "%d.%d.%d.%d", &mac[0], &mac[1], &mac[2], &mac[3]) + port := uint16(dev.bacnetIpConfig.CommonConfig.Port) + mac[4] = byte(port >> 8) + mac[5] = byte(port & 0x00FF) + dev.remoteDev = btypes.Device{ + Addr: btypes.Address{ + MacLen: 6, + Mac: mac, + }, + } + + go func(ctx context.Context) { + ticker := time.NewTicker(10 * time.Second) + for { + select { + case <-ctx.Done(): + { + ticker.Stop() + return + } + default: + { + } + } + + read, err2 := dev.read() + if err2 != nil { + glogger.GLogger.Error(err2) + } else { + dev.RuleEngine.WorkDevice(dev.Details(), string(read)) + } + <-ticker.C + } + }(cctx.Ctx) + + dev.status = typex.DEV_UP + return nil +} + +func (dev *GenericBacnetIpDevice) OnRead(cmd []byte, data []byte) (int, error) { + read, err := dev.read() + if err != nil { + return 0, err + } + len := copy(data, read) + return len, nil +} + +func (dev *GenericBacnetIpDevice) read() ([]byte, error) { + retMap := map[string]string{} + for _, v := range dev.bacnetIpConfig.NodeConfig { + property, err := dev.bacnetClient.ReadProperty(dev.remoteDev, v.property) + if err != nil { + glogger.GLogger.Error("read failed. tag = %v, err=%v", v.Tag, err) + continue + } + value := fmt.Sprintf("%v", property.Object.Properties[0].Data) + retMap[v.Tag] = value + } + bytes, _ := json.Marshal(retMap) + glogger.GLogger.Debugf("%v", retMap) + return bytes, nil +} + +func (dev *GenericBacnetIpDevice) OnWrite(cmd []byte, data []byte) (int, error) { + //TODO implement me + return 0, errors.New("not Support") +} + +func (dev *GenericBacnetIpDevice) OnCtrl(cmd []byte, args []byte) ([]byte, error) { + return nil, errors.New("not Support") +} + +func (dev *GenericBacnetIpDevice) Status() typex.DeviceState { + return dev.status +} + +func (dev *GenericBacnetIpDevice) Stop() { + if dev.bacnetClient != nil { + dev.bacnetClient.Close() + } +} + +func (dev *GenericBacnetIpDevice) Property() []typex.DeviceProperty { + return []typex.DeviceProperty{} +} + +func (dev *GenericBacnetIpDevice) Details() *typex.Device { + return dev.RuleEngine.GetDevice(dev.PointId) +} + +func (dev *GenericBacnetIpDevice) SetState(state typex.DeviceState) { + dev.status = state +} + +func (dev *GenericBacnetIpDevice) Driver() typex.XExternalDriver { + return nil +} + +func (dev *GenericBacnetIpDevice) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { + return typex.DCAResult{} +} diff --git a/engine/engine.go b/engine/engine.go index 60b4564ee..ff09ec30f 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -592,6 +592,12 @@ func (e *RuleEngine) InitDeviceTypeManager() error { NewDevice: device.NewAISDevice, }, ) + e.DeviceTypeManager.Register(typex.GENERIC_BACNET_IP, + &typex.XConfig{ + Engine: e, + NewDevice: device.NewGenericBacnetIpDevice, + }, + ) return nil } diff --git a/go.mod b/go.mod index 1da40b2df..74adcf1da 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/hootrhino/rulex go 1.18 require ( + github.com/BeatTime/bacnet v0.2.0-gary github.com/DrmagicE/gmqtt v0.5.0 github.com/Kowiste/ProfinetServer v0.0.0-20200929093941-9c422ae1f008 github.com/adrianmo/go-nmea v1.8.0 @@ -37,7 +38,7 @@ require ( github.com/rs/zerolog v1.28.0 github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil/v3 v3.23.5 - github.com/sirupsen/logrus v1.9.2 + github.com/sirupsen/logrus v1.9.3 github.com/suapapa/go_eddystone v1.3.1 github.com/tbrandon/mbserver v0.0.0-20211210035124-daf3c8c4269f github.com/thinkgos/go-iecp5 v1.2.1 @@ -47,11 +48,12 @@ require ( github.com/wwhai/ntp v0.3.0 github.com/wwhai/tarmserial v1.0.0 github.com/wwhai/tinycache v0.0.0-20191004192108-46f407853014 + github.com/xuri/excelize/v2 v2.7.1 go.bug.st/serial v1.5.0 go.mongodb.org/mongo-driver v1.11.6 go.uber.org/zap v1.15.0 golang.org/x/crypto v0.9.0 - golang.org/x/sys v0.8.0 + golang.org/x/sys v0.10.0 google.golang.org/grpc v1.55.0 google.golang.org/protobuf v1.30.0 gopkg.in/ini.v1 v1.67.0 @@ -66,7 +68,6 @@ require ( github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect - github.com/xuri/excelize/v2 v2.7.1 // indirect github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect ) @@ -144,7 +145,7 @@ require ( golang.org/x/arch v0.3.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.2.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20230525234025-438c736192d0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a // indirect diff --git a/go.sum b/go.sum index 64e0a9852..221fefd42 100644 --- a/go.sum +++ b/go.sum @@ -360,6 +360,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BeatTime/bacnet v0.2.0-gary h1:2+ZMrgzmrRovVXBCQ+djXIWUQOySfyfm+hi0kD/0bXI= +github.com/BeatTime/bacnet v0.2.0-gary/go.mod h1:TnVpYMUX0Xgt5/VfJ2aT30QK2QM5H1+ZeXAVauKkjvA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -458,8 +460,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= @@ -859,8 +861,10 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= -github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -1014,6 +1018,7 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1228,8 +1233,9 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -1248,8 +1254,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/typex/xdevice.go b/typex/xdevice.go index 4e34c102f..9a58d8f9c 100644 --- a/typex/xdevice.go +++ b/typex/xdevice.go @@ -53,7 +53,7 @@ const ( GENERIC_OPCUA DeviceType = "GENERIC_OPCUA" // 通用OPCUA GENERIC_CAMERA DeviceType = "GENERIC_CAMERA" // 通用摄像头 GENERIC_AIS DeviceType = "GENERIC_AIS" // 通用AIS - + GENERIC_BACNET_IP DeviceType = "GENERIC_BACNET_IP" // 通用BacnetIP ) // 设备元数据, 本质是保存在配置里面的数据的一个内存映射实例 From 47f96040a532226fb61e799e78443bc897d0cd3b Mon Sep 17 00:00:00 2001 From: Gary Date: Sun, 6 Aug 2023 23:01:03 +0800 Subject: [PATCH 3/3] feat: support BACnetIP Device --- device/generic_bacnetip_device.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/device/generic_bacnetip_device.go b/device/generic_bacnetip_device.go index e857c3367..70dc64907 100644 --- a/device/generic_bacnetip_device.go +++ b/device/generic_bacnetip_device.go @@ -17,15 +17,16 @@ type bacnetIpCommonConfig struct { Ip string `json:"ip,omitempty" title:"bacnet设备ip"` Port int `json:"port,omitempty" title:"bacnet端口,通常是47808"` LocalPort int `json:"localPort" title:"本地监听端口,填0表示默认47808(有的模拟器必须本地监听47808才能正常交互)"` + Interval int `json:"interval" title:"采集间隔,单位秒"` } type bacnetIpNodeConfig struct { - //IsMstp int `json:"isMstp,omitempty" title:"是否为mstp设备,若是则设备id和子网号必须填写"` - //DeviceId int `json:"deviceId,omitempty" title:"设备id"` - //Subnet int `json:"subnet,omitempty" title:"子网号"` - Tag string `json:"tag" validate:"required" title:"数据Tag" info:""` - Type int `json:"type,omitempty" title:"object类型"` - Id int `json:"id,omitempty" title:"object的id"` + IsMstp int `json:"isMstp,omitempty" title:"是否为mstp设备,若是则设备id和子网号必须填写"` + DeviceId int `json:"deviceId,omitempty" title:"设备id"` + Subnet int `json:"subnet,omitempty" title:"子网号"` + Tag string `json:"tag" validate:"required" title:"数据Tag"` + Type int `json:"type,omitempty" title:"object类型"` + Id int `json:"id,omitempty" title:"object的id"` property btypes.PropertyData `json:"ignore"` } @@ -111,7 +112,8 @@ func (dev *GenericBacnetIpDevice) Start(cctx typex.CCTX) error { } go func(ctx context.Context) { - ticker := time.NewTicker(10 * time.Second) + interval := dev.bacnetIpConfig.CommonConfig.Interval + ticker := time.NewTicker(time.Duration(interval) * time.Second) for { select { case <-ctx.Done():