Skip to content

Commit

Permalink
util: Add recvTime to uplink decoder input
Browse files Browse the repository at this point in the history
  • Loading branch information
vlasebian committed Jan 22, 2025
1 parent d716835 commit 74d0af3
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ For details about compatibility between different releases, see the **Commitment

### Added

- Add recvTime field to the decodeUplink input in payload formatters

### Changed

### Deprecated
Expand Down
45 changes: 30 additions & 15 deletions pkg/messageprocessors/javascript/javascript.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"reflect"
"runtime/trace"
"strings"
"time"

"go.thethings.network/lorawan-stack/v3/pkg/errors"
"go.thethings.network/lorawan-stack/v3/pkg/goproto"
Expand Down Expand Up @@ -101,8 +102,8 @@ func (h *host) CompileDownlinkEncoder(

return func(
ctx context.Context,
ids *ttnpb.EndDeviceIdentifiers,
version *ttnpb.EndDeviceVersionIdentifiers,
_ *ttnpb.EndDeviceIdentifiers,
_ *ttnpb.EndDeviceVersionIdentifiers,
msg *ttnpb.ApplicationDownlink,
) error {
return h.encodeDownlink(ctx, msg, run)
Expand Down Expand Up @@ -138,7 +139,7 @@ func (*host) encodeDownlink(
if err != nil {
return errInput.WithCause(err)
}
fPort := uint8(msg.FPort)
fPort := uint8(msg.FPort) // nolint:gosec
input := encodeDownlinkInput{
Data: data,
FPort: &fPort,
Expand Down Expand Up @@ -170,8 +171,9 @@ func (*host) encodeDownlink(
}

type decodeUplinkInput struct {
Bytes []uint8 `json:"bytes"`
FPort uint8 `json:"fPort"`
Bytes []uint8 `json:"bytes"`
FPort uint8 `json:"fPort"`
RecvTime int64 `json:"recvTime"` // UnixNano
}

type decodeUplinkOutput struct {
Expand Down Expand Up @@ -200,9 +202,13 @@ func wrapUplinkDecoderScript(script string) string {
function main(input) {
const bytes = input.bytes.slice();
const { fPort } = input;
const { fPort, recvTime } = input;
// Convert UnixNano to JavaScript Date.
const jsDate = new Date(Number(BigInt(recvTime) / 1000000n));
if (typeof decodeUplink === 'function') {
const decoded = decodeUplink({ bytes, fPort });
const decoded = decodeUplink({ bytes, fPort, recvTime: jsDate });
let normalized;
const { data, errors } = decoded;
if ((!errors || !errors.length) && data && typeof normalizeUplink === 'function') {
Expand Down Expand Up @@ -240,8 +246,8 @@ func (h *host) CompileUplinkDecoder(

return func(
ctx context.Context,
ids *ttnpb.EndDeviceIdentifiers,
version *ttnpb.EndDeviceVersionIdentifiers,
_ *ttnpb.EndDeviceIdentifiers,
_ *ttnpb.EndDeviceVersionIdentifiers,
msg *ttnpb.ApplicationUplink,
) error {
return h.decodeUplink(ctx, msg, run)
Expand Down Expand Up @@ -280,16 +286,17 @@ func appendValidationErrors(dst []string, measurements []normalizedpayload.Parse
return dst
}

func (*host) decodeUplink(
func (*host) decodeUplink( // nolint: gocyclo
ctx context.Context,
msg *ttnpb.ApplicationUplink,
run func(context.Context, string, ...any) (func(any) error, error),
) error {
defer trace.StartRegion(ctx, "decode uplink message").End()

input := decodeUplinkInput{
Bytes: msg.FrmPayload,
FPort: uint8(msg.FPort),
Bytes: msg.FrmPayload,
FPort: uint8(msg.FPort), // nolint:gosec
RecvTime: msg.ReceivedAt.AsTime().UnixNano(),
}

valueAs, err := run(ctx, "main", input)
Expand All @@ -306,6 +313,14 @@ func (*host) decodeUplink(
if errs := output.Decoded.Errors; len(errs) > 0 {
return errOutputErrors.WithAttributes("errors", strings.Join(errs, ", "))
}

// goproto.Struct does not support time.Time, use UnixNano instead.
for key, item := range output.Decoded.Data {
if t, ok := item.(time.Time); ok {
output.Decoded.Data[key] = t.UnixNano()
}
}

decodedPayload, err := goproto.Struct(output.Decoded.Data)
if err != nil {
return errOutput.WithCause(err)
Expand Down Expand Up @@ -432,8 +447,8 @@ func (h *host) CompileDownlinkDecoder(

return func(
ctx context.Context,
ids *ttnpb.EndDeviceIdentifiers,
version *ttnpb.EndDeviceVersionIdentifiers,
_ *ttnpb.EndDeviceIdentifiers,
_ *ttnpb.EndDeviceVersionIdentifiers,
msg *ttnpb.ApplicationDownlink,
) error {
return h.decodeDownlink(ctx, msg, run)
Expand Down Expand Up @@ -463,7 +478,7 @@ func (*host) decodeDownlink(

input := decodeDownlinkInput{
Bytes: msg.FrmPayload,
FPort: uint8(msg.FPort),
FPort: uint8(msg.FPort), // nolint:gosec
}

valueAs, err := run(ctx, "main", input)
Expand Down
27 changes: 27 additions & 0 deletions pkg/messageprocessors/javascript/javascript_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,33 @@ func TestDecodeUplink(t *testing.T) {
err := host.DecodeUplink(ctx, ids, nil, message, script)
a.So(err, should.BeNil)
}

// Check recvTime.
{
script := `
function decodeUplink(input) {
if (input.recvTime === undefined) {
throw new Error('recvTime is undefined');
}
if (input.recvTime === null) {
throw new Error('recvTime is null');
}
if (!(input.recvTime instanceof Date)) {
throw new Error('recvTime is not a date object, got ' + typeof input.recvTime);
}
return {
data: {
recvTime: input.recvTime
}
}
}
`
err := host.DecodeUplink(ctx, ids, nil, message, script)
a.So(err, should.BeNil)
}
}

func TestDecodeDownlink(t *testing.T) {
Expand Down

0 comments on commit 74d0af3

Please sign in to comment.