func (w *WeatherStation) getDataWithCRC16(numBytes int64, prompt string) ([]byte, error) { var err error buf := new(bytes.Buffer) if prompt != "" { // We'll write to a Buffer and then dump it to the device _, err = buf.WriteString(prompt) if err != nil { return nil, err } // Write the buffer to the device _, err = buf.WriteTo(w.RW) if err != nil { return nil, err } w.RW.Flush() } // We're going to try reading data from the device maxTries times... for i := 1; i <= maxTries; i++ { // If it's not our first attempt at reading from the console, we send a RESEND command // to goad the console into responding. if i > 1 { _, err = buf.Write([]byte(RESEND)) if err != nil { log.Println("Could not write RESEND command to buffer") return nil, err } // Write the buffer to the console _, err = buf.WriteTo(w.RW) if err != nil { log.Println("Could not write buffer to console") return nil, err } checkBytes := make([]byte, numBytes) _, err := w.RW.Read(checkBytes) if err != nil { return nil, err } // Do a CRC16 check on data we read and return data if it passes if crc16.Crc16(checkBytes) == uint16(0) { return checkBytes, nil } // We didn't pass the CRC check so we loop again. log.Println("The data read did not pass the CRC16 check") } } // We failed at reading data from the console return nil, fmt.Errorf("Failed to read any data from the console after %v attempts.", maxTries) }
func (w *WeatherStation) sendDataWithCRC16(d []byte) error { var resp []byte // We'll write to a Buffer and then dump the buffer to the device buf := new(bytes.Buffer) check := crc16.Crc16(d) // First, write the data _, err := buf.Write(d) if err != nil { return err } // Next, write the CRC in big-endian order err = binary.Write(buf, binary.BigEndian, check) if err != nil { return err } for i := 0; i <= maxTries; i++ { _, err := buf.WriteTo(w.RW) if err != nil { return err } _, err = w.RW.Read(resp) if err != nil { log.Println("Error reading response:", err) return err } if resp[0] != ACK[0] { log.Println("No <ACK> was received from console") return nil } } return fmt.Errorf("I/O error writing data with CRC to device.") }
// GetDavisLoopPackets attempts to initiate a LOOP command against the station and retrieve some packets func (w *WeatherStation) GetDavisLoopPackets(n int, packetChan chan<- Reading) error { // Make a slice of loop packet maps, n elements long. //var loopPackets []*LoopPacketWithTrend log.Println("Initiating LOOP mode for", n, "packets.") // Request n packets w.sendData([]byte(fmt.Sprintf("LOOP %v\n", n))) w.RW.Flush() time.Sleep(1 * time.Second) tries := 1 for l := 0; l < n; l++ { time.Sleep(1 * time.Second) if tries > maxTries { log.Println("Max retries exeeded while getting loop data") return nil } err := w.C.SetReadDeadline(time.Now().Add(5 * time.Second)) if err != nil { log.Println("Error setting read deadline:", err) } // Read 99 bytes from the console buf := make([]byte, 99) _, err = w.RW.Read(buf) //_, err = io.ReadAtLeast(w.C, buf, 99) if err != nil { tries++ log.Printf("Error while reading from console, LOOP %v: %v", l, err) return nil } if buf[95] != 0x0A && buf[96] != 0x0D { log.Println("End-of-packet signature not found; rejecting.") } else { if crc16.Crc16(buf) != 0 { log.Printf("LOOP %v CRC error. Try #%v", l, tries) tries++ continue } unpacked, err := w.unpackLoopPacket(buf) if err != nil { tries++ log.Printf("Error unpacking loop packet: %v. Try %v", err, tries) continue } tries = 1 r := convValues(unpacked) // Set the timestamp on our reading to the current system time r.Timestamp = time.Now() r.StationName = w.Config.Device.Name packetChan <- r //loopPackets = append(loopPackets, unpacked) } } return nil }