Skip to content

Commit 8fcdce6

Browse files
committed
Move BasicStation channel-plan configuration to config file.
This makes it possible to use BasicStation gateways without the need of having LoRa Server configured with a Gateway Profile.
1 parent 3c1b07d commit 8fcdce6

File tree

9 files changed

+674
-23
lines changed

9 files changed

+674
-23
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# hidden files
22
.*
33

4+
# Vagrant
5+
Vagrantfile
6+
47
# configuration files
58
/*.toml
69

cmd/lora-gateway-bridge/cmd/configfile.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,59 @@ type="{{ .Backend.Type }}"
135135
# Maximum frequency (Hz).
136136
frequency_max={{ .Backend.BasicStation.FrequencyMax }}
137137
138+
# Concentrator configuration.
139+
#
140+
# This section contains the configuration for the SX1301 concentrator chips.
141+
# Example:
142+
# [[backend.basic_station.concentrators]]
143+
#
144+
# # Multi-SF channel configuration.
145+
# [backend.basic_station.concentrators.multi_sf]
146+
#
147+
# # Frequencies (Hz).
148+
# frequencies=[
149+
# 868100000,
150+
# 868300000,
151+
# 868500000,
152+
# 867100000,
153+
# 867300000,
154+
# 867500000,
155+
# 867700000,
156+
# 867900000,
157+
# ]
158+
#
159+
# # LoRa STD channel.
160+
# [backend.basic_station.concentrators.lora_std]
161+
#
162+
# # Frequency (Hz).
163+
# frequency=868300000
164+
#
165+
# # Bandwidth (Hz).
166+
# bandwidth=250000
167+
#
168+
# # Spreading factor.
169+
# spreading_factor=7
170+
#
171+
# # FSK channel.
172+
# [backend.basic_station.concentrators.fsk]
173+
#
174+
# # Frequency (Hz).
175+
# frequency=868800000
176+
{{ range $i, $concentrator := .Backend.BasicStation.Concentrators }}
177+
[[backend.basic_station.concentrators]]
178+
[backend.basic_station.concentrators.multi_sf]
179+
frequencies=[{{ range $index, $elm := $concentrator.MultiSF.Frequencies }}
180+
{{ $elm }},{{ end }}
181+
]
182+
183+
[backend.basic_station.concentrators.lora_std]
184+
frequency={{ $concentrator.LoRaSTD.Frequency }}
185+
bandwidth={{ $concentrator.LoRaSTD.Bandwidth }}
186+
spreading_factor={{ $concentrator.LoRaSTD.SpreadingFactor }}
187+
188+
[backend.basic_station.concentrators.fsk]
189+
frequency={{ $concentrator.FSK.Frequency }}
190+
{{ end }}
138191
139192
# Integration configuration.
140193
[integration]

docs/content/backends/basic-station.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,12 @@ of each gateway as a HEX encoded string, e.g. `0102030405060708`.
3737

3838
## Channel-plan / `router_config`
3939

40-
When using Basic Station powered gateways, assigning a _Gateway Profile_ to a
41-
gateway within LoRa (App) Server is a requirement. As part of the connection
42-
handshake, LoRa Gateway Bridge must send the channel-plan configuration to the
43-
Basic Station. The flow for this is:
44-
45-
* Basic Station sends a `version` message to the LoRa Gateway Bridge
46-
* The LoRa Gateway Bridge sends a `stats` [Event]({{<ref "payloads/events.md">}})
47-
* [LoRa Server](/loraserver/) responds with a `config` [Command]({{<ref "payloads/commands.md">}}), containing the channel-plan from the _Gateway Profile_
48-
* The LoRa Gateway Bridge forwards this as `router_config` to the Basic Station
40+
You must configure the gateway channel-plan in the LoRa Gateway Bridge
41+
[Configuration]({{<ref "/install/config.md">}}) file.
42+
43+
**Note:** In previous versions of the LoRa Gateway Bridge, you had to configure
44+
a _Gateway Profile_. This has been deprecated if favor of directly configuring
45+
the channels in the configuration file.
4946

5047
## Known issues
5148

docs/content/install/config.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,45 @@ type="semtech_udp"
179179
# Maximum frequency (Hz).
180180
frequency_max=870000000
181181

182+
# Concentrator configuration.
183+
#
184+
# This section contains the configuration for the SX1301 concentrator chips.
185+
# Example:
186+
# [[backend.basic_station.concentrators]]
187+
#
188+
# # Multi-SF channel configuration.
189+
# [backend.basic_station.concentrators.multi_sf]
190+
#
191+
# # Frequencies (Hz).
192+
# frequencies=[
193+
# 868100000,
194+
# 868300000,
195+
# 868500000,
196+
# 867100000,
197+
# 867300000,
198+
# 867500000,
199+
# 867700000,
200+
# 867900000,
201+
# ]
202+
#
203+
# # LoRa STD channel.
204+
# [backend.basic_station.concentrators.lora_std]
205+
#
206+
# # Frequency (Hz).
207+
# frequency=868300000
208+
#
209+
# # Bandwidth (Hz).
210+
# bandwidth=250000
211+
#
212+
# # Spreading factor.
213+
# spreading_factor=7
214+
#
215+
# # FSK channel.
216+
# [backend.basic_station.concentrators.fsk]
217+
#
218+
# # Frequency (Hz).
219+
# frequency=868800000
220+
182221

183222
# Integration configuration.
184223
[integration]

internal/backend/basicstation/backend.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type Backend struct {
5858
joinEUIs [][2]lorawan.EUI64
5959
frequencyMin uint32
6060
frequencyMax uint32
61+
routerConfig *structs.RouterConfig
6162

6263
// diidMap stores the mapping of diid to UUIDs. This should take ~ 1MB of
6364
// memory. Optionaly this could be optimized by letting keys expire after
@@ -117,6 +118,15 @@ func NewBackend(conf config.Config) (*Backend, error) {
117118
return nil, errors.Wrap(err, "get band config error")
118119
}
119120

121+
if len(conf.Backend.BasicStation.Concentrators) != 0 {
122+
conf, err := structs.GetRouterConfig(b.region, b.netIDs, b.joinEUIs, b.frequencyMin, b.frequencyMax, conf.Backend.BasicStation.Concentrators)
123+
if err != nil {
124+
return nil, errors.Wrap(err, "get router config error")
125+
}
126+
127+
b.routerConfig = &conf
128+
}
129+
120130
mux := http.NewServeMux()
121131
mux.HandleFunc("/router-info", func(w http.ResponseWriter, r *http.Request) {
122132
b.websocketWrap(b.handleRouterInfo, w, r)
@@ -241,7 +251,7 @@ func (b *Backend) SendDownlinkFrame(df gw.DownlinkFrame) error {
241251
}
242252

243253
func (b *Backend) ApplyConfiguration(gwConfig gw.GatewayConfiguration) error {
244-
rc, err := structs.GetRouterConfig(b.region, b.netIDs, b.joinEUIs, b.frequencyMin, b.frequencyMax, gwConfig)
254+
rc, err := structs.GetRouterConfigOld(b.region, b.netIDs, b.joinEUIs, b.frequencyMin, b.frequencyMax, gwConfig)
245255
if err != nil {
246256
return errors.Wrap(err, "get router config error")
247257
}
@@ -480,12 +490,25 @@ func (b *Backend) handleVersion(gatewayID lorawan.EUI64, pl structs.Version) {
480490
return
481491
}
482492

483-
b.gatewayStatsChan <- gw.GatewayStats{
484-
GatewayId: gatewayID[:],
485-
Ip: g.conn.RemoteAddr().String(),
486-
Time: ts,
487-
ConfigVersion: g.configVersion,
493+
// TODO: remove this in the next major release
494+
if b.routerConfig == nil {
495+
b.gatewayStatsChan <- gw.GatewayStats{
496+
GatewayId: gatewayID[:],
497+
Ip: g.conn.RemoteAddr().String(),
498+
Time: ts,
499+
ConfigVersion: g.configVersion,
500+
}
501+
502+
return
503+
}
504+
505+
websocketSendCounter("router_config").Inc()
506+
if err := b.sendToGateway(gatewayID, *b.routerConfig); err != nil {
507+
log.WithError(err).Error("backend/basicstation: send to gateway error")
508+
return
488509
}
510+
511+
log.WithField("gateway_id", gatewayID).Info("backend/basicstation: router-config message sent to gateway")
489512
}
490513

491514
func (b *Backend) handleJoinRequest(gatewayID lorawan.EUI64, v structs.JoinRequest) {

internal/backend/basicstation/backend_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ func (ts *BackendTestSuite) TestRouterInfo() {
9696
}, resp)
9797
}
9898

99-
func (ts *BackendTestSuite) TestVersion() {
99+
func (ts *BackendTestSuite) TestVersionOld() {
100100
assert := require.New(ts.T())
101+
ts.backend.routerConfig = nil
101102

102103
ver := structs.Version{
103104
MessageType: structs.VersionMessage,
@@ -110,6 +111,25 @@ func (ts *BackendTestSuite) TestVersion() {
110111
assert.Equal([]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, stats.GatewayId)
111112
}
112113

114+
func (ts *BackendTestSuite) TestVersion() {
115+
assert := require.New(ts.T())
116+
ts.backend.routerConfig = &structs.RouterConfig{
117+
MessageType: structs.RouterConfigMessage,
118+
}
119+
120+
ver := structs.Version{
121+
MessageType: structs.VersionMessage,
122+
Protocol: 2,
123+
}
124+
125+
assert.NoError(ts.wsClient.WriteJSON(ver))
126+
127+
var routerConfig structs.RouterConfig
128+
assert.NoError(ts.wsClient.ReadJSON(&routerConfig))
129+
130+
assert.Equal(*ts.backend.routerConfig, routerConfig)
131+
}
132+
113133
func (ts *BackendTestSuite) TestUplinkDataFrame() {
114134
assert := require.New(ts.T())
115135

0 commit comments

Comments
 (0)