Skip to content

Commit 29bd099

Browse files
committed
fix(lwm2m): allow timestamps in the future of up to 60 seconds
Some devices clocks drift so that they report a timestamp a few seconds in the future. This change allows the offset to be up to 60 seconds.
1 parent 3ebaf2e commit 29bd099

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

historicalData/instanceToMeasures.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
timestampResources,
88
type LwM2MObjectInstance,
99
} from '@hello.nrfcloud.com/proto-map/lwm2m'
10+
import { isNumber } from 'lodash-es'
11+
import { correctOffset } from '../lwm2m/correctOffset.js'
1012
import { InvalidTimeError } from '../lwm2m/InvalidTimeError.js'
1113
import { isNumeric } from '../lwm2m/isNumeric.js'
1214
import { isUnixTimeInSeconds } from '../lwm2m/isUnixTimeInSeconds.js'
@@ -30,7 +32,16 @@ export const instanceToMeasures = ({
3032
}
3133
}
3234

33-
if (!isUnixTimeInSeconds(ts)) {
35+
if (!isNumber(ts)) {
36+
return {
37+
error: new InvalidTimeError(
38+
`Not a timestamp resource defined for ${ObjectID}: ${ts.toString()}!`,
39+
),
40+
}
41+
}
42+
const correctedTs = correctOffset(ts)
43+
44+
if (!isUnixTimeInSeconds(correctedTs)) {
3445
return {
3546
error: new InvalidTimeError(
3647
`Timestamp ${JSON.stringify(ts)} for ${ObjectID} is not a valid unix time in seconds!`,

lwm2m/correctOffset.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import assert from 'node:assert/strict'
2+
import { describe, it } from 'node:test'
3+
import { correctOffset } from './correctOffset.js'
4+
import { isUnixTimeInSeconds } from './isUnixTimeInSeconds.js'
5+
6+
void describe('correctOffset()', () => {
7+
void it('should correct timestamps in the future of up to 60 seconds', () => {
8+
assert.equal(
9+
isUnixTimeInSeconds(correctOffset(Date.now() / 1000 + 1)),
10+
true,
11+
'should correct 1 second in the future',
12+
)
13+
assert.equal(
14+
isUnixTimeInSeconds(correctOffset(Date.now() / 1000 + 60)),
15+
true,
16+
'should correct 60 seconds in the future',
17+
)
18+
assert.equal(
19+
isUnixTimeInSeconds(correctOffset(Date.now() / 1000 + 61)),
20+
false,
21+
'should not correct 61 seconds in the future',
22+
)
23+
})
24+
})

lwm2m/correctOffset.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Corrects an offset of up to 60 seconds in the future.
3+
* This is needed because some devices clocks drift, and they report timestamps in the future.
4+
*/
5+
export const correctOffset = (ts: number, maxOffsetSeconds = 60): number => {
6+
const nowSeconds = Math.ceil(Date.now() / 1000)
7+
const offset = ts * 1000 - nowSeconds
8+
if (offset < 0) {
9+
return ts
10+
}
11+
return ts - Math.min(offset, maxOffsetSeconds)
12+
}

lwm2m/isUnixTimeInSeconds.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { isNumber } from 'lodash-es'
2+
13
export const isUnixTimeInSeconds = (value: unknown): value is number => {
2-
if (typeof value !== 'number') return false
4+
if (!isNumber(value)) return false
35
if (value < 1700000000) return false
46
if (value * 1000 > Date.now()) return false
57
return true

0 commit comments

Comments
 (0)