tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/lora/lorawan/adaptor.go (about) 1 package lorawan 2 3 import ( 4 "errors" 5 6 "tinygo.org/x/drivers/lora" 7 "tinygo.org/x/drivers/lora/lorawan/region" 8 ) 9 10 var ( 11 ErrNoJoinAcceptReceived = errors.New("no JoinAccept packet received") 12 ErrNoRadioAttached = errors.New("no LoRa radio attached") 13 ErrInvalidEuiLength = errors.New("invalid EUI length") 14 ErrInvalidAppKeyLength = errors.New("invalid AppKey length") 15 ErrInvalidPacketLength = errors.New("invalid packet length") 16 ErrInvalidDevAddrLength = errors.New("invalid DevAddr length") 17 ErrInvalidMic = errors.New("invalid Mic") 18 ErrFrmPayloadTooLarge = errors.New("FRM payload too large") 19 ErrInvalidNetIDLength = errors.New("invalid NetID length") 20 ErrInvalidNwkSKeyLength = errors.New("invalid NwkSKey length") 21 ErrInvalidAppSKeyLength = errors.New("invalid AppSKey length") 22 ErrUndefinedRegionSettings = errors.New("undefined Regionnal Settings ") 23 ) 24 25 const ( 26 LORA_TX_TIMEOUT = 2000 27 LORA_RX_TIMEOUT = 10000 28 ) 29 30 var ( 31 ActiveRadio lora.Radio 32 Retries = 15 33 regionSettings region.Settings 34 ) 35 36 // UseRegionSettings sets current Lorawan Regional parameters 37 func UseRegionSettings(rs region.Settings) { 38 regionSettings = rs 39 } 40 41 // UseRadio attaches Lora radio driver to Lorawan 42 func UseRadio(r lora.Radio) { 43 if ActiveRadio != nil { 44 panic("lorawan.ActiveRadio is already set") 45 } 46 ActiveRadio = r 47 } 48 49 // SetPublicNetwork defines Lora Sync Word according to network type (public/private) 50 func SetPublicNetwork(enabled bool) { 51 ActiveRadio.SetPublicNetwork(enabled) 52 } 53 54 // ApplyChannelConfig sets current Lora modulation according to current regional settings 55 func applyChannelConfig(ch region.Channel) { 56 ActiveRadio.SetFrequency(ch.Frequency()) 57 ActiveRadio.SetBandwidth(ch.Bandwidth()) 58 ActiveRadio.SetCodingRate(ch.CodingRate()) 59 ActiveRadio.SetSpreadingFactor(ch.SpreadingFactor()) 60 ActiveRadio.SetPreambleLength(ch.PreambleLength()) 61 ActiveRadio.SetTxPower(ch.TxPowerDBm()) 62 // Lorawan defaults to explicit headers 63 ActiveRadio.SetHeaderType(lora.HeaderExplicit) 64 ActiveRadio.SetCrc(true) 65 } 66 67 // Join tries to connect Lorawan Gateway 68 func Join(otaa *Otaa, session *Session) error { 69 var resp []uint8 70 71 if ActiveRadio == nil { 72 return ErrNoRadioAttached 73 } 74 75 if regionSettings == nil { 76 return ErrUndefinedRegionSettings 77 } 78 79 otaa.Init() 80 81 // Send join packet 82 payload, err := otaa.GenerateJoinRequest() 83 if err != nil { 84 return err 85 } 86 87 for { 88 joinRequestChannel := regionSettings.JoinRequestChannel() 89 joinAcceptChannel := regionSettings.JoinAcceptChannel() 90 91 // Prepare radio for Join Tx 92 applyChannelConfig(joinRequestChannel) 93 ActiveRadio.SetIqMode(lora.IQStandard) 94 ActiveRadio.Tx(payload, LORA_TX_TIMEOUT) 95 if err != nil { 96 return err 97 } 98 99 // Wait for JoinAccept 100 if joinAcceptChannel.Frequency() != 0 { 101 applyChannelConfig(joinAcceptChannel) 102 } 103 ActiveRadio.SetIqMode(lora.IQInverted) 104 resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT) 105 if err == nil && resp != nil { 106 break 107 } 108 if !joinAcceptChannel.Next() { 109 return ErrNoJoinAcceptReceived 110 } 111 } 112 113 err = otaa.DecodeJoinAccept(resp, session) 114 if err != nil { 115 return err 116 } 117 118 return nil 119 } 120 121 // SendUplink sends Lorawan Uplink message 122 func SendUplink(data []uint8, session *Session) error { 123 124 if regionSettings == nil { 125 return ErrUndefinedRegionSettings 126 } 127 128 payload, err := session.GenMessage(0, []byte(data)) 129 if err != nil { 130 return err 131 } 132 133 applyChannelConfig(regionSettings.UplinkChannel()) 134 ActiveRadio.SetIqMode(lora.IQStandard) 135 ActiveRadio.Tx(payload, LORA_TX_TIMEOUT) 136 if err != nil { 137 return err 138 } 139 return nil 140 } 141 142 func ListenDownlink() error { 143 return nil 144 }