1
1
import { Type , type TSchema , type Static } from '@sinclair/typebox'
2
2
import { slashless } from './slashless.js'
3
3
import { ValidationError , validatedFetch } from './validatedFetch.js'
4
-
5
- type Nullable < T > = { [ K in keyof T ] : T [ K ] | null }
6
-
7
- export const DeviceConfig = Type . Partial (
8
- Type . Object ( {
9
- activeMode : Type . Boolean ( ) , // e.g. false
10
- locationTimeout : Type . Number ( ) , // e.g. 300
11
- activeWaitTime : Type . Number ( ) , // e.g. 120
12
- movementResolution : Type . Number ( ) , // e.g. 120
13
- movementTimeout : Type . Number ( ) , // e.g. 3600
14
- accThreshAct : Type . Number ( ) , // e.g. 4
15
- accThreshInact : Type . Number ( ) , // e.g. 4
16
- accTimeoutInact : Type . Number ( ) , // e.g. 60
17
- nod : Type . Array (
18
- Type . Union ( [
19
- Type . Literal ( 'gnss' ) ,
20
- Type . Literal ( 'ncell' ) ,
21
- Type . Literal ( 'wifi' ) ,
22
- ] ) ,
23
- ) , // e.g. ['nod']
24
- } ) ,
25
- )
4
+ import { DeviceShadow } from './DeviceShadow.js'
26
5
27
6
const Device = Type . Object ( {
28
7
id : Type . String ( ) ,
29
- state : Type . Optional (
30
- Type . Object ( {
31
- reported : Type . Optional (
32
- Type . Object ( {
33
- config : Type . Optional ( DeviceConfig ) ,
34
- connection : Type . Optional (
35
- Type . Object ( {
36
- status : Type . Optional (
37
- Type . Union ( [
38
- Type . Literal ( 'connected' ) ,
39
- Type . Literal ( 'disconnected' ) ,
40
- ] ) ,
41
- ) ,
42
- } ) ,
43
- ) ,
44
- device : Type . Optional (
45
- Type . Object ( {
46
- deviceInfo : Type . Optional (
47
- Type . Partial (
48
- Type . Object ( {
49
- appVersion : Type . String ( ) , // e.g. '1.1.0'
50
- modemFirmware : Type . String ( ) , // e.g. 'mfw_nrf9160_1.3.4'
51
- imei : Type . String ( ) , // e.g. '352656108602296'
52
- board : Type . String ( ) , // e.g. 'thingy91_nrf9160'
53
- hwVer : Type . String ( ) , // e.g. 'nRF9160 SICA B1A'
54
- } ) ,
55
- ) ,
56
- ) ,
57
- } ) ,
58
- ) ,
59
- } ) ,
60
- ) ,
61
- desired : Type . Optional (
62
- Type . Object ( {
63
- config : Type . Optional ( DeviceConfig ) ,
64
- } ) ,
65
- ) ,
66
- version : Type . Number ( ) ,
67
- } ) ,
68
- ) ,
69
- firmware : Type . Optional (
70
- Type . Object ( {
71
- app : Type . Optional (
72
- Type . Object ( {
73
- name : Type . String ( { minLength : 1 } ) ,
74
- version : Type . String ( { minLength : 1 } ) ,
75
- } ) ,
76
- ) ,
77
- } ) ,
78
- ) ,
8
+ state : Type . Optional ( DeviceShadow ) ,
79
9
} )
80
10
81
11
const Page = < T extends TSchema > ( Item : T ) =>
@@ -118,10 +48,12 @@ export const devices = (
118
48
) => Promise <
119
49
{ error : Error | ValidationError } | { result : Static < typeof Device > }
120
50
>
121
- updateConfig : (
51
+ updateState : (
122
52
id : string ,
123
- config : Nullable < Omit < Static < typeof DeviceConfig > , 'nod' > > &
124
- Pick < Static < typeof DeviceConfig > , 'nod' > ,
53
+ state : {
54
+ desired ?: Record < string , any >
55
+ reported ?: Record < string , any >
56
+ } ,
125
57
) => Promise < { error : Error } | { success : boolean } >
126
58
register : (
127
59
devices : {
@@ -156,7 +88,7 @@ export const devices = (
156
88
) ,
157
89
get : async ( id ) =>
158
90
vf ( { resource : `devices/${ encodeURIComponent ( id ) } ` } , Device ) ,
159
- updateConfig : async ( id , config ) =>
91
+ updateState : async ( id , state ) =>
160
92
fetch (
161
93
`${ slashless ( endpoint ) } /v1/devices/${ encodeURIComponent ( id ) } /state` ,
162
94
{
@@ -165,11 +97,7 @@ export const devices = (
165
97
'Content-Type' : 'application/json' ,
166
98
} ,
167
99
method : 'PATCH' ,
168
- body : JSON . stringify ( {
169
- desired : {
170
- config,
171
- } ,
172
- } ) ,
100
+ body : JSON . stringify ( state ) ,
173
101
} ,
174
102
) . then ( ( res ) => {
175
103
if ( res . status >= 400 )
0 commit comments