blob: 85d5dc98f676d261d809c41e7face2acb27c2c8c [file] [log] [blame]
/* Full-stack IoT client example. */
/*
* Copyright (c) 2018 Linaro Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_REGISTER(net_google_iot_mqtt, LOG_LEVEL_INF);
#include <zephyr.h>
#include "dhcp.h"
#include "protocol.h"
#include <net/sntp.h>
#include <net/net_config.h>
#include <net/net_event.h>
/* This comes from newlib. */
#include <time.h>
#include <inttypes.h>
s64_t time_base;
void do_sntp(struct addrinfo *addr)
{
struct sntp_ctx ctx;
int rc;
s64_t stamp;
u64_t epoch_time;
char time_str[sizeof("1970-01-01T00:00:00")];
LOG_INF("Sending NTP request for current time:");
/* Initialize sntp */
rc = sntp_init(&ctx, addr->ai_addr, sizeof(struct sockaddr_in));
if (rc < 0) {
LOG_ERR("Unable to init sntp context: %d", rc);
return;
}
rc = sntp_request(&ctx, K_FOREVER, &epoch_time);
if (rc == 0) {
stamp = k_uptime_get();
time_base = epoch_time * MSEC_PER_SEC - stamp;
/* Convert time to make sure. */
time_t now = epoch_time;
struct tm now_tm;
gmtime_r(&now, &now_tm);
strftime(time_str, sizeof(time_str), "%FT%T", &now_tm);
LOG_INF(" Acquired time: %s", log_strdup(time_str));
} else {
LOG_ERR(" Failed to acquire SNTP, code %d\n", rc);
}
sntp_close(&ctx);
}
/*
* TODO: These need to be configurable.
*/
#define MBEDTLS_NETWORK_TIMEOUT 30000
static void show_addrinfo(struct addrinfo *addr)
{
char hr_addr[NET_IPV6_ADDR_LEN];
void *a;
top:
LOG_DBG(" flags : %d", addr->ai_flags);
LOG_DBG(" family : %d", addr->ai_family);
LOG_DBG(" socktype: %d", addr->ai_socktype);
LOG_DBG(" protocol: %d", addr->ai_protocol);
LOG_DBG(" addrlen : %d", addr->ai_addrlen);
/* Assume two words. */
LOG_DBG(" addr[0]: 0x%lx", ((uint32_t *)addr->ai_addr)[0]);
LOG_DBG(" addr[1]: 0x%lx", ((uint32_t *)addr->ai_addr)[1]);
if (addr->ai_next != 0) {
addr = addr->ai_next;
goto top;
}
a = &net_sin(addr->ai_addr)->sin_addr;
LOG_INF(" Got %s",
log_strdup(net_addr_ntop(addr->ai_family, a,
hr_addr, sizeof(hr_addr))));
}
/*
* Things that make sense in a demo app that would need to be more
* robust in a real application:
*
* - DHCP happens once. If it fails, or we change networks, the
* network will just stop working.
*
*/
void main(void)
{
char time_ip[NET_IPV6_ADDR_LEN];
static struct addrinfo hints;
struct addrinfo *haddr;
int res;
int cnt = 0;
LOG_INF("Main entered");
app_dhcpv4_startup();
LOG_INF("Should have DHCPv4 lease at this point.");
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
while ((res = getaddrinfo("time.google.com", "123", &hints,
&haddr)) && cnt < 3) {
LOG_ERR("Unable to get address for NTP server, retrying");
cnt++;
}
if (res != 0) {
LOG_ERR("Unable to get address of NTP server, exiting %d", res);
return;
}
LOG_INF("DNS resolved for time.google.com:123");
time_base = 0;
inet_ntop(AF_INET, &net_sin(haddr->ai_addr)->sin_addr, time_ip,
haddr->ai_addrlen);
show_addrinfo(haddr);
do_sntp(haddr);
freeaddrinfo(haddr);
/* early return if we failed to acquire time */
if (time_base == 0) {
LOG_ERR("Failed to get NTP time");
return;
}
mqtt_startup("mqtt.googleapis.com", 8883);
}