-
Notifications
You must be signed in to change notification settings - Fork 3
/
discover.go
105 lines (91 loc) · 2.47 KB
/
discover.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package bacnet
import (
"context"
"fmt"
"github.com/vanti-dev/gobacnet"
bactypes "github.com/vanti-dev/gobacnet/types"
"github.com/vanti-dev/sc-bos/pkg/driver/bacnet/config"
)
func (d *Driver) findDevice(ctx context.Context, device config.Device) (bactypes.Device, error) {
return FindDevice(ctx, d.client, device)
}
func FindDevice(ctx context.Context, client *gobacnet.Client, device config.Device) (bactypes.Device, error) {
fail := func(err error) (bactypes.Device, error) {
return bactypes.Device{}, err
}
if device.Comm == nil {
id := device.ID
is, err := client.WhoIs(ctx, int(id), int(id))
if err != nil {
return fail(err)
}
if len(is) == 0 {
return fail(fmt.Errorf("no devices found (via WhoIs) with id %d", id))
}
return is[0], nil
}
addr, err := device.Comm.ToAddress()
if err != nil {
return fail(err)
}
bacDevices, err := client.RemoteDevices(ctx, addr, device.ID)
if err != nil {
return fail(err)
}
return bacDevices[0], nil
}
func (d *Driver) fetchObjects(ctx context.Context, cfg config.Root, device config.Device, bacDevice bactypes.Device) (map[bactypes.ObjectID]configObject, error) {
objects := make(map[bactypes.ObjectID]configObject, len(device.Objects))
for _, object := range device.Objects {
objects[bactypes.ObjectID(object.ID)] = configObject{
co: object,
bo: &bactypes.Object{
ID: bactypes.ObjectID(object.ID),
},
}
}
discoverObjects := cfg.DiscoverObjects
if device.DiscoverObjects != nil {
discoverObjects = *device.DiscoverObjects
}
if discoverObjects {
hasObjects, err := d.client.Objects(ctx, bacDevice)
if err != nil {
return objects, fmt.Errorf("read objects %w", err)
}
for _, objectsOfType := range hasObjects.Objects {
for _, object := range objectsOfType {
object := object
if known, found := objects[object.ID]; found {
// copy any additional data into the object config
if known.co.Title == "" {
known.co.Title = firstNonEmpty(object.Description, object.Name)
}
known.bo = &object
objects[object.ID] = known
continue
}
objects[object.ID] = configObject{
co: config.Object{
ID: config.ObjectID(object.ID),
Title: firstNonEmpty(object.Description, object.Name),
},
bo: &object,
}
}
}
}
return objects, nil
}
type configObject struct {
co config.Object
bo *bactypes.Object
}
func firstNonEmpty(strs ...string) string {
for _, str := range strs {
if str != "" {
return str
}
}
return ""
}