Sending UDP time requests

Send a UDP packet to the BBTime server to receive the current time. The packet must be at least 29 bytes (to prevent amplification attacks). The first 4 bytes are the header, the rest is padding:

Bytes Description
0-1 ASCII version digits (e.g. "00")
2-3 BB device ID, 2 bytes big-endian
4-28 Padding (any content, e.g. zeros)

Response format (29 bytes): +CCLK: "YY/MM/DD,HH:MM:SS+ZZ"

Rate limit: 20 responses per minute per source IP.

Host: bbtime.bbserver.eu IPv4: 195.140.252.32 IPv6: 2A01:430:D:0:2CC:E6FF:FEF7:AE65 UDP port: 4444

Linux (netcat/bash)

# BB ID = 0x00FF, padded to 29 bytes
printf '00\x00\xff%025d' 0 | nc -u -w1 bbtime.bbserver.eu 4444

# Using socat
printf '00\x00\xff%025d' 0 | socat - UDP:bbtime.bbserver.eu:4444

macOS (netcat)

# macOS netcat requires -c to close after response
printf '00\x00\xff%025d' 0 | nc -u -w1 -c bbtime.bbserver.eu 4444

Windows (PowerShell)

$udp = New-Object System.Net.Sockets.UdpClient
# Version "00" (0x30 0x30) + BB ID 0x00FF + 25 bytes padding
$bytes = [byte[]]@(0x30, 0x30, 0x00, 0xFF) + (New-Object byte[] 25)
$udp.Send($bytes, $bytes.Length, "bbtime.bbserver.eu", 4444)

# Receive response
$ep = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
$response = $udp.Receive([ref]$ep)
[System.Text.Encoding]::ASCII.GetString($response)
$udp.Close()

Arduino (ESP8266/ESP32)

#include <WiFiUdp.h>

WiFiUDP udp;
const char* server = "bbtime.bbserver.eu";
const int port = 4444;
const int MIN_PACKET_SIZE = 29;  // must match response size

void requestTime(uint16_t bbId) {
  byte packet[MIN_PACKET_SIZE] = {0};
  packet[0] = '0';  // version high
  packet[1] = '0';  // version low
  packet[2] = (bbId >> 8) & 0xFF;  // BB ID high byte
  packet[3] = bbId & 0xFF;          // BB ID low byte

  udp.beginPacket(server, port);
  udp.write(packet, MIN_PACKET_SIZE);
  udp.endPacket();

  // Wait for response
  int packetSize = 0;
  unsigned long start = millis();
  while (!packetSize && millis() - start < 2000) {
    packetSize = udp.parsePacket();
  }
  if (packetSize) {
    char buf[64];
    int len = udp.read(buf, sizeof(buf) - 1);
    buf[len] = '\0';
    // buf contains: +CCLK: "YY/MM/DD,HH:MM:SS+ZZ"
    Serial.println(buf);
  }
}

MicroPython (ESP32/RP2040)

import socket

MIN_PACKET_SIZE = 29  # must match response size

def request_time(server_ip, bb_id, port=4444):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(2)

    # Version "00" + BB ID as 2 bytes big-endian + padding
    header = b'00' + bb_id.to_bytes(2, 'big')
    packet = header + b'\x00' * (MIN_PACKET_SIZE - len(header))
    sock.sendto(packet, (server_ip, port))

    try:
        data, addr = sock.recvfrom(64)
        # data contains: +CCLK: "YY/MM/DD,HH:MM:SS+ZZ"
        print(data.decode())
    except OSError:
        print("Timeout waiting for response")
    finally:
        sock.close()

# Example: request time with BB ID 0x00FF
request_time("bbtime.bbserver.eu", 0x00FF)