tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/examples/lora/lorawan/atcmd/commands.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/hex"
     5  	"strings"
     6  
     7  	"tinygo.org/x/drivers/examples/lora/lorawan/common"
     8  	"tinygo.org/x/drivers/lora/lorawan"
     9  )
    10  
    11  // Use to test if connection to module is OK.
    12  func quicktest() {
    13  	writeCommandOutput("AT", "OK")
    14  }
    15  
    16  // Check firmware version.
    17  func version() {
    18  	writeCommandOutput("VER", common.CurrentVersion()+" ("+common.FirmwareVersion()+")")
    19  }
    20  
    21  // Use to check the ID of the LoRaWAN module, or change the ID.
    22  func id(args string) error {
    23  	cmd := "ID"
    24  
    25  	// look for comma in args
    26  	param, val, hasComma := strings.Cut(args, ",")
    27  	if hasComma {
    28  		// set
    29  		data := strings.Trim(val, "\"'")
    30  
    31  		// convert data from hex formatted string
    32  		data = strings.ReplaceAll(data, " ", "")
    33  		hexdata, err := hex.DecodeString(data)
    34  		if err != nil {
    35  			writeCommandOutput(cmd, err.Error())
    36  
    37  			return err
    38  		}
    39  
    40  		switch param {
    41  		case "DevAddr":
    42  			if err := session.SetDevAddr(hexdata); err != nil {
    43  				writeCommandOutput(cmd, err.Error())
    44  
    45  				return err
    46  			}
    47  
    48  			writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
    49  		case "DevEui":
    50  			if err := otaa.SetDevEUI(hexdata); err != nil {
    51  				writeCommandOutput(cmd, err.Error())
    52  
    53  				return err
    54  			}
    55  
    56  			writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
    57  		case "AppEui":
    58  			if err := otaa.SetAppEUI(hexdata); err != nil {
    59  				writeCommandOutput(cmd, err.Error())
    60  
    61  				return err
    62  			}
    63  
    64  			writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
    65  		default:
    66  			return errInvalidCommand
    67  		}
    68  
    69  		return nil
    70  	}
    71  
    72  	// get
    73  	switch param {
    74  	case "DevAddr":
    75  		writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
    76  	case "DevEui":
    77  		writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
    78  	case "AppEui":
    79  		writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
    80  	default:
    81  		writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
    82  		writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
    83  		writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
    84  	}
    85  
    86  	return nil
    87  }
    88  
    89  // Use to reset the module. If module returns error, then reset function is invalid.
    90  func reset() error {
    91  	radio.Reset()
    92  
    93  	writeCommandOutput("RESET", "OK")
    94  	return nil
    95  }
    96  
    97  // Use to send string format frame which is no need to be confirmed by the server.
    98  func msg(data string) error {
    99  	cmd := "MSG"
   100  	writeCommandOutput(cmd, "Start")
   101  
   102  	if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
   103  		writeCommandOutput(cmd, err.Error())
   104  
   105  		return err
   106  	}
   107  
   108  	writeCommandOutput(cmd, "Done")
   109  	return nil
   110  }
   111  
   112  // Use to send string format frame which must be confirmed by the server
   113  func cmsg(data string) error {
   114  	cmd := "CMSG"
   115  	writeCommandOutput(cmd, "Start")
   116  
   117  	if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
   118  		writeCommandOutput(cmd, err.Error())
   119  
   120  		return err
   121  	}
   122  
   123  	// TODO: confirmation
   124  
   125  	writeCommandOutput(cmd, "Done")
   126  	return nil
   127  }
   128  
   129  // Use to send hex format frame which is no need to be confirmed by the server
   130  func msghex(data string) error {
   131  	cmd := "MSGHEX"
   132  	writeCommandOutput(cmd, "Start")
   133  
   134  	writeCommandOutput(cmd, "Done")
   135  	return nil
   136  }
   137  
   138  // Use to send hex format frame which must be confirmed by the server.
   139  func cmsghex(data string) error {
   140  	cmd := "CMSGHEX"
   141  	writeCommandOutput(cmd, "Start")
   142  
   143  	writeCommandOutput(cmd, "Done")
   144  	return nil
   145  }
   146  
   147  // Use to send string format LoRaWAN proprietary frames
   148  func pmsg(data string) error {
   149  	cmd := "PMSG"
   150  	writeCommandOutput(cmd, "Start")
   151  
   152  	writeCommandOutput(cmd, "Done")
   153  	return nil
   154  }
   155  
   156  // Use to send hex format LoRaWAN proprietary frames.
   157  func pmsghex(data string) error {
   158  	cmd := "PMSGHEX"
   159  	writeCommandOutput(cmd, "Start")
   160  
   161  	writeCommandOutput(cmd, "Done")
   162  
   163  	return nil
   164  }
   165  
   166  // Set PORT number which will be used by MSG/CMSG/MSGHEX/CMSGHEX command to send
   167  // message, port number should range from 1 to 255. User should refer to LoRaWAN
   168  // specification to choose port.
   169  func port(p string) error {
   170  	cmd := "PMSG"
   171  	writeCommandOutput(cmd, p)
   172  
   173  	return nil
   174  }
   175  
   176  // Set ADR function of LoRaWAN module
   177  func adr(state string) error {
   178  	cmd := "ADR"
   179  	writeCommandOutput(cmd, state)
   180  
   181  	return nil
   182  }
   183  
   184  // Use LoRaWAN defined DRx to set datarate of LoRaWAN AT modem.
   185  func dr(rate string) error {
   186  	cmd := "DR"
   187  	writeCommandOutput(cmd, rate)
   188  
   189  	return nil
   190  }
   191  
   192  // Channel Configuration
   193  func ch(channel string) error {
   194  	cmd := "CH"
   195  	writeCommandOutput(cmd, channel)
   196  
   197  	return nil
   198  }
   199  
   200  // Set and Check Power
   201  func power(setting string) error {
   202  	cmd := "POWER"
   203  	writeCommandOutput(cmd, setting)
   204  
   205  	return nil
   206  }
   207  
   208  // Unconfirmed message repeats times.
   209  func rept(setting string) error {
   210  	cmd := "REPT"
   211  	writeCommandOutput(cmd, setting)
   212  
   213  	return nil
   214  }
   215  
   216  // Confirmed message retry times. Valid range 0~254,
   217  // if retry times is less than 2, only one message will
   218  // be sent. Random delay 3 - 10s between each retry
   219  // (band duty cycle limitation has the priority)
   220  func retry(setting string) error {
   221  	cmd := "RETRY"
   222  	writeCommandOutput(cmd, setting)
   223  
   224  	return nil
   225  }
   226  
   227  func rxwin2(setting string) error {
   228  	cmd := "RXWIN2"
   229  	writeCommandOutput(cmd, setting)
   230  
   231  	return nil
   232  }
   233  
   234  func rxwin1(setting string) error {
   235  	cmd := "RXWIN1"
   236  	writeCommandOutput(cmd, setting)
   237  
   238  	return nil
   239  }
   240  
   241  func key(setting string) error {
   242  	cmd := "KEY"
   243  
   244  	// look for comma in args
   245  	param, val, hasComma := strings.Cut(setting, ",")
   246  	if hasComma {
   247  		// set
   248  		data := strings.Trim(val, "\"'")
   249  
   250  		// convert data from hex formatted string
   251  		data = strings.ReplaceAll(data, " ", "")
   252  		hexdata, err := hex.DecodeString(data)
   253  		if err != nil {
   254  			writeCommandOutput(cmd, err.Error())
   255  
   256  			return err
   257  		}
   258  
   259  		switch param {
   260  		case "APPKEY":
   261  			if err := otaa.SetAppKey(hexdata); err != nil {
   262  				writeCommandOutput(cmd, err.Error())
   263  
   264  				return err
   265  			}
   266  
   267  			writeCommandOutput(cmd, "APPKEY, "+otaa.GetAppKey())
   268  		default:
   269  			return errInvalidCommand
   270  		}
   271  	}
   272  
   273  	// cannot get keys
   274  	return errInvalidCommand
   275  }
   276  
   277  func fdefault(setting string) error {
   278  	cmd := "FDEFAULT"
   279  	writeCommandOutput(cmd, "OK")
   280  
   281  	return nil
   282  }
   283  
   284  func mode(setting string) error {
   285  	cmd := "MODE"
   286  	writeCommandOutput(cmd, setting)
   287  
   288  	return nil
   289  }
   290  
   291  func join(setting string) error {
   292  	// TODO: check that DevEUI, AppEUI, and AppKey have values
   293  
   294  	cmd := "JOIN"
   295  	writeCommandOutput(cmd, "Starting")
   296  	if err := lorawan.Join(otaa, session); err != nil {
   297  		writeCommandOutput(cmd, err.Error())
   298  
   299  		return err
   300  	}
   301  
   302  	writeCommandOutput(cmd, "Network joined")
   303  	writeCommandOutput(cmd, "DevEui, "+otaa.GetDevEUI())
   304  	writeCommandOutput(cmd, "AppEui, "+otaa.GetAppEUI())
   305  	writeCommandOutput(cmd, "DevAddr, "+session.GetDevAddr())
   306  	writeCommandOutput(cmd, "NetID, "+otaa.GetNetID())
   307  	writeCommandOutput(cmd, "NwkSKey, "+session.GetNwkSKey())
   308  	writeCommandOutput(cmd, "AppSKey, "+session.GetAppSKey())
   309  	writeCommandOutput(cmd, "Done")
   310  	return nil
   311  }
   312  
   313  func beacon(setting string) error {
   314  	cmd := "BEACON"
   315  	writeCommandOutput(cmd, "Starting")
   316  
   317  	writeCommandOutput(cmd, "Done")
   318  
   319  	return nil
   320  }
   321  
   322  func class(setting string) error {
   323  	cmd := "CLASS"
   324  	writeCommandOutput(cmd, "Starting")
   325  
   326  	writeCommandOutput(cmd, "Done")
   327  
   328  	return nil
   329  }
   330  
   331  func delay(setting string) error {
   332  	cmd := "DELAY"
   333  	writeCommandOutput(cmd, setting)
   334  
   335  	return nil
   336  }
   337  
   338  func lw(setting string) error {
   339  	cmd := "LW"
   340  
   341  	param, val, hasComma := strings.Cut(setting, ",")
   342  	if hasComma {
   343  		if param == "NET" {
   344  			if val == "ON" {
   345  				lorawan.SetPublicNetwork(true)
   346  			} else {
   347  				lorawan.SetPublicNetwork(false)
   348  			}
   349  		}
   350  	}
   351  	writeCommandOutput(cmd, setting)
   352  
   353  	return nil
   354  }
   355  
   356  func wdt(setting string) error {
   357  	cmd := "WDT"
   358  	writeCommandOutput(cmd, "Not implemented")
   359  
   360  	return nil
   361  }
   362  
   363  func lowpower(setting string) error {
   364  	cmd := "LOWPOWER"
   365  	writeCommandOutput(cmd, "Not implemented")
   366  
   367  	return nil
   368  }
   369  
   370  func vdd(setting string) error {
   371  	cmd := "VDD"
   372  	writeCommandOutput(cmd, "Not implemented")
   373  
   374  	return nil
   375  }
   376  
   377  func temp(setting string) error {
   378  	cmd := "TEMP"
   379  	writeCommandOutput(cmd, "Not implemented")
   380  
   381  	return nil
   382  }
   383  
   384  func rtc(setting string) error {
   385  	cmd := "RTC"
   386  	writeCommandOutput(cmd, "Not implemented")
   387  
   388  	return nil
   389  }
   390  
   391  func eeprom(setting string) error {
   392  	cmd := "EEPROM"
   393  	writeCommandOutput(cmd, "Not implemented")
   394  
   395  	return nil
   396  }
   397  
   398  func uartcmd(setting string) error {
   399  	cmd := "UART"
   400  	writeCommandOutput(cmd, "Not implemented")
   401  
   402  	return nil
   403  }
   404  
   405  func test(setting string) error {
   406  	cmd := "TEST"
   407  	writeCommandOutput(cmd, "Not implemented")
   408  
   409  	return nil
   410  }
   411  
   412  func log(setting string) error {
   413  	cmd := "LOG"
   414  	writeCommandOutput(cmd, "Not implemented")
   415  
   416  	return nil
   417  }
   418  
   419  func send(data string) error {
   420  	cmd := "SEND"
   421  	writeCommandOutput(cmd, "Start")
   422  
   423  	// remove leading/trailing quotes
   424  	data = strings.Trim(data, "\"'")
   425  
   426  	if err := radio.Tx([]byte(data), defaultTimeout); err != nil {
   427  		writeCommandOutput(cmd, err.Error())
   428  
   429  		return err
   430  	}
   431  
   432  	writeCommandOutput(cmd, "Done")
   433  	return nil
   434  }
   435  
   436  func sendhex(data string) error {
   437  	cmd := "SENDHEX"
   438  	writeCommandOutput(cmd, "Start")
   439  
   440  	// remove leading/trailing quotes
   441  	data = strings.Trim(data, "\"'")
   442  
   443  	// convert data from hex formatted string
   444  	data = strings.ReplaceAll(data, " ", "")
   445  	payload, err := hex.DecodeString(data)
   446  	if err != nil {
   447  		writeCommandOutput(cmd, err.Error())
   448  
   449  		return err
   450  	}
   451  
   452  	if err := radio.Tx(payload, defaultTimeout); err != nil {
   453  		writeCommandOutput(cmd, err.Error())
   454  
   455  		return err
   456  	}
   457  
   458  	writeCommandOutput(cmd, "Done")
   459  	return nil
   460  }
   461  
   462  func recv(setting string) error {
   463  	cmd := "RECV"
   464  
   465  	data, err := common.Lorarx()
   466  	if err != nil {
   467  		writeCommandOutput(cmd, "ERROR "+err.Error())
   468  		return err
   469  	}
   470  	writeCommandOutput(cmd, string(data))
   471  
   472  	return nil
   473  }
   474  
   475  func recvhex(setting string) error {
   476  	cmd := "RECVHEX"
   477  
   478  	data, err := common.Lorarx()
   479  	if err != nil {
   480  		writeCommandOutput(cmd, "ERROR "+err.Error())
   481  		return err
   482  	}
   483  	writeCommandOutput(cmd, string(data))
   484  
   485  	return nil
   486  }
   487  
   488  func crlf() {
   489  	uart.Write([]byte("\r\n"))
   490  }
   491  
   492  func writeCommandOutput(cmd, data string) {
   493  	uart.Write([]byte("+" + cmd + ": "))
   494  	uart.Write([]byte(data))
   495  	crlf()
   496  }