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 }