Skip to content

Commit

Permalink
all: Add custom JSON serialization for sx1301 global config file
Browse files Browse the repository at this point in the history
  • Loading branch information
cvetkovski98 committed Nov 19, 2023
1 parent 6164dce commit fd88d49
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 0 deletions.
33 changes: 33 additions & 0 deletions pkg/pfconfig/semtechudp/semtechudp.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package semtechudp

import (
"encoding/json"

"go.thethings.network/lorawan-stack/v3/pkg/frequencyplans"
"go.thethings.network/lorawan-stack/v3/pkg/pfconfig/shared"
"go.thethings.network/lorawan-stack/v3/pkg/ttnpb"
Expand All @@ -28,6 +30,37 @@ type Config struct {
GatewayConf GatewayConf `json:"gateway_conf"`
}

// SingleSX1301Config is a helper type for marshaling a config with a single SX1301Config.
type singleSX1301Config struct {
SX1301Conf *shared.SX1301Config `json:"SX1301_conf"`
GatewayConf GatewayConf `json:"gateway_conf"`
}

// MarshalJSON implements json.Marshaler.
// Serializes the SX1301Conf field as an object if it contains a single element and as an array otherwise.
func (c Config) MarshalJSON() ([]byte, error) {
if len(c.SX1301Conf) == 1 {
return json.Marshal(singleSX1301Config{
SX1301Conf: c.SX1301Conf[0],
GatewayConf: c.GatewayConf,
})
}
type alias Config
return json.Marshal(alias(c))
}

// UnmarshalJSON implements json.Unmarshaler.
func (c *Config) UnmarshalJSON(data []byte) error {
var single singleSX1301Config
if err := json.Unmarshal(data, &single); err == nil {
c.SX1301Conf = []*shared.SX1301Config{single.SX1301Conf}
c.GatewayConf = single.GatewayConf
return nil
}
type alias Config
return json.Unmarshal(data, (*alias)(c))
}

// GatewayConf contains the configuration for the gateway's server connection.
type GatewayConf struct {
GatewayID string `json:"gateway_ID,omitempty"`
Expand Down
166 changes: 166 additions & 0 deletions pkg/pfconfig/semtechudp/semtechudp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Copyright © 2023 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package semtechudp_test

import (
"encoding/json"
"testing"

"github.com/smarty/assertions"
"go.thethings.network/lorawan-stack/v3/pkg/pfconfig/semtechudp"
"go.thethings.network/lorawan-stack/v3/pkg/pfconfig/shared"
"go.thethings.network/lorawan-stack/v3/pkg/util/test/assertions/should"
)

func getSX1301Conf(t *testing.T) *shared.SX1301Config {
t.Helper()

return &shared.SX1301Config{
LoRaWANPublic: true,
ClockSource: 1,
AntennaGain: 0,
Radios: []shared.RFConfig{
{
Enable: true,
Type: "SX1257",
Frequency: 867500000,
TxEnable: true,
TxFreqMin: 863000000,
TxFreqMax: 870000000,
RSSIOffset: -166,
},
{
Enable: true, Type: "SX1257",
Frequency: 868500000,
TxEnable: false,
TxFreqMin: 0,
TxFreqMax: 0,
RSSIOffset: -166,
},
},
Channels: []shared.IFConfig{
{Enable: true, Radio: 1, IFValue: -400000, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 1, IFValue: -200000, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 1, IFValue: 0, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 0, IFValue: -400000, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 0, IFValue: -200000, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 0, IFValue: 0, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 0, IFValue: 200000, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
{Enable: true, Radio: 0, IFValue: 400000, Bandwidth: 0, SpreadFactor: 0, Datarate: 0},
},
LoRaStandardChannel: &shared.IFConfig{
Enable: true,
Radio: 1,
IFValue: -200000,
Bandwidth: 250000,
SpreadFactor: 7,
Datarate: 0,
},
FSKChannel: &shared.IFConfig{
Enable: true,
Radio: 1,
IFValue: -200000,
Bandwidth: 250000,
SpreadFactor: 7,
Datarate: 0,
},
TxLUTConfigs: []shared.TxLUTConfig{
{PAGain: 0, MixGain: 8, RFPower: -6, DigGain: 0},
{PAGain: 0, MixGain: 10, RFPower: -3, DigGain: 0},
{PAGain: 0, MixGain: 12, RFPower: 0, DigGain: 0},
{PAGain: 1, MixGain: 8, RFPower: 3, DigGain: 0},
{PAGain: 1, MixGain: 10, RFPower: 6, DigGain: 0},
{PAGain: 1, MixGain: 12, RFPower: 10, DigGain: 0},
{PAGain: 1, MixGain: 13, RFPower: 11, DigGain: 0},
{PAGain: 2, MixGain: 9, RFPower: 12, DigGain: 0},
{PAGain: 1, MixGain: 15, RFPower: 13, DigGain: 0},
{PAGain: 2, MixGain: 10, RFPower: 14, DigGain: 0},
{PAGain: 2, MixGain: 11, RFPower: 16, DigGain: 0},
{PAGain: 3, MixGain: 9, RFPower: 20, DigGain: 0},
{PAGain: 3, MixGain: 10, RFPower: 23, DigGain: 0},
{PAGain: 3, MixGain: 11, RFPower: 25, DigGain: 0},
{PAGain: 3, MixGain: 12, RFPower: 26, DigGain: 0},
{PAGain: 3, MixGain: 14, RFPower: 27, DigGain: 0},
},
}
}

func getGtwConfig(t *testing.T) semtechudp.GatewayConf {
t.Helper()

return semtechudp.GatewayConf{
ServerAddress: "localhost",
ServerPortUp: 1700,
ServerPortDown: 1700,
Servers: []semtechudp.GatewayConf{
{
ServerAddress: "localhost",
ServerPortUp: 1700,
ServerPortDown: 1700,
Enabled: true,
},
},
}
}

func TestConfigSerialization(t *testing.T) {
t.Parallel()

testCases := []struct {
Name string
*semtechudp.Config
}{
{
Name: "Single Frequency Plan",
Config: &semtechudp.Config{
SX1301Conf: []*shared.SX1301Config{
getSX1301Conf(t),
},
GatewayConf: getGtwConfig(t),
},
},
{
Name: "Multiple Frequency Plans",
Config: &semtechudp.Config{
SX1301Conf: []*shared.SX1301Config{
getSX1301Conf(t),
getSX1301Conf(t),
getSX1301Conf(t),
},
GatewayConf: getGtwConfig(t),
},
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
a := assertions.New(t)
marshalled, err := json.Marshal(tc.Config)
if !a.So(err, should.BeNil) {
t.FailNow()
}

var cfg2 semtechudp.Config
err = json.Unmarshal(marshalled, &cfg2)
if !a.So(err, should.BeNil) {
t.FailNow()
}

a.So(cfg2, should.Resemble, *tc.Config)
})
}
}

0 comments on commit fd88d49

Please sign in to comment.