@hello.nrfcloud.com/proto-map 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +122 -0
  3. package/dist/generator/addDocBlock.js +5 -0
  4. package/dist/generator/generateLwM2MDefinitions.js +82 -0
  5. package/dist/generator/generateLwM2MDefinitions.spec.js +91 -0
  6. package/dist/generator/generateLwm2mTimestampResources.js +69 -0
  7. package/dist/generator/generateModels.js +142 -0
  8. package/dist/generator/generateType.js +90 -0
  9. package/dist/generator/generateValidator.js +132 -0
  10. package/dist/generator/generateValidators.js +63 -0
  11. package/dist/generator/isDir.js +163 -0
  12. package/dist/generator/isDir.spec.js +212 -0
  13. package/dist/generator/lwm2m.js +106 -0
  14. package/dist/generator/models.js +306 -0
  15. package/dist/generator/printNode.js +8 -0
  16. package/dist/generator/tokenizeName.js +5 -0
  17. package/dist/generator/tokenizeName.spec.js +98 -0
  18. package/dist/generator/types.js +140 -0
  19. package/dist/lwm2m/LWM2MObjectDefinition.js +88 -0
  20. package/dist/lwm2m/LWM2MObjectInfo.js +9 -0
  21. package/dist/lwm2m/LwM2MObject.d.js +1 -0
  22. package/dist/lwm2m/LwM2MObjectID.js +57 -0
  23. package/dist/lwm2m/ParsedLwM2MObjectDefinition.js +1 -0
  24. package/dist/lwm2m/check-lwm2m-rules.js +480 -0
  25. package/dist/lwm2m/definitions.js +596 -0
  26. package/dist/lwm2m/fromXML2JSON.js +194 -0
  27. package/dist/lwm2m/instanceTs.js +9 -0
  28. package/dist/lwm2m/instanceTs.spec.js +16 -0
  29. package/dist/lwm2m/isRegisteredLwM2MObject.js +3 -0
  30. package/dist/lwm2m/isRegisteredLwM2MObject.spec.js +45 -0
  31. package/dist/lwm2m/object/14201.d.js +5 -0
  32. package/dist/lwm2m/object/14202.d.js +5 -0
  33. package/dist/lwm2m/object/14203.d.js +5 -0
  34. package/dist/lwm2m/object/14204.d.js +5 -0
  35. package/dist/lwm2m/object/14205.d.js +5 -0
  36. package/dist/lwm2m/object/14210.d.js +5 -0
  37. package/dist/lwm2m/object/14220.d.js +5 -0
  38. package/dist/lwm2m/object/14230.d.js +5 -0
  39. package/dist/lwm2m/object/validate14201.js +18 -0
  40. package/dist/lwm2m/object/validate14202.js +17 -0
  41. package/dist/lwm2m/object/validate14203.js +19 -0
  42. package/dist/lwm2m/object/validate14204.js +17 -0
  43. package/dist/lwm2m/object/validate14205.js +15 -0
  44. package/dist/lwm2m/object/validate14210.js +13 -0
  45. package/dist/lwm2m/object/validate14220.js +12 -0
  46. package/dist/lwm2m/object/validate14230.js +13 -0
  47. package/dist/lwm2m/objects.js +8 -0
  48. package/dist/lwm2m/parseRangeEnumeration.js +20 -0
  49. package/dist/lwm2m/parseRangeEnumeration.spec.js +27 -0
  50. package/dist/lwm2m/resourceType.js +12 -0
  51. package/dist/lwm2m/timestampResources.js +12 -0
  52. package/dist/lwm2m/unwrapNestedArray.js +114 -0
  53. package/dist/lwm2m/unwrapNestedArray.spec.js +374 -0
  54. package/dist/lwm2m/validate.js +14 -0
  55. package/dist/lwm2m/validation.js +146 -0
  56. package/dist/lwm2m/validators.js +20 -0
  57. package/dist/markdown/getCodeBlock.js +74 -0
  58. package/dist/markdown/getFrontMatter.js +15 -0
  59. package/dist/markdown/parseREADME.js +19 -0
  60. package/dist/models/asset_tracker_v2+AWS/examples/examples.spec.js +489 -0
  61. package/dist/models/check-model-rules.js +137 -0
  62. package/dist/models/models.js +137 -0
  63. package/dist/models/types.js +13 -0
  64. package/dist/senml/SenMLSchema.js +79 -0
  65. package/dist/senml/SenMLSchema.spec.js +23 -0
  66. package/dist/senml/hasValue.js +8 -0
  67. package/dist/senml/hasValue.spec.js +103 -0
  68. package/dist/senml/lwm2mToSenML.js +137 -0
  69. package/dist/senml/lwm2mToSenML.spec.js +104 -0
  70. package/dist/senml/parseResourceId.js +58 -0
  71. package/dist/senml/parseResourceId.spec.js +13 -0
  72. package/dist/senml/senMLtoLwM2M.js +126 -0
  73. package/dist/senml/senMLtoLwM2M.spec.js +226 -0
  74. package/dist/senml/validateSenML.js +6 -0
  75. package/dist/senml/validateSenML.spec.js +31 -0
  76. package/export.js +13 -0
  77. package/index.d.ts +14 -0
  78. package/lwm2m/14201.xml +94 -0
  79. package/lwm2m/14202.xml +84 -0
  80. package/lwm2m/14203.xml +104 -0
  81. package/lwm2m/14204.xml +84 -0
  82. package/lwm2m/14205.xml +64 -0
  83. package/lwm2m/14210.xml +44 -0
  84. package/lwm2m/14220.xml +34 -0
  85. package/lwm2m/14230.xml +44 -0
  86. package/lwm2m/LWM2M-v1_1.xsd +168 -0
  87. package/lwm2m/LWM2MObjectDefinition.ts +84 -0
  88. package/lwm2m/LWM2MObjectInfo.ts +42 -0
  89. package/lwm2m/LwM2MObject.d.ts +19 -0
  90. package/lwm2m/LwM2MObjectID.ts +73 -0
  91. package/lwm2m/ParsedLwM2MObjectDefinition.ts +28 -0
  92. package/lwm2m/check-lwm2m-rules.ts +160 -0
  93. package/lwm2m/definitions.ts +278 -0
  94. package/lwm2m/format.sh +3 -0
  95. package/lwm2m/fromXML2JSON.ts +44 -0
  96. package/lwm2m/instanceTs.spec.ts +19 -0
  97. package/lwm2m/instanceTs.ts +10 -0
  98. package/lwm2m/isRegisteredLwM2MObject.spec.ts +48 -0
  99. package/lwm2m/isRegisteredLwM2MObject.ts +4 -0
  100. package/lwm2m/object/14201.d.ts +73 -0
  101. package/lwm2m/object/14202.d.ts +59 -0
  102. package/lwm2m/object/14203.d.ts +67 -0
  103. package/lwm2m/object/14204.d.ts +55 -0
  104. package/lwm2m/object/14205.d.ts +43 -0
  105. package/lwm2m/object/14210.d.ts +31 -0
  106. package/lwm2m/object/14220.d.ts +25 -0
  107. package/lwm2m/object/14230.d.ts +31 -0
  108. package/lwm2m/object/validate14201.ts +10 -0
  109. package/lwm2m/object/validate14202.ts +10 -0
  110. package/lwm2m/object/validate14203.ts +10 -0
  111. package/lwm2m/object/validate14204.ts +10 -0
  112. package/lwm2m/object/validate14205.ts +10 -0
  113. package/lwm2m/object/validate14210.ts +10 -0
  114. package/lwm2m/object/validate14220.ts +10 -0
  115. package/lwm2m/object/validate14230.ts +10 -0
  116. package/lwm2m/objects.ts +16 -0
  117. package/lwm2m/parseRangeEnumeration.spec.ts +34 -0
  118. package/lwm2m/parseRangeEnumeration.ts +29 -0
  119. package/lwm2m/resourceType.ts +11 -0
  120. package/lwm2m/timestampResources.ts +4 -0
  121. package/lwm2m/unwrapNestedArray.spec.ts +241 -0
  122. package/lwm2m/unwrapNestedArray.ts +27 -0
  123. package/lwm2m/validate.ts +30 -0
  124. package/lwm2m/validation.ts +120 -0
  125. package/lwm2m/validators.ts +21 -0
  126. package/models/PCA20035+solar/README.md +10 -0
  127. package/models/PCA20035+solar/transforms/airQuality.md +48 -0
  128. package/models/PCA20035+solar/transforms/battery.md +46 -0
  129. package/models/PCA20035+solar/transforms/button.md +45 -0
  130. package/models/PCA20035+solar/transforms/deviceInfo.md +72 -0
  131. package/models/PCA20035+solar/transforms/gain.md +45 -0
  132. package/models/PCA20035+solar/transforms/geolocationFromGroundfix.md +67 -0
  133. package/models/PCA20035+solar/transforms/geolocationFromMessage.md +80 -0
  134. package/models/PCA20035+solar/transforms/humidity.md +43 -0
  135. package/models/PCA20035+solar/transforms/networkInfo.md +84 -0
  136. package/models/PCA20035+solar/transforms/pressure.md +43 -0
  137. package/models/PCA20035+solar/transforms/temperature.md +43 -0
  138. package/models/README.md +10 -0
  139. package/models/asset_tracker_v2+AWS/README.md +6 -0
  140. package/models/asset_tracker_v2+AWS/examples/examples.spec.ts +229 -0
  141. package/models/asset_tracker_v2+AWS/examples/shadow/example-1.json +24 -0
  142. package/models/asset_tracker_v2+AWS/examples/shadow/example-2.json +30 -0
  143. package/models/asset_tracker_v2+AWS/examples/shadow/example-3.json +37 -0
  144. package/models/asset_tracker_v2+AWS/examples/shadow/example-4.json +48 -0
  145. package/models/asset_tracker_v2+AWS/examples/shadow/example-5.json +43 -0
  146. package/models/asset_tracker_v2+AWS/transforms/GNSS.md +66 -0
  147. package/models/asset_tracker_v2+AWS/transforms/battery-voltage.md +50 -0
  148. package/models/asset_tracker_v2+AWS/transforms/device-info.md +61 -0
  149. package/models/asset_tracker_v2+AWS/transforms/env.md +69 -0
  150. package/models/asset_tracker_v2+AWS/transforms/fuel-gauge.md +62 -0
  151. package/models/asset_tracker_v2+AWS/transforms/roam.md +100 -0
  152. package/models/asset_tracker_v2+AWS/transforms/solar.md +58 -0
  153. package/models/check-model-rules.ts +125 -0
  154. package/models/kartverket-vasstandsdata/README.md +13 -0
  155. package/models/models.ts +36 -0
  156. package/models/types.ts +17 -0
  157. package/package.json +111 -0
  158. package/senml/SenMLSchema.spec.ts +21 -0
  159. package/senml/SenMLSchema.ts +74 -0
  160. package/senml/hasValue.spec.ts +19 -0
  161. package/senml/hasValue.ts +12 -0
  162. package/senml/lwm2mToSenML.spec.ts +74 -0
  163. package/senml/lwm2mToSenML.ts +62 -0
  164. package/senml/parseResourceId.spec.ts +13 -0
  165. package/senml/parseResourceId.ts +23 -0
  166. package/senml/senMLtoLwM2M.spec.ts +181 -0
  167. package/senml/senMLtoLwM2M.ts +121 -0
  168. package/senml/validateSenML.spec.ts +16 -0
  169. package/senml/validateSenML.ts +8 -0
