// This is an example of an NTP client. // // It creates a UDP connection to request the current time and parse the // response from a NTP server. The system time is set to NTP time. //go:build ninafw || wioterminal || challenger_rp2040 || comboat_fw package main import ( "fmt" "io" "log" "machine" "net" "runtime" "time" "tinygo.org/x/drivers/netlink" "tinygo.org/x/drivers/netlink/probe" ) var ( ssid string pass string // IP address of the server aka "hub". Replace with your own info. ntpHost string = "0.pool.ntp.org:123" ) const NTP_PACKET_SIZE = 48 var response = make([]byte, NTP_PACKET_SIZE) func main() { waitSerial() link, _ := probe.Probe() err := link.NetConnect(&netlink.ConnectParams{ Ssid: ssid, Passphrase: pass, }) if err != nil { log.Fatal(err) } conn, err := net.Dial("udp", ntpHost) if err != nil { log.Fatal(err) } println("Requesting NTP time...") t, err := getCurrentTime(conn) if err != nil { log.Fatal(fmt.Sprintf("Error getting current time: %v", err)) } else { message("NTP time: %v", t) } conn.Close() link.NetDisconnect() runtime.AdjustTimeOffset(-1 * int64(time.Since(t))) for { message("Current time: %v", time.Now()) time.Sleep(time.Minute) } } // Wait for user to open serial console func waitSerial() { for !machine.Serial.DTR() { time.Sleep(100 * time.Millisecond) } } func getCurrentTime(conn net.Conn) (time.Time, error) { if err := sendNTPpacket(conn); err != nil { return time.Time{}, err } n, err := conn.Read(response) if err != nil && err != io.EOF { return time.Time{}, err } if n != NTP_PACKET_SIZE { return time.Time{}, fmt.Errorf("expected NTP packet size of %d: %d", NTP_PACKET_SIZE, n) } return parseNTPpacket(response), nil } func sendNTPpacket(conn net.Conn) error { var request = [48]byte{ 0xe3, } _, err := conn.Write(request[:]) return err } func parseNTPpacket(r []byte) time.Time { // the timestamp starts at byte 40 of the received packet and is four bytes, // this is NTP time (seconds since Jan 1 1900): t := uint32(r[40])<<24 | uint32(r[41])<<16 | uint32(r[42])<<8 | uint32(r[43]) const seventyYears = 2208988800 return time.Unix(int64(t-seventyYears), 0) } func message(format string, args ...interface{}) { println(fmt.Sprintf(format, args...), "\r") }