// Send data to the serial sending device, this function takes care // of the binary encoding of the passed data. // The data should be in format FF FF FF FF func sendDataToSniffer(data string) { // Initialize the sender port var err error senderPort, err := serial.Open(*sniffingTTY) if err != nil { log.Fatal("Error: " + err.Error()) } if err != nil { log.Fatal(err) } strippedData := strings.Split(data, " ") var checkSum uint64 hexLiteral := []byte{} for index := range strippedData { actualByte, _ := strconv.ParseUint(strippedData[index], 16, 10) hexLiteral = append(hexLiteral, byte(actualByte)) checkSum = checkSum ^ actualByte } // Append checksum hexLiteral = append(hexLiteral, byte(checkSum)) senderPort.Write(hexLiteral) senderPort.Close() time.Sleep(time.Millisecond * 100) }
// Open connection to the device. // name - path to the device file (eg: /dev/ttyUSB0) func Open(name string) (*Avt414, error) { s, err := serial.Open(name) if err != nil { return nil, err } if err = s.SetSpeed(57600); err != nil { return nil, err } return &Avt414{s}, nil }
// Open opens an AVT414 device. // name - path to the device file (eg: /dev/ttyUSB0) func Open(name string) (*AVT414, error) { s, err := serial.Open(name) if err != nil { return nil, err } if err = s.SetSpeed(57600); err != nil { return nil, err } a := AVT414{s: s} a.lastA = 0xff a.cmd[0] = esc return &a, nil }
// Reads continous the data from the connected serial device func readData() { s, err := serial.Open(*sniffingTTY) if err != nil { log.Fatal("Error: " + err.Error()) } snifferActive = true var buf []byte // Reset the device sendDataToSniffer("FF 05 00") for { newData := make([]byte, 1000000) n, err := s.Read(newData) if n > 0 { // Sprintf is used here to prevent interpreting the bytes (e.g. 0x13 as newline character) buf = append(buf, fmt.Sprintf("%s", hex.EncodeToString(newData[:n]))...) if err != nil { log.Fatal(err) } if bytes.Count(buf, []byte("ff03")) > 0 && snifferActive { frames := strings.Split(fmt.Sprintf("%s", buf), "ff03") for i := range frames { // Only proceed if we received the length byte as we will only read until there if len(frames[i]) > 2 { decodedString, err := hex.DecodeString(fmt.Sprintf("%s", frames[i][:2])) if err == nil { // The sniffer appends +1 to the length byte, therefore we have to decrement the value lengthByte, err := strconv.Atoi(fmt.Sprintf("%d", decodedString[0])) if err == nil { lengthByte = lengthByte - 1 newLength := fmt.Sprintf("%#x", lengthByte) // Only read if the length is correct if len(frames[i]) >= (lengthByte*2)+2 && lengthByte > 10 { frame, _ := mbus.NewFrame(fmt.Sprintf("%s", strings.ToUpper(newLength[2:]+frames[i][2:(lengthByte*2)+2]))) // HACK: Only sniff encrypted frames if frame.Configuration() != "0000" && frame.Configuration() != "" { go addFrameToDB(frame) } buf = []byte(strings.Join(frames[i+1:], "")) } } } } } // Just drop everything if the sniffer is not active if !snifferActive { buf = []byte("") } } } } }
func main() { button := make(chan byte, 16) msg := make(chan string, 16) eof := make(chan error, 0) eofSeen := false buf := make([]string, scrollback) pos := 0 var nlines float64 = 0 var str string var btn byte disp, err := ssd1306.New(gpio.P8[3], ssd1306.IFACE_I2C, 0x3c, 1, 128, 64) defer disp.Close() if err != nil { log.Fatal(err) } disp.Setup() var s *serial.Serial s, err = serial.Open(os.Args[len(os.Args)-1]) if err != nil { log.Fatal(err) } defer s.Close() s.SetSpeed(115200) s.SetCanon(true) // cts := make(chan bool) go ButtonGet(button) go ReadInput(os.Stdin, msg, s, eof) for !eofSeen { disp.Clear(color.Black) for i := 0; i < 8; i++ { disp.String(0, 63-8*i, color.White, buf[pos+i]) } disp.Rectangle(126, int(64-64*(float64(pos)+8)/math.Max(nlines, 8)), 127, int(63-64*float64(pos)/math.Max(nlines, 8)), color.White) disp.Draw() select { case str = <-msg: for long := true; long; { for i := int(nlines); i >= 1; i-- { buf[i] = buf[i-1] } str = strings.TrimSpace(str) buf[0] = str[:int(math.Min(float64(len(str)), 21))] if nlines < scrollback { nlines++ } if len(str) <= 21 { long = false } else { str = str[21:] } } case btn = <-button: switch btn { case 1: if pos < int(nlines)-8 { pos++ } case 2: if pos > 0 { pos-- } } case <-eof: eofSeen = true } } }