   serial.printf("Address: %s\n", WiFi.localIP().toString().c_str());
 }
 
-static WiFiClient connect_client() {
-  WiFiClient client;
-  if (!client.connect(HOST, PORT))
-    fatal_error("Connection to host failed");
-  return client;
-}
-
 static void delete_messages() {
   auto size = pending_messages_queue::storage_size(MAX_PENDING_MESSAGES);
   for (size_t i = 0; i < size; i++)

  serial.printf("Attempting to send %d messages\n",
      pending_messages->size());

  // XXX Add pop_front() ???
  // XXX Implement a circular queue ???
  while (!pending_messages->empty()) {
    auto last_idx = pending_messages->size() - 1;
    auto& msg = (*pending_messages)[last_idx];
    serial.printf("About to send msg %d (idx: %d)\n", msg.time, last_idx);
    // TODO use error code
    send_message(msg);
    pending_messages->pop_back();
  } 
}

static void send_message(const message& msg) {
  // TODO use the same connection for all messages
  auto client = connect_client();
  client.print("sensor-id: ");
  serial.printf("msg.time=%d\n", msg.time);
  client.println(msg.time);

//      serial.printf("time: %d\n", msg.time);
//    for (size_t s = 0; s < SAMPLES_PER_MESSAGE; s++)
//      serial.printf("sample%d: %d\n", s, msg.samples[s]);
}

static void print_date() {

static constexpr size_t MAX_PENDING_MESSAGES = 4;
static constexpr size_t SAMPLES_PER_MESSAGE = 8;

static constexpr unsigned SENSOR_WARMUP_DELAY = 1000;
static constexpr unsigned DELAY_BETWEEN_SAMPLES = 500;

// Sleep time: 30s (measured in us)
static constexpr unsigned SLEEP_TIME = 30 * 1000 * 1000;

static constexpr unsigned short local_port = 8888;

struct message {
  time_t time;
  unsigned short samples[SAMPLES_PER_MESSAGE];
};

typedef persistent_queue<message> pending_messages_queue;

static pending_messages_queue* pending_messages;

static WiFiUDP Udp;
// TODO make ntp_client a template capable of handling both WiFiUDP and EthernetUDP
static ntp_client ntp(Udp);

static PrintEx serial = Serial;

void setup() {
  Serial.begin(115200);
