mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-18 21:53:56 +00:00
lorawan: Basic implementation of Lorawan Regional Settings and EU868/AU915 regions
This commit is contained in:
committed by
Ron Evans
parent
e6cde8f7ae
commit
78cc1afe46
@@ -15,6 +15,7 @@ import (
|
|||||||
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
||||||
"tinygo.org/x/drivers/lora"
|
"tinygo.org/x/drivers/lora"
|
||||||
"tinygo.org/x/drivers/lora/lorawan"
|
"tinygo.org/x/drivers/lora/lorawan"
|
||||||
|
"tinygo.org/x/drivers/lora/lorawan/region"
|
||||||
)
|
)
|
||||||
|
|
||||||
// change these to test a different UART or pins if available
|
// change these to test a different UART or pins if available
|
||||||
@@ -44,6 +45,8 @@ func main() {
|
|||||||
otaa = &lorawan.Otaa{}
|
otaa = &lorawan.Otaa{}
|
||||||
lorawan.UseRadio(radio)
|
lorawan.UseRadio(radio)
|
||||||
|
|
||||||
|
lorawan.UseRegionSettings(region.EU868())
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if uart.Buffered() > 0 {
|
if uart.Buffered() > 0 {
|
||||||
data, _ := uart.ReadByte()
|
data, _ := uart.ReadByte()
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ import (
|
|||||||
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
||||||
"tinygo.org/x/drivers/lora"
|
"tinygo.org/x/drivers/lora"
|
||||||
"tinygo.org/x/drivers/lora/lorawan"
|
"tinygo.org/x/drivers/lora/lorawan"
|
||||||
|
"tinygo.org/x/drivers/lora/lorawan/region"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
debug = true
|
||||||
LORAWAN_JOIN_TIMEOUT_SEC = 180
|
LORAWAN_JOIN_TIMEOUT_SEC = 180
|
||||||
LORAWAN_RECONNECT_DELAY_SEC = 15
|
LORAWAN_RECONNECT_DELAY_SEC = 15
|
||||||
LORAWAN_UPLINK_DELAY_SEC = 60
|
LORAWAN_UPLINK_DELAY_SEC = 60
|
||||||
@@ -81,14 +83,29 @@ func main() {
|
|||||||
// Connect the lorawan with the Lora Radio device.
|
// Connect the lorawan with the Lora Radio device.
|
||||||
lorawan.UseRadio(radio)
|
lorawan.UseRadio(radio)
|
||||||
|
|
||||||
|
lorawan.UseRegionSettings(region.EU868())
|
||||||
|
|
||||||
// Configure AppEUI, DevEUI, APPKey
|
// Configure AppEUI, DevEUI, APPKey
|
||||||
setLorawanKeys()
|
setLorawanKeys()
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
println("main: Network joined")
|
||||||
|
println("main: DevEui, " + otaa.GetDevEUI())
|
||||||
|
println("main: AppEui, " + otaa.GetAppEUI())
|
||||||
|
println("main: DevAddr, " + session.GetDevAddr())
|
||||||
|
}
|
||||||
|
|
||||||
// Try to connect Lorawan network
|
// Try to connect Lorawan network
|
||||||
if err := loraConnect(); err != nil {
|
if err := loraConnect(); err != nil {
|
||||||
failMessage(err)
|
failMessage(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
println("main: NetID, " + otaa.GetNetID())
|
||||||
|
println("main: NwkSKey, " + session.GetNwkSKey())
|
||||||
|
println("main: AppSKey, " + session.GetAppSKey())
|
||||||
|
println("main: Done")
|
||||||
|
}
|
||||||
// Try to periodicaly send an uplink sample message
|
// Try to periodicaly send an uplink sample message
|
||||||
upCount := 1
|
upCount := 1
|
||||||
for {
|
for {
|
||||||
|
|||||||
+46
-13
@@ -4,20 +4,22 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"tinygo.org/x/drivers/lora"
|
"tinygo.org/x/drivers/lora"
|
||||||
|
"tinygo.org/x/drivers/lora/lorawan/region"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoJoinAcceptReceived = errors.New("no JoinAccept packet received")
|
ErrNoJoinAcceptReceived = errors.New("no JoinAccept packet received")
|
||||||
ErrNoRadioAttached = errors.New("no LoRa radio attached")
|
ErrNoRadioAttached = errors.New("no LoRa radio attached")
|
||||||
ErrInvalidEuiLength = errors.New("invalid EUI length")
|
ErrInvalidEuiLength = errors.New("invalid EUI length")
|
||||||
ErrInvalidAppKeyLength = errors.New("invalid AppKey length")
|
ErrInvalidAppKeyLength = errors.New("invalid AppKey length")
|
||||||
ErrInvalidPacketLength = errors.New("invalid packet length")
|
ErrInvalidPacketLength = errors.New("invalid packet length")
|
||||||
ErrInvalidDevAddrLength = errors.New("invalid DevAddr length")
|
ErrInvalidDevAddrLength = errors.New("invalid DevAddr length")
|
||||||
ErrInvalidMic = errors.New("invalid Mic")
|
ErrInvalidMic = errors.New("invalid Mic")
|
||||||
ErrFrmPayloadTooLarge = errors.New("FRM payload too large")
|
ErrFrmPayloadTooLarge = errors.New("FRM payload too large")
|
||||||
ErrInvalidNetIDLength = errors.New("invalid NetID length")
|
ErrInvalidNetIDLength = errors.New("invalid NetID length")
|
||||||
ErrInvalidNwkSKeyLength = errors.New("invalid NwkSKey length")
|
ErrInvalidNwkSKeyLength = errors.New("invalid NwkSKey length")
|
||||||
ErrInvalidAppSKeyLength = errors.New("invalid AppSKey length")
|
ErrInvalidAppSKeyLength = errors.New("invalid AppSKey length")
|
||||||
|
ErrUndefinedRegionSettings = errors.New("undefined Regionnal Settings ")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -26,10 +28,15 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ActiveRadio lora.Radio
|
ActiveRadio lora.Radio
|
||||||
Retries = 15
|
Retries = 15
|
||||||
|
regionSettings region.RegionSettings
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func UseRegionSettings(rs region.RegionSettings) {
|
||||||
|
regionSettings = rs
|
||||||
|
}
|
||||||
|
|
||||||
func UseRadio(r lora.Radio) {
|
func UseRadio(r lora.Radio) {
|
||||||
if ActiveRadio != nil {
|
if ActiveRadio != nil {
|
||||||
panic("lorawan.ActiveRadio is already set")
|
panic("lorawan.ActiveRadio is already set")
|
||||||
@@ -44,6 +51,10 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
return ErrNoRadioAttached
|
return ErrNoRadioAttached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if regionSettings == nil {
|
||||||
|
return ErrUndefinedRegionSettings
|
||||||
|
}
|
||||||
|
|
||||||
otaa.Init()
|
otaa.Init()
|
||||||
|
|
||||||
// Send join packet
|
// Send join packet
|
||||||
@@ -52,6 +63,12 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare radio for Join Tx
|
||||||
|
joinChannel := regionSettings.GetJoinRequestChannel()
|
||||||
|
ActiveRadio.SetFrequency(joinChannel.Frequency)
|
||||||
|
ActiveRadio.SetBandwidth(joinChannel.Bandwidth)
|
||||||
|
ActiveRadio.SetCodingRate(joinChannel.CodingRate)
|
||||||
|
ActiveRadio.SetSpreadingFactor(joinChannel.SpreadingFactor)
|
||||||
ActiveRadio.SetCrc(true)
|
ActiveRadio.SetCrc(true)
|
||||||
ActiveRadio.SetIqMode(0) // IQ Standard
|
ActiveRadio.SetIqMode(0) // IQ Standard
|
||||||
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
||||||
@@ -60,6 +77,11 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for JoinAccept
|
// Wait for JoinAccept
|
||||||
|
joinChannel = regionSettings.GetJoinAcceptChannel()
|
||||||
|
ActiveRadio.SetFrequency(joinChannel.Frequency)
|
||||||
|
ActiveRadio.SetBandwidth(joinChannel.Bandwidth)
|
||||||
|
ActiveRadio.SetCodingRate(joinChannel.CodingRate)
|
||||||
|
ActiveRadio.SetSpreadingFactor(joinChannel.SpreadingFactor)
|
||||||
ActiveRadio.SetIqMode(1) // IQ Inverted
|
ActiveRadio.SetIqMode(1) // IQ Inverted
|
||||||
for i := 0; i < Retries; i++ {
|
for i := 0; i < Retries; i++ {
|
||||||
resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT)
|
resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT)
|
||||||
@@ -83,10 +105,21 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendUplink(data []uint8, session *Session) error {
|
func SendUplink(data []uint8, session *Session) error {
|
||||||
|
|
||||||
|
if regionSettings == nil {
|
||||||
|
return ErrUndefinedRegionSettings
|
||||||
|
}
|
||||||
|
|
||||||
payload, err := session.GenMessage(0, []byte(data))
|
payload, err := session.GenMessage(0, []byte(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
joinChannel := regionSettings.GetUplinkChannel()
|
||||||
|
ActiveRadio.SetFrequency(joinChannel.Frequency)
|
||||||
|
ActiveRadio.SetBandwidth(joinChannel.Bandwidth)
|
||||||
|
ActiveRadio.SetCodingRate(joinChannel.CodingRate)
|
||||||
|
ActiveRadio.SetSpreadingFactor(joinChannel.SpreadingFactor)
|
||||||
ActiveRadio.SetCrc(true)
|
ActiveRadio.SetCrc(true)
|
||||||
ActiveRadio.SetIqMode(0) // IQ Standard
|
ActiveRadio.SetIqMode(0) // IQ Standard
|
||||||
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ type Otaa struct {
|
|||||||
// Initialize DevNonce
|
// Initialize DevNonce
|
||||||
func (o *Otaa) Init() {
|
func (o *Otaa) Init() {
|
||||||
o.buf = make([]uint8, 0)
|
o.buf = make([]uint8, 0)
|
||||||
|
|
||||||
o.generateDevNonce()
|
o.generateDevNonce()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package region
|
||||||
|
|
||||||
|
import "tinygo.org/x/drivers/lora"
|
||||||
|
|
||||||
|
type RegionSettingsAU915 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func AU915() *RegionSettingsAU915 {
|
||||||
|
return &RegionSettingsAU915{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RegionSettingsAU915) GetJoinRequestChannel() Channel {
|
||||||
|
return Channel{916800000, lora.Bandwidth_125_0, lora.SpreadingFactor9, lora.CodingRate4_5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RegionSettingsAU915) GetJoinAcceptChannel() Channel {
|
||||||
|
return Channel{923300000, lora.Bandwidth_500_0, lora.SpreadingFactor9, lora.CodingRate4_5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RegionSettingsAU915) GetUplinkChannel() Channel {
|
||||||
|
return Channel{868500000, lora.Bandwidth_125_0, lora.SpreadingFactor9, lora.CodingRate4_5}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package region
|
||||||
|
|
||||||
|
import "tinygo.org/x/drivers/lora"
|
||||||
|
|
||||||
|
type RegionSettingsEU868 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func EU868() *RegionSettingsEU868 {
|
||||||
|
return &RegionSettingsEU868{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RegionSettingsEU868) GetJoinRequestChannel() Channel {
|
||||||
|
return Channel{868100000, lora.Bandwidth_125_0, lora.SpreadingFactor9, lora.CodingRate4_7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RegionSettingsEU868) GetJoinAcceptChannel() Channel {
|
||||||
|
return Channel{868100000, lora.Bandwidth_125_0, lora.SpreadingFactor9, lora.CodingRate4_7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RegionSettingsEU868) GetUplinkChannel() Channel {
|
||||||
|
return Channel{868100000, lora.Bandwidth_125_0, lora.SpreadingFactor9, lora.CodingRate4_7}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package region
|
||||||
|
|
||||||
|
type Channel struct {
|
||||||
|
Frequency uint32
|
||||||
|
Bandwidth uint8
|
||||||
|
SpreadingFactor uint8
|
||||||
|
CodingRate uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegionSettings interface {
|
||||||
|
GetJoinRequestChannel() Channel
|
||||||
|
GetJoinAcceptChannel() Channel
|
||||||
|
GetUplinkChannel() Channel
|
||||||
|
}
|
||||||
@@ -640,6 +640,7 @@ func (d *Device) Rx(timeoutMs uint32) ([]uint8, error) {
|
|||||||
irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR)
|
irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR)
|
||||||
d.SetStandby()
|
d.SetStandby()
|
||||||
d.SetBufferBaseAddress(0, 0)
|
d.SetBufferBaseAddress(0, 0)
|
||||||
|
d.SetRfFrequency(d.loraConf.Freq)
|
||||||
d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr)
|
d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr)
|
||||||
d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, 0xFF, d.loraConf.Iq)
|
d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, 0xFF, d.loraConf.Iq)
|
||||||
d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE)
|
d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE)
|
||||||
|
|||||||
Reference in New Issue
Block a user