@@ -0,0 +1,42 @@
1
+ import type { LwM2MObjectID } from './LwM2MObjectID.js'
2
+
3
+ /**
4
+ * Provides information about the the LwM2M objects defined in this project.
5
+ */
6
+ export type LWM2MObjectInfo = {
7
+ ObjectID: LwM2MObjectID
8
+ ObjectVersion: string
9
+ Name: string
10
+ Description: string
11
+ Resources: Record<number, LwM2MResourceInfo>
12
+ }
13
+
14
+ export type LwM2MResourceInfo = {
15
+ ResourceID: number
16
+ Name: string
17
+ Mandatory: boolean
18
+ Type: ResourceType
19
+ Description: string // e.g. 'The decimal notation of latitude, e.g. -43.5723 [World Geodetic System 1984].'
20
+ RangeEnumeration?: Range
21
+ Units?: string // e.g. 'lat'
22
+ }
23
+
24
+ export type Range = {
25
+ /**
26
+ * The minimum inclusive value of the range. Always smaller than max.
27
+ */
28
+ min: number
29
+ /**
30
+ * The maximum inclusive value of the range. Always larger than min.
31
+ */
32
+ max: number
33
+ }
34
+
35
+ export enum ResourceType {
36
+ String = 'String',
37
+ Integer = 'Integer',
38
+ Float = 'Float',
39
+ Boolean = 'Boolean',
40
+ Opaque = 'Opaque',
41
+ Time = 'Time',
42
+ }
@@ -0,0 +1,19 @@
1
+ import type { LwM2MResourceValue } from '../senml/senMLtoLwM2M.js'
2
+ import type { LwM2MObjectID } from './LwM2MObjectID.js'
3
+
4
+ export type LwM2MObject<
5
+ ObjectDef extends {
6
+ ObjectID: LwM2MObjectID
7
+ /**
8
+ * The Object Version of an Object is composed of 2 digits separated by a dot '.'
9
+ *
10
+ * @see https://www.openmobilealliance.org/release/LightweightM2M/V1_1_1-20190617-A/OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A.pdf Section 7.2.2
11
+ */
12
+ ObjectVersion: string
13
+ Resources: Record<number, LwM2MResourceValue | undefined>
14
+ },
15
+ > = {
16
+ ObjectID: ObjectDef['ObjectID']
17
+ ObjectVersion: ObjectDef['ObjectVersion']
18
+ Resources: ObjectDef['Resources']
19
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The LwM2M Object IDs defined in this repo.
3
+ */
4
+ export enum LwM2MObjectID {
5
+ /**
6
+ * Geolocation (14201)
7
+ *
8
+ * Describes the geo location of a device
9
+ */
10
+ Geolocation_14201 = 14201,
11
+ /**
12
+ * Battery and Power (14202)
13
+ *
14
+ * Information about the battery and power status of the device.
15
+ */
16
+ BatteryAndPower_14202 = 14202,
17
+ /**
18
+ * Connection information (14203)
19
+ *
20
+ * Details about the device's connection.
21
+ */
22
+ ConnectionInformation_14203 = 14203,
23
+ /**
24
+ * Device information (14204)
25
+ *
26
+ * Details about the device's connection.
27
+ */
28
+ DeviceInformation_14204 = 14204,
29
+ /**
30
+ * Environment (14205)
31
+ *
32
+ * Environment information.
33
+ */
34
+ Environment_14205 = 14205,
35
+ /**
36
+ * Solar charge (14210)
37
+ *
38
+ * Measurements from the solar shield.
39
+ */
40
+ SolarCharge_14210 = 14210,
41
+ /**
42
+ * Button press (14220)
43
+ *
44
+ * Describes a button press event.
45
+ */
46
+ ButtonPress_14220 = 14220,
47
+ /**
48
+ * Sea Water Level (14230)
49
+ *
50
+ * Describes observed sea water level.
51
+ */
52
+ SeaWaterLevel_14230 = 14230
53
+ }
54
+ /**
55
+ * The LwM2M Object IDs defined in this repo.
56
+ */
57
+ export const LwM2MObjectIDs = [
58
+ // Geolocation (14201)
59
+ LwM2MObjectID.Geolocation_14201,
60
+ // Battery and Power (14202)
61
+ LwM2MObjectID.BatteryAndPower_14202,
62
+ // Connection information (14203)
63
+ LwM2MObjectID.ConnectionInformation_14203,
64
+ // Device information (14204)
65
+ LwM2MObjectID.DeviceInformation_14204,
66
+ // Environment (14205)
67
+ LwM2MObjectID.Environment_14205,
68
+ // Solar charge (14210)
69
+ LwM2MObjectID.SolarCharge_14210,
70
+ // Button press (14220)
71
+ LwM2MObjectID.ButtonPress_14220,
72
+ // Sea Water Level (14230)
73
+ LwM2MObjectID.SeaWaterLevel_14230];
@@ -0,0 +1,28 @@
1
+ export type Resource = {
2
+ $: {
3
+ ID: string // e.g. '0'
4
+ }
5
+ Name: string // e.g. 'Latitude'
6
+ Operations: 'R'
7
+ MultipleInstances: 'Single'
8
+ Mandatory: 'Optional' | 'Mandatory'
9
+ Type: 'String' | 'Integer' | 'Float' | 'Boolean' | 'Opaque' | 'Time'
10
+ RangeEnumeration: string // e.g. -10..10
11
+ Units: string // e.g. 'lat'
12
+ Description: string // e.g. 'The decimal notation of latitude, e.g. -43.5723 [World Geodetic System 1984].'
13
+ }
14
+
15
+ export type ParsedLwM2MObjectDefinition = {
16
+ $: { ObjectType: 'MODefinition' }
17
+ Name: string // e.g. 'Location'
18
+ Description1: string // e.g. 'This LwM2M Object provides a range of location telemetry related information which can be queried by the LwM2M Server.'
19
+ ObjectID: string // e.g. '14201'
20
+ ObjectURN: string // e.g. 'urn:oma:lwm2m:x:14201'
21
+ ObjectVersion?: string // e.g. '1.0'
22
+ MultipleInstances: 'Multiple'
23
+ Mandatory: 'Optional'
24
+ Resources: {
25
+ Item: Resource[]
26
+ }
27
+ Description2: string // e.g. ''
28
+ }
@@ -0,0 +1,160 @@
1
+ import chalk from 'chalk'
2
+ import { readFile, readdir, stat } from 'node:fs/promises'
3
+ import path, { parse } from 'node:path'
4
+ import assert from 'node:assert/strict'
5
+ import xml2js from 'xml2js'
6
+ import { exec } from 'node:child_process'
7
+ import { unwrapNestedArray } from './unwrapNestedArray.js'
8
+ import {
9
+ LWM2MObjectDefinition,
10
+ type LWM2MObjectDefinitionType,
11
+ } from './LWM2MObjectDefinition.js'
12
+ import type { ParsedLwM2MObjectDefinition } from './ParsedLwM2MObjectDefinition.js'
13
+ import { validate } from '../validate.js'
14
+ import { parseRangeEnumeration } from './parseRangeEnumeration.js'
15
+
16
+ const v = validate(LWM2MObjectDefinition)
17
+
18
+ const listLwm2mDefinitions = async (
19
+ modelDir: string,
20
+ ): Promise<LWM2MObjectDefinitionType[]> => {
21
+ const defs: LWM2MObjectDefinitionType[] = []
22
+ const files = await readdir(modelDir)
23
+ for (const file of files) {
24
+ if (!file.endsWith('.xml')) continue
25
+ console.log(chalk.white('·'), chalk.white.bold(file))
26
+ assert.match(
27
+ file,
28
+ /^[0-9]+\.xml$/,
29
+ 'LwM2M object definition files must only have numbers in their file names',
30
+ )
31
+ console.log(chalk.green('✔'), chalk.gray('File name is correct'))
32
+ const objectDefinitionFile = path.join(modelDir, file)
33
+ if ((await stat(objectDefinitionFile)).isDirectory()) continue
34
+
35
+ // validate
36
+ const schemaValidated = await new Promise<boolean>((resolve) =>
37
+ exec(
38
+ `xmllint --noout --schema ${path.join(
39
+ process.cwd(),
40
+ 'lwm2m',
41
+ 'LWM2M-v1_1.xsd',
42
+ )} ${objectDefinitionFile}`,
43
+ (error, _, stderr) => {
44
+ if (error) {
45
+ console.error(stderr)
46
+ return resolve(false)
47
+ }
48
+ resolve(true)
49
+ },
50
+ ),
51
+ )
52
+ assert.equal(schemaValidated, true, '')
53
+ console.log(
54
+ chalk.green('✔'),
55
+ chalk.gray('Is a valid LwM2M object definition'),
56
+ )
57
+ const ObjectID = parseInt(parse(objectDefinitionFile).name, 10)
58
+ assert.equal(ObjectID > 14200, true, 'ObjectID must be greater than 14200')
59
+ assert.equal(ObjectID < 15000, true, 'ObjectID must be smaller than 15000')
60
+ const ObjectURN = `urn:oma:lwm2m:x:${ObjectID}`
61
+
62
+ const definition = (
63
+ unwrapNestedArray(
64
+ await xml2js.parseStringPromise(
65
+ await readFile(objectDefinitionFile, 'utf-8'),
66
+ ),
67
+ ) as any
68
+ ).LWM2M.Object as ParsedLwM2MObjectDefinition
69
+
70
+ assert.equal(
71
+ ObjectID.toString(),
72
+ definition.ObjectID,
73
+ `ObjectID must match filename`,
74
+ )
75
+ assert.equal(
76
+ ObjectURN,
77
+ definition.ObjectURN,
78
+ `ObjectURN must follow schema`,
79
+ )
80
+
81
+ console.log(
82
+ chalk.green('✔'),
83
+ chalk.blue(ObjectURN),
84
+ chalk.gray('ObjectID and URN match filename and schema'),
85
+ )
86
+
87
+ const objectDef: LWM2MObjectDefinitionType = {
88
+ ...definition,
89
+ LWM2MVersion: '1.1',
90
+ Resources: definition.Resources.Item.reduce<Record<string, any>>(
91
+ (resources, { $, ...item }) => {
92
+ if (resources[$.ID] !== undefined)
93
+ throw new Error(`Duplicate resource ID: ${$.ID}`)
94
+ if (item.RangeEnumeration.length > 0) {
95
+ const maybeRange = parseRangeEnumeration(item.RangeEnumeration)
96
+ if ('error' in maybeRange) throw maybeRange.error
97
+ }
98
+ return {
99
+ ...resources,
100
+ [$.ID]: item,
101
+ }
102
+ },
103
+ {},
104
+ ),
105
+ }
106
+
107
+ const maybeValid = v(objectDef)
108
+ if ('errors' in maybeValid) {
109
+ console.error(maybeValid.errors)
110
+ throw new Error(`The definition should be valid!`)
111
+ }
112
+
113
+ console.log(chalk.green('✔'), chalk.gray('LwM2M limitations are honored'))
114
+
115
+ defs.push(maybeValid.value)
116
+
117
+ const { Name, Resources } = maybeValid.value
118
+
119
+ const TimeResources = Object.values(Resources).filter(
120
+ ({ Type }) => Type === 'Time',
121
+ )
122
+ assert.equal(
123
+ TimeResources.length,
124
+ 1,
125
+ 'Objects must define one Time resource',
126
+ )
127
+ assert.equal(
128
+ TimeResources[0]?.Mandatory,
129
+ 'Mandatory',
130
+ 'The Time resources must be mandatory.',
131
+ )
132
+ console.log(
133
+ chalk.green('✔'),
134
+ chalk.gray(`Object has one time resource (${TimeResources[0]?.Name})`),
135
+ )
136
+
137
+ console.log(`${chalk.yellow(ObjectID)}:`, chalk.white(Name))
138
+ for (const [id, resource] of Object.entries(Resources)) {
139
+ console.log(
140
+ `${chalk.gray(ObjectID)}.${chalk.yellow(id)}:`,
141
+ chalk.white(resource.Name),
142
+ `${chalk.gray(resource.Type)} ${chalk.gray(
143
+ `(${resource.Units ?? 'no unit'})`,
144
+ )}`,
145
+ )
146
+ }
147
+ }
148
+ return defs
149
+ }
150
+
151
+ // LwM2M
152
+ console.log(chalk.gray('LwM2M rules check'))
153
+ console.log('')
154
+ const lwm2mDir = path.join(process.cwd(), 'lwm2m')
155
+ const lwm2mDefinitions = await listLwm2mDefinitions(lwm2mDir)
156
+ assert.equal(
157
+ lwm2mDefinitions.length > 0,
158
+ true,
159
+ 'LwM2M objects must be defined.',
160
+ )
@@ -0,0 +1,278 @@
1
+ import { type LWM2MObjectInfo, ResourceType } from "./LWM2MObjectInfo.js";
2
+ import { LwM2MObjectID } from "./LwM2MObjectID.js";
3
+ /**
4
+ * Contains the ID of the resource that defines the timestamp for each LwM2M object definition
5
+ */
6
+ export const definitions: Record<LwM2MObjectID, LWM2MObjectInfo> = { /**
7
+ * Geolocation (14201)
8
+ *
9
+ * Describes the geo location of a device
10
+ */
11
+ [LwM2MObjectID.Geolocation_14201]: { ObjectID: LwM2MObjectID.Geolocation_14201, ObjectVersion: "1.0", Name: "Geolocation", Description: "Describes the geo location of a device", Resources: { /**
12
+ * Latitude (Float)
13
+ *
14
+ * The decimal notation of latitude in degrees, e.g. -43.5723 [World Geodetic System 1984].
15
+ *
16
+ * Minimum: -90
17
+ * Maximum: 90
18
+ */
19
+ 0: { ResourceID: 0, Name: "Latitude", Mandatory: true, Type: ResourceType.Float, Description: "The decimal notation of latitude in degrees, e.g. -43.5723 [World Geodetic System 1984].", RangeEnumeration: { min: -90, max: 90 }, Units: "\u00B0" }, /**
20
+ * Longitude (Float)
21
+ *
22
+ * The decimal notation of longitude in degrees, e.g. 153.21760 [World Geodetic System 1984].
23
+ *
24
+ * Minimum: -180
25
+ * Maximum: 180
26
+ */
27
+ 1: { ResourceID: 1, Name: "Longitude", Mandatory: true, Type: ResourceType.Float, Description: "The decimal notation of longitude in degrees, e.g. 153.21760 [World Geodetic System 1984].", RangeEnumeration: { min: -180, max: 180 }, Units: "\u00B0" }, /**
28
+ * Altitude (Float)
29
+ *
30
+ * The decimal notation of altitude in meters above sea level.
31
+ */
32
+ 2: { ResourceID: 2, Name: "Altitude", Mandatory: false, Type: ResourceType.Float, Description: "The decimal notation of altitude in meters above sea level.", Units: "m" }, /**
33
+ * Radius (Float)
34
+ *
35
+ * The value in this resource indicates the radius of a circular area in meters. The circular area is used to describe uncertainty about a point for coordinates in a two-dimensional coordinate reference systems (CRS). The center point of a circular area is specified by using the Latitude and the Longitude Resources.
36
+ */
37
+ 3: { ResourceID: 3, Name: "Radius", Mandatory: false, Type: ResourceType.Float, Description: "The value in this resource indicates the radius of a circular area in meters. The circular area is used to describe uncertainty about a point for coordinates in a two-dimensional coordinate reference systems (CRS). The center point of a circular area is specified by using the Latitude and the Longitude Resources.", Units: "m" }, /**
38
+ * Speed (Float)
39
+ *
40
+ * Speed is the time rate of change in position.
41
+ */
42
+ 4: { ResourceID: 4, Name: "Speed", Mandatory: false, Type: ResourceType.Float, Description: "Speed is the time rate of change in position.", Units: "m/s" }, /**
43
+ * Heading (Float)
44
+ *
45
+ * The angle of movement in degrees.
46
+ *
47
+ * Minimum: 0
48
+ * Maximum: 360
49
+ */
50
+ 5: { ResourceID: 5, Name: "Heading", Mandatory: false, Type: ResourceType.Float, Description: "The angle of movement in degrees.", RangeEnumeration: { min: 0, max: 360 }, Units: "\u00B0" }, /**
51
+ * Source (String)
52
+ *
53
+ * The source of the geo location, e.g. GNSS, SCELL, MCELL, WIFI.
54
+ */
55
+ 6: { ResourceID: 6, Name: "Source", Mandatory: true, Type: ResourceType.String, Description: "The source of the geo location, e.g. GNSS, SCELL, MCELL, WIFI." }, /**
56
+ * Timestamp (Time)
57
+ *
58
+ * The timestamp of when the location measurement was performed.
59
+ */
60
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the location measurement was performed." } } }, /**
61
+ * Battery and Power (14202)
62
+ *
63
+ * Information about the battery and power status of the device.
64
+ */
65
+ [LwM2MObjectID.BatteryAndPower_14202]: { ObjectID: LwM2MObjectID.BatteryAndPower_14202, ObjectVersion: "1.0", Name: "Battery and Power", Description: "Information about the battery and power status of the device.", Resources: { /**
66
+ * State of charge (Integer)
67
+ *
68
+ * State of charge in percent. Examples: 23, 1, 100.
69
+ *
70
+ * Minimum: 0
71
+ * Maximum: 100
72
+ */
73
+ 0: { ResourceID: 0, Name: "State of charge", Mandatory: false, Type: ResourceType.Integer, Description: "State of charge in percent. Examples: 23, 1, 100.", RangeEnumeration: { min: 0, max: 100 }, Units: "%" }, /**
74
+ * Voltage (Float)
75
+ *
76
+ * Battery voltage in Volt. Examples: 2.754, 3.3.
77
+ */
78
+ 1: { ResourceID: 1, Name: "Voltage", Mandatory: false, Type: ResourceType.Float, Description: "Battery voltage in Volt. Examples: 2.754, 3.3.", Units: "V" }, /**
79
+ * Charge current (Float)
80
+ *
81
+ * Charge current in mA. Examples: 429, -244.
82
+ */
83
+ 2: { ResourceID: 2, Name: "Charge current", Mandatory: false, Type: ResourceType.Float, Description: "Charge current in mA. Examples: 429, -244.", Units: "mA" }, /**
84
+ * Battery temperature (Float)
85
+ *
86
+ * Battery temperature in Celsius. Examples: 21.7, 23.123.
87
+ */
88
+ 3: { ResourceID: 3, Name: "Battery temperature", Mandatory: false, Type: ResourceType.Float, Description: "Battery temperature in Celsius. Examples: 21.7, 23.123.", Units: "C" }, /**
89
+ * Time to full (Integer)
90
+ *
91
+ * Time to full in seconds. Examples: 4652.
92
+ */
93
+ 4: { ResourceID: 4, Name: "Time to full", Mandatory: false, Type: ResourceType.Integer, Description: "Time to full in seconds. Examples: 4652.", Units: "s" }, /**
94
+ * Time to empty (Integer)
95
+ *
96
+ * Time to empty in seconds. Examples: 4652.
97
+ */
98
+ 5: { ResourceID: 5, Name: "Time to empty", Mandatory: false, Type: ResourceType.Integer, Description: "Time to empty in seconds. Examples: 4652.", Units: "s" }, /**
99
+ * Timestamp (Time)
100
+ *
101
+ * The timestamp of when the measurement was performed.
102
+ */
103
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the measurement was performed." } } }, /**
104
+ * Connection information (14203)
105
+ *
106
+ * Details about the device's connection.
107
+ */
108
+ [LwM2MObjectID.ConnectionInformation_14203]: { ObjectID: LwM2MObjectID.ConnectionInformation_14203, ObjectVersion: "1.0", Name: "Connection information", Description: "Details about the device's connection.", Resources: { /**
109
+ * Network mode (String)
110
+ *
111
+ * Examples: LTE-M, NB-IoT.
112
+ */
113
+ 0: { ResourceID: 0, Name: "Network mode", Mandatory: false, Type: ResourceType.String, Description: "Examples: LTE-M, NB-IoT." }, /**
114
+ * Band (Integer)
115
+ *
116
+ * E-UTRA Absolute Radio Frequency Channel Number (EARFCN) of the current cell where the EARFCN is as defined in 3GPP TS 36.101. LTE carrier channel number for unique identification of LTE band and carrier frequency. Examples: 262143
117
+ */
118
+ 1: { ResourceID: 1, Name: "Band", Mandatory: false, Type: ResourceType.Integer, Description: "E-UTRA Absolute Radio Frequency Channel Number (EARFCN) of the current cell where the EARFCN is as defined in 3GPP TS 36.101. LTE carrier channel number for unique identification of LTE band and carrier frequency. Examples: 262143" }, /**
119
+ * RSRP (Integer)
120
+ *
121
+ * Reference Signal Received Power (RSRP). The average power level in dBm received from a single reference signal in an LTE (Long-term Evolution) network. Typically this value ranges from -140 to -40 dBm. Examples: -97, -104.
122
+ */
123
+ 2: { ResourceID: 2, Name: "RSRP", Mandatory: false, Type: ResourceType.Integer, Description: "Reference Signal Received Power (RSRP). The average power level in dBm received from a single reference signal in an LTE (Long-term Evolution) network. Typically this value ranges from -140 to -40 dBm. Examples: -97, -104.", Units: "dBm" }, /**
124
+ * Area (Integer)
125
+ *
126
+ * Area code. Examples: 12
127
+ */
128
+ 3: { ResourceID: 3, Name: "Area", Mandatory: false, Type: ResourceType.Integer, Description: "Area code. Examples: 12" }, /**
129
+ * Cell (Integer)
130
+ *
131
+ * The cell ID the User Equipment (UE) is camped on. 4-byte Evolved Terrestrial Radio Access Network (E-UTRAN) cell ID. Examples: 33703719
132
+ */
133
+ 4: { ResourceID: 4, Name: "Cell", Mandatory: false, Type: ResourceType.Integer, Description: "The cell ID the User Equipment (UE) is camped on. 4-byte Evolved Terrestrial Radio Access Network (E-UTRAN) cell ID. Examples: 33703719" }, /**
134
+ * Mobile country code and mobile network code (Integer)
135
+ *
136
+ * Examples: 24202, 310410
137
+ */
138
+ 5: { ResourceID: 5, Name: "Mobile country code and mobile network code", Mandatory: false, Type: ResourceType.Integer, Description: "Examples: 24202, 310410" }, /**
139
+ * IP address (String)
140
+ *
141
+ * Examples: 10.81.183.99, 2001:0db8:85a3:0000:0000:8a2e:0370:7334, 2001:db8:85a3::8a2e:370:7334
142
+ */
143
+ 6: { ResourceID: 6, Name: "IP address", Mandatory: false, Type: ResourceType.String, Description: "Examples: 10.81.183.99, 2001:0db8:85a3:0000:0000:8a2e:0370:7334, 2001:db8:85a3::8a2e:370:7334" }, /**
144
+ * Energy Estimate (Integer)
145
+ *
146
+ * The %CONEVAL AT command returns amongst other data the energy estimate: Relative estimated energy consumption of data transmission compared to nominal consumption. A higher value means smaller energy consumption. 5: Difficulties in setting up connections. Maximum number of repetitions might be needed for data. 6: Poor conditions. Setting up a connection might require retries and a higher number of repetitions for data. 7: Normal conditions for cIoT device. No repetitions for data or only a few repetitions in the worst case. 8: Good conditions. Possibly very good conditions for small amounts of data. 9: Very good conditions. Efficient data transfer estimated also for larger amounts of data. Examples: 5, 7
147
+ */
148
+ 11: { ResourceID: 11, Name: "Energy Estimate", Mandatory: false, Type: ResourceType.Integer, Description: "The %CONEVAL AT command returns amongst other data the energy estimate: Relative estimated energy consumption of data transmission compared to nominal consumption. A higher value means smaller energy consumption. 5: Difficulties in setting up connections. Maximum number of repetitions might be needed for data. 6: Poor conditions. Setting up a connection might require retries and a higher number of repetitions for data. 7: Normal conditions for cIoT device. No repetitions for data or only a few repetitions in the worst case. 8: Good conditions. Possibly very good conditions for small amounts of data. 9: Very good conditions. Efficient data transfer estimated also for larger amounts of data. Examples: 5, 7" }, /**
149
+ * Timestamp (Time)
150
+ *
151
+ * The timestamp of when the measurement was performed.
152
+ */
153
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the measurement was performed." } } }, /**
154
+ * Device information (14204)
155
+ *
156
+ * Details about the device's connection.
157
+ */
158
+ [LwM2MObjectID.DeviceInformation_14204]: { ObjectID: LwM2MObjectID.DeviceInformation_14204, ObjectVersion: "1.0", Name: "Device information", Description: "Details about the device's connection.", Resources: { /**
159
+ * IMEI (String)
160
+ *
161
+ * Board IMEI. Examples: 352656106111232.
162
+ */
163
+ 0: { ResourceID: 0, Name: "IMEI", Mandatory: true, Type: ResourceType.String, Description: "Board IMEI. Examples: 352656106111232." }, /**
164
+ * SIM ICCID (String)
165
+ *
166
+ * Examples: 89450421180216216095.
167
+ */
168
+ 1: { ResourceID: 1, Name: "SIM ICCID", Mandatory: false, Type: ResourceType.String, Description: "Examples: 89450421180216216095." }, /**
169
+ * Modem firmware version (String)
170
+ *
171
+ * Examples: mfw_nrf9160_1.0.0.
172
+ */
173
+ 2: { ResourceID: 2, Name: "Modem firmware version", Mandatory: true, Type: ResourceType.String, Description: "Examples: mfw_nrf9160_1.0.0." }, /**
174
+ * Application firmware version (String)
175
+ *
176
+ * Examples: v1.0.0-rc1-327-g6fc8c16b239f.
177
+ */
178
+ 3: { ResourceID: 3, Name: "Application firmware version", Mandatory: true, Type: ResourceType.String, Description: "Examples: v1.0.0-rc1-327-g6fc8c16b239f." }, /**
179
+ * Board version (String)
180
+ *
181
+ * Examples: thingy91_nrf9160.
182
+ */
183
+ 4: { ResourceID: 4, Name: "Board version", Mandatory: true, Type: ResourceType.String, Description: "Examples: thingy91_nrf9160." }, /**
184
+ * Battery model (String)
185
+ *
186
+ * Examples: LP302535, LP502540, LP803035.
187
+ */
188
+ 5: { ResourceID: 5, Name: "Battery model", Mandatory: false, Type: ResourceType.String, Description: "Examples: LP302535, LP502540, LP803035." }, /**
189
+ * Timestamp (Time)
190
+ *
191
+ * The timestamp of when the measurement was performed.
192
+ */
193
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the measurement was performed." } } }, /**
194
+ * Environment (14205)
195
+ *
196
+ * Environment information.
197
+ */
198
+ [LwM2MObjectID.Environment_14205]: { ObjectID: LwM2MObjectID.Environment_14205, ObjectVersion: "1.0", Name: "Environment", Description: "Environment information.", Resources: { /**
199
+ * Temperature (Float)
200
+ *
201
+ * Environmental temperature in Celsius. Examples: 23.5, -10.2.
202
+ */
203
+ 0: { ResourceID: 0, Name: "Temperature", Mandatory: false, Type: ResourceType.Float, Description: "Environmental temperature in Celsius. Examples: 23.5, -10.2.", Units: "\u00B0C" }, /**
204
+ * Humidity (Float)
205
+ *
206
+ * Environmental humidity in percent. Examples: 44.2, 72.
207
+ */
208
+ 1: { ResourceID: 1, Name: "Humidity", Mandatory: false, Type: ResourceType.Float, Description: "Environmental humidity in percent. Examples: 44.2, 72.", Units: "%" }, /**
209
+ * Atmospheric pressure (Float)
210
+ *
211
+ * Atmospheric pressure in pascal. Examples: 1003.6, 977.
212
+ */
213
+ 2: { ResourceID: 2, Name: "Atmospheric pressure", Mandatory: false, Type: ResourceType.Float, Description: "Atmospheric pressure in pascal. Examples: 1003.6, 977.", Units: "Pa" }, /**
214
+ * Air Quality Index (Integer)
215
+ *
216
+ * The Bosch BME680 sensor calculates an Air Quality Index. See https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme680-ds001.pdf
217
+ */
218
+ 10: { ResourceID: 10, Name: "Air Quality Index", Mandatory: false, Type: ResourceType.Integer, Description: "The Bosch BME680 sensor calculates an Air Quality Index. See https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme680-ds001.pdf" }, /**
219
+ * Timestamp (Time)
220
+ *
221
+ * The timestamp of when the measurement was performed.
222
+ */
223
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the measurement was performed." } } }, /**
224
+ * Solar charge (14210)
225
+ *
226
+ * Measurements from the solar shield.
227
+ */
228
+ [LwM2MObjectID.SolarCharge_14210]: { ObjectID: LwM2MObjectID.SolarCharge_14210, ObjectVersion: "1.0", Name: "Solar charge", Description: "Measurements from the solar shield.", Resources: { /**
229
+ * Gain (Float)
230
+ *
231
+ * The current gain from the solar shield, measured in mA. Example: 3.123, -0.0032.
232
+ */
233
+ 0: { ResourceID: 0, Name: "Gain", Mandatory: true, Type: ResourceType.Float, Description: "The current gain from the solar shield, measured in mA. Example: 3.123, -0.0032.", Units: "mA" }, /**
234
+ * Voltage (Float)
235
+ *
236
+ * Battery voltage in Volt. Examples: 2.754, 3.3.
237
+ */
238
+ 1: { ResourceID: 1, Name: "Voltage", Mandatory: false, Type: ResourceType.Float, Description: "Battery voltage in Volt. Examples: 2.754, 3.3.", Units: "V" }, /**
239
+ * Timestamp (Time)
240
+ *
241
+ * The timestamp of when the measurement was performed.
242
+ */
243
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the measurement was performed." } } }, /**
244
+ * Button press (14220)
245
+ *
246
+ * Describes a button press event.
247
+ */
248
+ [LwM2MObjectID.ButtonPress_14220]: { ObjectID: LwM2MObjectID.ButtonPress_14220, ObjectVersion: "1.0", Name: "Button press", Description: "Describes a button press event.", Resources: { /**
249
+ * Button ID (Integer)
250
+ *
251
+ * The ID of the button that was pressed. Examples: 1, 2.
252
+ */
253
+ 0: { ResourceID: 0, Name: "Button ID", Mandatory: true, Type: ResourceType.Integer, Description: "The ID of the button that was pressed. Examples: 1, 2." }, /**
254
+ * Timestamp (Time)
255
+ *
256
+ * The timestamp of when the button was pressed.
257
+ */
258
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the button was pressed." } } }, /**
259
+ * Sea Water Level (14230)
260
+ *
261
+ * Describes observed sea water level.
262
+ */
263
+ [LwM2MObjectID.SeaWaterLevel_14230]: { ObjectID: LwM2MObjectID.SeaWaterLevel_14230, ObjectVersion: "1.0", Name: "Sea Water Level", Description: "Describes observed sea water level.", Resources: { /**
264
+ * Sea Water Level (Float)
265
+ *
266
+ * The observed sea water level relative the the sea level elevation of the sea map. Examples: 134.2, 104.5.
267
+ */
268
+ 0: { ResourceID: 0, Name: "Sea Water Level", Mandatory: true, Type: ResourceType.Float, Description: "The observed sea water level relative the the sea level elevation of the sea map. Examples: 134.2, 104.5.", Units: "cm" }, /**
269
+ * Station code (String)
270
+ *
271
+ * The code of the observation station. Examples: TRD, SVG.
272
+ */
273
+ 1: { ResourceID: 1, Name: "Station code", Mandatory: true, Type: ResourceType.String, Description: "The code of the observation station. Examples: TRD, SVG." }, /**
274
+ * Timestamp (Time)
275
+ *
276
+ * The timestamp of when the observation was made.
277
+ */
278
+ 99: { ResourceID: 99, Name: "Timestamp", Mandatory: true, Type: ResourceType.Time, Description: "The timestamp of when the observation was made." } } } };
@@ -0,0 +1,3 @@
1
+ #!/bin/env sh
2
+
3
+ xmllint --output $1 --format $1
@@ -0,0 +1,44 @@
1
+ import xml2js from 'xml2js'
2
+ import { readFile } from 'node:fs/promises'
3
+ import path from 'node:path'
4
+ import type { LwM2MType } from './resourceType.js'
5
+
6
+ /**
7
+ * JSON representation of an XML object
8
+ */
9
+ type jsonObject = {
10
+ Name: string[]
11
+ Description1: string[]
12
+ ObjectID: string[]
13
+ ObjectURN: string[]
14
+ LWM2MVersion: string[]
15
+ ObjectVersion: string[]
16
+ MultipleInstances: ['Single'] | ['Multiple']
17
+ Mandatory: ['Optional'] | ['Mandatory']
18
+ Resources: [{ Item: Resource[] }]
19
+ Description2: string[]
20
+ }
21
+
22
+ type Resource = {
23
+ $: { ID: string }
24
+ Name: string[]
25
+ Operations: string[]
26
+ MultipleInstances: ['Single'] | ['Multiple']
27
+ Mandatory: ['Optional'] | ['Mandatory']
28
+ Type: LwM2MType[]
29
+ RangeEnumeration: string[]
30
+ Units: string[]
31
+ Description: string[]
32
+ }
33
+
34
+ /**
35
+ * From XML to JSON
36
+ */
37
+ export const fromXML2JSON = async (id: number): Promise<jsonObject> => {
38
+ const baseDir = process.cwd()
39
+ const subDir = (...tree: string[]): string => path.join(baseDir, ...tree)
40
+ const jsonObject = await xml2js.parseStringPromise(
41
+ await readFile(subDir('lwm2m', `${id}.xml`), 'utf-8'),
42
+ )
43
+ return jsonObject.LWM2M.Object[0]
44
+ }
@@ -0,0 +1,19 @@
1
+ import { describe, it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { instanceTs } from './instanceTs.js'
4
+
5
+ void describe('instanceTs()', () => {
6
+ void it('should return the timestamp of the instance', () =>
7
+ assert.equal(
8
+ instanceTs({
9
+ ObjectID: 14210,
10
+ ObjectVersion: '1.0',
11
+ Resources: {
12
+ '0': 3.5399999618530273,
13
+ '1': 4.168000221252441,
14
+ '99': '2024-02-23T10:18:20.474Z',
15
+ },
16
+ }).getTime(),
17
+ new Date('2024-02-23T10:18:20.474Z').getTime(),
18
+ ))
19
+ })