4
4
"encoding/json"
5
5
"io"
6
6
"io/ioutil"
7
+ "strconv"
7
8
"sync"
8
9
"time"
9
10
34
35
ErrResponseChannelNotExist = errors .New ("response channel not exist" )
35
36
ErrAccessConfigNotExist = errors .New ("access config not exist" )
36
37
ErrPropsConfigNotExist = errors .New ("properties config not exist" )
38
+ ErrDeviceNotExist = errors .New ("device not exist" )
39
+ ErrTypeNotSupported = errors .New ("type not supported" )
40
+ )
41
+
42
+ const (
43
+ TypeInt16 = "int16"
44
+ TypeInt32 = "int32"
45
+ TypeInt64 = "int64"
46
+ TypeFloat32 = "float32"
47
+ TypeFloat64 = "float64"
48
+ TypeBool = "bool"
49
+ TypeString = "string"
37
50
)
38
51
39
52
type DeltaCallback func (* DeviceInfo , v1.Delta ) error
@@ -49,8 +62,8 @@ type Context interface {
49
62
Online (device * DeviceInfo ) error
50
63
Offline (device * DeviceInfo ) error
51
64
GetDriverConfig () string
52
- GetAccessConfig () map [string ]string
53
- GetDeviceAccessConfig (device * DeviceInfo ) (string , error )
65
+ GetAccessConfig () map [string ]AccessConfig
66
+ GetDeviceAccessConfig (device * DeviceInfo ) (* AccessConfig , error )
54
67
GetPropertiesConfig () map [string ][]DeviceProperty
55
68
GetDevicePropertiesConfig (device * DeviceInfo ) ([]DeviceProperty , error )
56
69
Start ()
@@ -69,7 +82,7 @@ type DmCtx struct {
69
82
msgChs map [string ]chan * v1.Message
70
83
driverConfig string
71
84
propsConfig map [string ][]DeviceProperty
72
- accessConfig map [string ]string
85
+ accessConfig map [string ]AccessConfig
73
86
}
74
87
75
88
func NewContext (confFile string ) Context {
@@ -146,13 +159,16 @@ func (c *DmCtx) processDelta(msg *v1.Message) error {
146
159
return nil
147
160
}
148
161
var delta v1.Delta
149
- if err := msg .Content .Unmarshal (& delta ); err != nil {
162
+ if err := msg .Content .ExactUnmarshal (& delta ); err != nil {
150
163
return errors .Trace (err )
151
164
}
152
165
dev , ok := c .devices [deviceName ]
153
166
if ! ok {
154
- c .log .Warn ("delta callback can not find device" , log .Any ("device" , deviceName ))
155
- return nil
167
+ return errors .Trace (ErrDeviceNotExist )
168
+ }
169
+ delta , err := c .parsePropertyValues (deviceName , delta )
170
+ if err != nil {
171
+ return errors .Trace (err )
156
172
}
157
173
if err := c .deltaCb (& dev , delta ); err != nil {
158
174
return errors .Trace (err )
@@ -182,8 +198,8 @@ func (c *DmCtx) processEvent(msg *v1.Message) error {
182
198
}
183
199
184
200
func (c * DmCtx ) processResponse (msg * v1.Message ) error {
185
- device := msg .Metadata [KeyDevice ]
186
- val , ok := c .response .Load (device )
201
+ deviceName := msg .Metadata [KeyDevice ]
202
+ val , ok := c .response .Load (deviceName )
187
203
if ! ok {
188
204
return errors .Trace (ErrResponseChannelNotExist )
189
205
}
@@ -192,12 +208,21 @@ func (c *DmCtx) processResponse(msg *v1.Message) error {
192
208
return errors .Trace (ErrInvalidChannel )
193
209
}
194
210
var shad * DeviceShadow
195
- if err := msg .Content .Unmarshal (& shad ); err != nil {
211
+ if err := msg .Content .ExactUnmarshal (& shad ); err != nil {
196
212
return errors .Trace (err )
197
213
}
198
214
if ! ok {
199
215
return errors .Trace (ErrInvalidMessage )
200
216
}
217
+ var err error
218
+ shad .Report , err = c .parsePropertyValues (deviceName , shad .Report )
219
+ if err != nil {
220
+ return errors .Trace (err )
221
+ }
222
+ shad .Desire , err = c .parsePropertyValues (deviceName , shad .Desire )
223
+ if err != nil {
224
+ return errors .Trace (err )
225
+ }
201
226
select {
202
227
case ch <- shad :
203
228
default :
@@ -351,15 +376,15 @@ func (c *DmCtx) Offline(info *DeviceInfo) error {
351
376
func (c * DmCtx ) GetDriverConfig () string {
352
377
return c .driverConfig
353
378
}
354
- func (c * DmCtx ) GetAccessConfig () map [string ]string {
379
+ func (c * DmCtx ) GetAccessConfig () map [string ]AccessConfig {
355
380
return c .accessConfig
356
381
}
357
382
358
- func (c * DmCtx ) GetDeviceAccessConfig (device * DeviceInfo ) (string , error ) {
383
+ func (c * DmCtx ) GetDeviceAccessConfig (device * DeviceInfo ) (* AccessConfig , error ) {
359
384
if cfg , ok := c .accessConfig [device .Name ]; ok {
360
- return cfg , nil
385
+ return & cfg , nil
361
386
} else {
362
- return "" , ErrAccessConfigNotExist
387
+ return nil , ErrAccessConfigNotExist
363
388
}
364
389
}
365
390
@@ -382,3 +407,72 @@ func unmarshalYAML(file string, out interface{}) error {
382
407
}
383
408
return yaml .Unmarshal (bs , out )
384
409
}
410
+
411
+ func (c * DmCtx ) parsePropertyValues (devName string , props map [string ]interface {}) (map [string ]interface {}, error ) {
412
+ res := make (map [string ]interface {})
413
+ vals , ok := c .propsConfig [devName ]
414
+ if ! ok {
415
+ return nil , errors .Trace (ErrDeviceNotExist )
416
+ }
417
+ cfgs := make (map [string ]DeviceProperty )
418
+ for _ , val := range vals {
419
+ cfgs [val .Name ] = val
420
+ }
421
+ for key , val := range props {
422
+ if cfg , ok := cfgs [key ]; ok {
423
+ pVal , err := parsePropertyValue (cfg .Type , val )
424
+ if err != nil {
425
+ return nil , errors .Trace (err )
426
+ }
427
+ res [key ] = pVal
428
+ } else {
429
+ return nil , errors .Trace (ErrPropsConfigNotExist )
430
+ }
431
+ }
432
+ return res , nil
433
+ }
434
+
435
+ func parsePropertyValue (tpy string , val interface {}) (interface {}, error ) {
436
+ // it is json.Number (string actually) when val is number
437
+ switch tpy {
438
+ case TypeInt16 :
439
+ num , _ := val .(json.Number )
440
+ i , err := strconv .ParseInt (num .String (), 10 , 16 )
441
+ if err != nil {
442
+ return nil , errors .Trace (err )
443
+ }
444
+ return int16 (i ), nil
445
+ case TypeInt32 :
446
+ num , _ := val .(json.Number )
447
+ i , err := strconv .ParseInt (num .String (), 10 , 32 )
448
+ if err != nil {
449
+ return nil , errors .Trace (err )
450
+ }
451
+ return int32 (i ), nil
452
+ case TypeInt64 :
453
+ num , _ := val .(json.Number )
454
+ i , err := strconv .ParseInt (num .String (), 10 , 64 )
455
+ if err != nil {
456
+ return nil , errors .Trace (err )
457
+ }
458
+ return i , nil
459
+ case TypeFloat32 :
460
+ num , _ := val .(json.Number )
461
+ f , err := strconv .ParseFloat (num .String (), 32 )
462
+ if err != nil {
463
+ return nil , errors .Trace (err )
464
+ }
465
+ return float32 (f ), nil
466
+ case TypeFloat64 :
467
+ num , _ := val .(json.Number )
468
+ f , err := strconv .ParseFloat (num .String (), 64 )
469
+ if err != nil {
470
+ return nil , errors .Trace (err )
471
+ }
472
+ return f , nil
473
+ case TypeBool , TypeString :
474
+ return val , nil
475
+ default :
476
+ return nil , errors .Trace (ErrTypeNotSupported )
477
+ }
478
+ }
0 commit comments