diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 963c4e1..fd3a52e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,7 +98,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v8 with: - version: v2.1 + version: v2.10.1 - name: Run JSON tags camelCase check run: make check-json-tags diff --git a/pkg/decoder/tagxl/v1/decoder.go b/pkg/decoder/tagxl/v1/decoder.go index 8b02b7e..0195b90 100644 --- a/pkg/decoder/tagxl/v1/decoder.go +++ b/pkg/decoder/tagxl/v1/decoder.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "reflect" + "slices" "time" "github.com/truvami/decoder/pkg/common" @@ -129,7 +130,7 @@ func (t TagXLv1Decoder) getConfig(port uint8, payload []byte) (common.PayloadCon return ((v.([]byte)[0] >> 1) & 0x01) != 0 }}, {Name: "ResetCount", Tag: 0x49, Optional: true}, - {Name: "ResetCause", Tag: 0x4a, Optional: true}, + {Name: "ResetCause", Tag: 0x4a, Optional: true, Feature: decoder.FeatureResetReason}, {Name: "GnssScans", Tag: 0x4b, Optional: true, Transform: func(v any) any { return uint16((common.BytesToUint32(v.([]byte)) >> 16) & 0xffff) }}, @@ -144,7 +145,7 @@ func (t TagXLv1Decoder) getConfig(port uint8, payload []byte) (common.PayloadCon }}, }, TargetType: reflect.TypeOf(Port151Payload{}), - Features: []decoder.Feature{decoder.FeatureDataRate, decoder.FeatureResetReason}, + Features: []decoder.Feature{decoder.FeatureDataRate}, }, nil case 152: if len(payload) < 1 { @@ -667,6 +668,11 @@ func (t TagXLv1Decoder) Decode(ctx context.Context, data string, port uint8) (*d } decodedData, err := common.Decode(&data, &config) + if resetReason, ok := decodedData.(decoder.UplinkFeatureResetReason); ok && resetReason.GetResetReason() == decoder.ResetReasonUnknown { + config.Features = slices.DeleteFunc(config.Features, func(feature decoder.Feature) bool { + return feature == decoder.FeatureResetReason + }) + } return decoder.NewDecodedUplink(config.Features, decodedData), err } } diff --git a/pkg/decoder/tagxl/v1/decoder_test.go b/pkg/decoder/tagxl/v1/decoder_test.go index b4a2954..3994aaf 100644 --- a/pkg/decoder/tagxl/v1/decoder_test.go +++ b/pkg/decoder/tagxl/v1/decoder_test.go @@ -1768,25 +1768,59 @@ func TestPort151ResetReasonFromDecode(t *testing.T) { Data: decoder.NewDecodedUplink([]decoder.Feature{decoder.FeatureWiFi}, Port197Payload{}), }, zap.NewExample()) - // Real-world payload taken from the existing TestDecode fixtures: contains - // 4a 04 00 00 00 02 (PIN reset). - const payload = "4c2a0940010f4104012c1c204204012c05dc43010644011e45020d4e4604f6c7d8104902000a4a0400000002" - - decodedUplink, err := d.Decode(context.TODO(), payload, 151) - if err != nil { - t.Fatalf("unexpected error: %v", err) + tests := []struct { + name string + payload string + expectFeature bool + expected decoder.ResetReason + }{ + { + name: "without reset cause", + payload: "4c050145020a92", + expectFeature: false, + expected: decoder.ResetReasonUnknown, + }, + { + name: "zero reset cause", + payload: "4c07014a0400000000", + expectFeature: false, + expected: decoder.ResetReasonUnknown, + }, + { + name: "VREGIN-only reset cause", + payload: "4c07014a0480000000", + expectFeature: false, + expected: decoder.ResetReasonUnknown, + }, + { + name: "PIN reset", + // Real-world payload taken from the existing TestDecode fixtures: contains + // 4a 04 00 00 00 02 (PIN reset). + payload: "4c2a0940010f4104012c1c204204012c05dc43010644011e45020d4e4604f6c7d8104902000a4a0400000002", + expectFeature: true, + expected: decoder.ResetReasonPinReset, + }, } - if !decodedUplink.Is(decoder.FeatureResetReason) { - t.Fatalf("expected FeatureResetReason to be set") - } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + decodedUplink, err := d.Decode(context.TODO(), tc.payload, 151) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } - resetReason, ok := decodedUplink.Data.(decoder.UplinkFeatureResetReason) - if !ok { - t.Fatalf("expected UplinkFeatureResetReason, got %T", decodedUplink.Data) - } + if got := decodedUplink.Is(decoder.FeatureResetReason); got != tc.expectFeature { + t.Fatalf("expected FeatureResetReason presence %v, got %v", tc.expectFeature, got) + } + + resetReason, ok := decodedUplink.Data.(decoder.UplinkFeatureResetReason) + if !ok { + t.Fatalf("expected UplinkFeatureResetReason, got %T", decodedUplink.Data) + } - if got := resetReason.GetResetReason(); got != decoder.ResetReasonPinReset { - t.Errorf("expected %v, got %v", decoder.ResetReasonPinReset, got) + if got := resetReason.GetResetReason(); got != tc.expected { + t.Errorf("expected %v, got %v", tc.expected, got) + } + }) } }