Skip to content

Commit

Permalink
feat(wirepas): do not send unused data
Browse files Browse the repository at this point in the history
  • Loading branch information
coderbyheart committed Feb 7, 2024
1 parent 81d09ac commit 55cf14d
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 42 deletions.
4 changes: 4 additions & 0 deletions wirepas-5g-mesh-gateway/ScannableArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ export class ScannableArray {
hasNext(): boolean {
return this.array.at(this.index + 1) !== undefined
}

pos(): number {
return this.index
}
}
10 changes: 2 additions & 8 deletions wirepas-5g-mesh-gateway/decodePayload.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,14 @@ void describe('decodePayload()', () => {
const decoded = decodePayload(payload)

assert.deepEqual(decoded, {
counter: 49730,
timestamp: 251355997789000,
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
temperature: 24.479999542236328,
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
humidity: 17.695999145507812,
raw_pressure: 100325,
raw_gas: 81300,
temp: 24.479999542236328,
})
})

void it('should decode a button press', () =>
assert.deepEqual(decodePayload(Buffer.from('010002', 'hex')), {
button: 2,
btn: 2,
}))

void it('should decode a LED state change', () =>
Expand Down
41 changes: 13 additions & 28 deletions wirepas-5g-mesh-gateway/decodePayload.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { ScannableArray } from './ScannableArray.js'
export type Wirepas5GMeshNodePayload = {
counter?: number
// Uptime in nanoseconds
timestamp?: number // e.g. 251355997789000 / 1000 / 1000 / 1000 / 60 / 60 / 24 = 2.909 days
temperature?: number
button?: number
humidity?: number
raw_pressure?: number
raw_gas?: number
temp?: number
btn?: number
led?: {
r?: boolean
g?: boolean
Expand All @@ -17,6 +11,7 @@ export type Wirepas5GMeshNodePayload = {

enum MessageType {
COUNTER = 0x01, // [0x04] [size_t counter]
// Uptime in nanoseconds, e.g. 251355997789000 / 1000 / 1000 / 1000 / 60 / 60 / 24 = 2.909 days
TIMESTAMP = 0x02, // [0x08] [int64_t timestamp]
IAQ = 0x03, // [0x02] [uint16_t iaq]
IAQ_ACC = 0x04, // [0x01] [uint8_t iaq_acc]
Expand Down Expand Up @@ -70,6 +65,7 @@ Byte 3: State. 0x00: off, 0x01: on.
*/
export const decodePayload = (
payload: Uint8Array,
onUnknown?: (type: number, pos: number) => void,
): Wirepas5GMeshNodePayload => {
const msg = new ScannableArray(payload)

Expand All @@ -79,14 +75,14 @@ export const decodePayload = (
if (payload.length === 3 && msg.peek() === 1) {
msg.next() // skip type
msg.next() // skip len
return { button: msg.peek() }
return { btn: readUint(msg, 1) }
}

// LED special case
if (payload.length === 3 && msg.peek() === 3) {
msg.next() // skip type
const color = msg.getChar()
const state = msg.getChar()
const color = readUint(msg, 1)
const state = readUint(msg, 1)
switch (color) {
case LED_COLOR.BLUE:
return {
Expand Down Expand Up @@ -117,14 +113,9 @@ export const decodePayload = (
for (let i = 0; i < len; i++) msg.getChar()
}
switch (type) {
// Periodic message with a counter value
// Skip
case MessageType.COUNTER:
message = { ...message, counter: readUint(msg, len) }
continue
case MessageType.TIMESTAMP:
message = { ...message, timestamp: readUint(msg, len) }
continue
// Skip
case MessageType.IAQ:
case MessageType.IAQ_ACC:
case MessageType.SIAQ:
Expand All @@ -139,22 +130,16 @@ export const decodePayload = (
case MessageType.CO2_ACC:
case MessageType.TEMP_RAW:
case MessageType.HUM_RAW:
skip()
continue
case MessageType.TEMPERATURE:
message = { ...message, temperature: readFloat(msg, len) }
continue
case MessageType.HUMIDITY:
message = { ...message, humidity: readFloat(msg, len) }
continue
case MessageType.PRESS_RAW:
message = { ...message, raw_pressure: readFloat(msg, len) }
continue
case MessageType.GAS_RAW:
message = { ...message, raw_gas: readFloat(msg, len) }
skip()
continue
case MessageType.TEMPERATURE:
message = { ...message, temp: readFloat(msg, len) }
continue
default:
console.error(`Unknown message type`, type)
onUnknown?.(type, msg.pos() - 1)
skip()
break
}
Expand Down
32 changes: 26 additions & 6 deletions wirepas-5g-mesh-gateway/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
type ThingAttribute,
} from '@aws-sdk/client-iot'
import { merge } from 'lodash-es'
import { decodePayload } from './decodePayload.js'

const { region, accessKeyId, secretAccessKey, gatewayEndpoint } = fromEnv({
region: 'GATEWAY_REGION',
Expand Down Expand Up @@ -113,10 +114,24 @@ client.on('message', (_, message) => {
nodes[gwId] = merge(
{
[sourceAddress]: {
travelTimeMs,
lat: travelTimeMs,
...(hopCount !== undefined ? { hops: hopCount } : {}),
rxTime,
ts: rxTime,
qos,
payload: ((payload) => {
try {
return decodePayload(payload, (type, pos) => {
debug(`Unknown message type`, type)
debug(Buffer.from(payload).toString('hex'))
debug(' '.repeat(Math.max(0, pos - 1)) + ' ^')
})
} catch {
debug(
`Failed to decode payload: ${Buffer.from(payload).toString('hex')}`,
)
}
return {}
})(payload),
},
},
nodes[gwId],
Expand All @@ -127,8 +142,13 @@ client.on('message', (_, message) => {
// Regularly send buffered updates
setInterval(async () => {
await Promise.all(
Object.entries(nodes).map(async ([gwId, nodes]) =>
iotDataClient.send(
Object.entries(nodes).map(async ([gwId, nodes]) => {
Object.entries(nodes).forEach(([nodeId, data]) => {
debug()
debug(gwId, nodeId, JSON.stringify(data))
})

return iotDataClient.send(
new UpdateThingShadowCommand({
thingName: gwId,
payload: JSON.stringify({
Expand All @@ -139,8 +159,8 @@ setInterval(async () => {
},
}),
}),
),
),
)
}),
)
nodes = {}
}, stateFlushInterval * 1000)
Expand Down

0 comments on commit 55cf14d

Please sign in to comment.