package main import ( "fmt" "github.com/tarm/serial" "log" "os" "path/filepath" "strings" "time" ) // read serial buffer func readUntilEmpty(p *serial.Port) { p.Flush() time.Sleep(100 * time.Millisecond) ignorebuf := make([]byte, 1024) p.Read(ignorebuf) } // returns last line of output func sendCommand(p *serial.Port, command string) string { fmt.Printf("%s\n", command) var first_line string = "" p.Flush() time.Sleep(500 * time.Millisecond) readUntilEmpty(p) _, err := p.Write([]byte(command + "\n")) if err != nil { log.Fatal(err) } buf := make([]byte, 1024) time.Sleep(500 * time.Millisecond) n, _ := p.Read(buf) if n > 0 { lines := strings.Split(string(buf[:n]), "\n") //fmt.Printf("%+q\n", lines) first_line = lines[0] } return first_line } func getDevEui(p *serial.Port) string { var reply = sendCommand(p, "AT+DADDR=?") //fmt.Printf("XXX%sYYY\n",reply) if len(reply) >= 10 { return "a8 40 41 00 " + reply[0:11] } else { return "" } } func getFWVersion(p *serial.Port) string { var reply = sendCommand(p, "AT+VER=?") //fmt.Printf("XXX%sYYY\n",reply) if len(reply) >= 10 { return reply } else { return "" } } func getAppKey(deveui string) string { if len(deveui) == 23 { mdeveui := strings.ReplaceAll(deveui, " ", "") appkey := fmt.Sprintf("%c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c", mdeveui[10], mdeveui[3], mdeveui[4], mdeveui[7], mdeveui[15], mdeveui[9], mdeveui[11], mdeveui[2], mdeveui[0], mdeveui[8], mdeveui[1], mdeveui[6], mdeveui[5], mdeveui[12], mdeveui[14], mdeveui[13], mdeveui[3], mdeveui[6], mdeveui[12], mdeveui[7], mdeveui[15], mdeveui[1], mdeveui[9], mdeveui[11], mdeveui[2], mdeveui[10], mdeveui[0], mdeveui[8], mdeveui[5], mdeveui[14], mdeveui[4], mdeveui[13]) fmt.Printf("calculated AppKey: %s\n", appkey) return appkey } else { fmt.Printf("devEui has wrong length: %s\n", deveui) return "" } } func readSerial(p *serial.Port) { p.Flush() buf := make([]byte, 32) time.Sleep(200 * time.Millisecond) n, _ := p.Read(buf) for n > 0 { // ignoring error as EOF raises error on Linux reply := string(buf[:n]) fmt.Printf("%s", reply) n, _ = p.Read(buf) } } func isValidTXP(txp string) bool { switch txp { case "0", "1", "2", "3", "4", "5", "-1": return true } return false } func main() { if len(os.Args) != 3 { fmt.Println("usage: " + filepath.Base(os.Args[0]) + " ") os.Exit(1) } serialdev := os.Args[1] txp := os.Args[2] if !(isValidTXP(txp)) { fmt.Println("invalid TXP, valid values are 0-5 and -1 (ADR)") os.Exit(2) } appEui := "a8 40 41 35 10 35 10 35" c := &serial.Config{Name: serialdev, Baud: 9600, ReadTimeout: time.Second * 1} s, err := serial.OpenPort(c) if err != nil { log.Fatal("Problem mit Serial Interface") } location, err := time.LoadLocation("Europe/Zurich") f, err := os.OpenFile("setup-node.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Println(err) } defer f.Close() sendCommand(s, "AT") sendCommand(s, "ATNJM=0") devEui := getDevEui(s) FWVersion := getFWVersion(s) if devEui != "" { fmt.Printf("devEui: %s\n", devEui) sendCommand(s, "AT+APPEUI="+appEui) appkey := getAppKey(devEui) sendCommand(s, "AT+APPKEY="+appkey) sendCommand(s, "AT+FDR") sendCommand(s, "AT+FDR") sendCommand(s, "AT+LON=0") sendCommand(s, "AT+NMEA353=4") if txp != "-1" { // we use no ADR sendCommand(s, "AT+ADR=0") sendCommand(s, "AT+TXP="+txp) } sendCommand(s, "ATNJM=1") sendCommand(s, "ATZ") logline := strings.ToUpper(fmt.Sprintf("%s: %s %s %s %s\n", time.Now().In(location).Format("02.01.2006 15:04"), strings.ReplaceAll(devEui, " ", ""), strings.ReplaceAll(appEui, " ", ""), strings.ReplaceAll(appkey, " ", ""), FWVersion)) if _, err := f.WriteString(logline); err != nil { log.Println(err) } readSerial(s) } else { log.Fatal("Could not get devEui") } }