Skip to content

Commit cdbb5f9

Browse files
committed
fix(history): use proper types and add e2e test
1 parent cf4a985 commit cdbb5f9

File tree

6 files changed

+143
-70
lines changed

6 files changed

+143
-70
lines changed

cdk/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ new BackendApp({
4141
: undefined,
4242
version: (() => {
4343
const v = process.env.VERSION
44-
const defaultVersion = '0.0.0-development'
44+
const defaultVersion = `0.0.0-development`
4545
if (v === undefined)
4646
console.warn(`VERSION is not defined, using ${defaultVersion}!`)
4747
return v ?? defaultVersion

feature-runner/run-features.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ import { slashless } from '@hello.nrfcloud.com/nrfcloud-api-helpers/api'
2525
const iotData = new IoTDataPlaneClient({})
2626
const db = new DynamoDBClient({})
2727

28-
const backendConfig = await stackOutput(
29-
new CloudFormationClient({}),
30-
)<BackendStackOutputs>(STACK_NAME)
31-
3228
const { mockApiEndpoint, responsesTableName } = fromEnv({
3329
mockApiEndpoint: 'HTTP_API_MOCK_API_URL',
3430
responsesTableName: 'HTTP_API_MOCK_RESPONSES_TABLE_NAME',
3531
requestsTableName: 'HTTP_API_MOCK_REQUESTS_TABLE_NAME',
3632
})(process.env)
3733

34+
const backendConfig = await stackOutput(
35+
new CloudFormationClient({}),
36+
)<BackendStackOutputs>(STACK_NAME)
37+
3838
const print = (arg: unknown) =>
3939
typeof arg === 'object' ? JSON.stringify(arg) : arg
4040
const start = Date.now()

features/ResourceHistory.feature.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
exampleContext:
3+
deviceId: f1394b9a-a7c7-4a4a-ade2-bf2012f92e1f
4+
publicDeviceId: discloak-classify-nodosity
5+
ts: 1694503339523
6+
API: "https://api.nordicsemi.world/2024-04-15"
7+
---
8+
9+
# History can be fetched for numeric LwM2M object resources
10+
11+
## Background
12+
13+
Given I have the device id for a shared `kartverket-vasstandsdata` device in
14+
`deviceId` and the public device id in `publicDeviceId`
15+
16+
## Publish SenML via MQTT
17+
18+
Given I store `$millis()` into `ts`
19+
20+
And the device `${deviceId}` publishes this message to the topic
21+
`m/senml/${deviceId}`
22+
23+
```json
24+
[
25+
{
26+
"bn": "14230/0/",
27+
"bt": "$number{ts}",
28+
"n": "0",
29+
"v": 225.1
30+
},
31+
{
32+
"n": "1",
33+
"vs": "TRD"
34+
}
35+
]
36+
```
37+
38+
## Fetch the published data
39+
40+
When I `GET` `${API}/history?deviceId=${publicDeviceId}&instance=14230%2F0`
41+
42+
Then I should receive a
43+
`https://github.com/hello-nrfcloud/proto-map/history/resource` response
44+
45+
And `$.query` of the last response should match
46+
47+
```json
48+
{
49+
"ObjectID": 14230,
50+
"ObjectVersion": "1.0",
51+
"ObjectInstanceID": 0,
52+
"deviceId": "${publicDeviceId}",
53+
"binIntervalMinutes": 15
54+
}
55+
```
56+
57+
And `$.partialInstances[0]` of the last response should match
58+
59+
```json
60+
{
61+
"0": 225.1,
62+
"99": "$number{ts}"
63+
}
64+
```

lambda/queryHistory.ts

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ import {
1212
isLwM2MObjectID,
1313
type LWM2MObjectInfo,
1414
} from '@hello.nrfcloud.com/proto-map'
15-
import { PublicDeviceId } from '@hello.nrfcloud.com/proto-map/api'
15+
import {
16+
Context,
17+
PublicDeviceId,
18+
ResourceHistory,
19+
} from '@hello.nrfcloud.com/proto-map/api'
1620
import { fromEnv } from '@nordicsemiconductor/from-env'
1721
import { parseResult } from '@nordicsemiconductor/timestream-helpers'
18-
import { Type } from '@sinclair/typebox'
22+
import { Type, type Static } from '@sinclair/typebox'
1923
import type {
2024
APIGatewayProxyEventV2,
2125
APIGatewayProxyResultV2,
@@ -53,6 +57,16 @@ const validateInput = validateWithTypeBox(
5357
}),
5458
)
5559

60+
// TODO: cache globally
61+
const availableColumns =
62+
(
63+
await ts.send(
64+
new QueryCommand({
65+
QueryString: `SELECT * FROM "${DatabaseName}"."${TableName}" LIMIT 1`,
66+
}),
67+
)
68+
)?.ColumnInfo?.map(({ Name }) => Name) ?? []
69+
5670
const h = async (
5771
event: APIGatewayProxyEventV2,
5872
): Promise<APIGatewayProxyResultV2> => {
@@ -81,26 +95,27 @@ const h = async (
8195
const def = definitions[ObjectID]
8296

8397
try {
84-
const res = await queryResourceHistory({
98+
const history = await queryResourceHistory({
8599
def,
86100
instance: InstanceID,
87101
deviceId,
88102
})
103+
const result: Static<typeof ResourceHistory> = {
104+
'@context': Context.history.resource.toString(),
105+
query: {
106+
ObjectID,
107+
ObjectVersion: def.ObjectVersion,
108+
ObjectInstanceID: InstanceID,
109+
deviceId,
110+
binIntervalMinutes,
111+
},
112+
partialInstances: history,
113+
}
89114
return aResponse(
90115
200,
91116
{
92-
// FIXME: add to proto-map
93-
'@context': new URL(
94-
'https://github.com/hello-nrfcloud/proto-map/history',
95-
),
96-
query: {
97-
ObjectID,
98-
ObjectVersion: def.ObjectVersion,
99-
InstanceID,
100-
deviceId,
101-
binIntervalMinutes,
102-
},
103-
partialInstances: res,
117+
...result,
118+
'@context': Context.history.resource,
104119
},
105120
binIntervalMinutes * 60,
106121
)
@@ -131,17 +146,9 @@ const queryResourceHistory = async ({
131146
def: LWM2MObjectInfo
132147
instance: number
133148
deviceId: string
134-
}) => {
135-
// TODO: cache
136-
const availableColumns =
137-
(
138-
await ts.send(
139-
new QueryCommand({
140-
QueryString: `SELECT * FROM "${DatabaseName}"."${TableName}" LIMIT 1`,
141-
}),
142-
)
143-
)?.ColumnInfo?.map(({ Name }) => Name) ?? []
144-
149+
}): Promise<
150+
Array<Record<number, string | number | boolean> & { ts: string }>
151+
> => {
145152
const resourceNames = Object.values(def.Resources)
146153
.filter(isNumeric)
147154
.map<[string, number]>(({ ResourceID }) => [

package-lock.json

Lines changed: 37 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"@bifravst/run": "1.2.0",
4242
"@commitlint/config-conventional": "19.2.2",
4343
"@hello.nrfcloud.com/bdd-markdown-steps": "2.1.0",
44-
"@nordicsemiconductor/bdd-markdown": "8.1.0",
44+
"@nordicsemiconductor/bdd-markdown": "8.1.1",
4545
"@nordicsemiconductor/cloudformation-helpers": "9.0.3",
4646
"@swc/cli": "0.3.12",
4747
"@swc/core": "1.4.16",
@@ -102,13 +102,13 @@
102102
"@hello.nrfcloud.com/certificate-helpers": "1.0.0",
103103
"@hello.nrfcloud.com/lambda-helpers": "1.0.2",
104104
"@hello.nrfcloud.com/nrfcloud-api-helpers": "2.0.0",
105-
"@hello.nrfcloud.com/proto": "6.6.2",
106-
"@hello.nrfcloud.com/proto-map": "5.3.2",
105+
"@hello.nrfcloud.com/proto": "6.6.3",
106+
"@hello.nrfcloud.com/proto-map": "5.4.2",
107107
"@middy/core": "5.3.2",
108108
"@nordicsemiconductor/from-env": "3.0.1",
109109
"@nordicsemiconductor/random-words": "8.0.1",
110110
"@nordicsemiconductor/timestream-helpers": "6.0.2",
111-
"@sinclair/typebox": "0.32.20",
111+
"@sinclair/typebox": "0.32.21",
112112
"id128": "1.6.6",
113113
"lodash-es": "4.17.21"
114114
}

0 commit comments

Comments
 (0)