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  }