Hi all,
I'm in the process of implementing a SNTP client in OpenThread for the
purpose of configuring the real-time clock. Looking around, I found a
fairly straightforward implementation of an NTP client that just polls a
NTP server (unicast) then prints out the time.
https://github.com/lettier/ntpclient
This, I've re-spun as a library built on OpenThread. Perhaps in the
future it might become another add-on module for OpenThread as we can't
be the only people that would find NTP clients useful, the code for this
is in a branch here:
https://github.com/vrtsystems/ntpclient/tree/feature/WSHUB-6-openthread-port
To use this client, I add the following code:
> int main(int argc, char* argv[]) {
…
> /* NTP client */
> struct ntp_client_t ntp_client;
> uint16_t ntp_interval = 0;
…
> /* Set up GPT0 as a 100msec (10Hz) one-shot event timer */
> SYS_CTRL_RCGCGPT |= (1 << SYS_CTRL_xCGCGPT_GPT0);
> uint32_t gpt0_period = sysctrl_sys_clock_rate() / 10;
> gptimer_oneshot32(GPT0_BASE, gpt0_period);
…
> while (1) {
> otTaskletsProcess(instance);
> PlatformProcessDrivers(instance);
…
> switch (ntp_client.state) {
> case NTP_CLIENT_DONE:
> iprintf("NTP time received: %ld sec %ld usec\r\n",
> ntp_client.tv.tv_sec,
> ntp_client.tv.tv_usec);
> ntp_client.state = NTP_CLIENT_INIT;
> break;
> case NTP_CLIENT_INT_ERR:
> iprintf("NTP time fetch failed: %d\r\n",
> ntp_client.error);
> ntp_client.state = NTP_CLIENT_INIT;
> break;
> case NTP_CLIENT_TIMEOUT:
> iprintf("NTP time fetch timed out\r\n");
> ntp_client.state = NTP_CLIENT_INIT;
> break;
> case NTP_CLIENT_INIT:
> if (!ntp_interval) {
>
> otIp6Address addr;
> otIp6AddressFromString("fdde:ad00:beef:0:d79a:fe40:f760:1de6", &addr);
>
> otError err = ntp_client_begin(instance, &ntp_client,
> &addr, NTP_CLIENT_DEFAULT_PORT, 2);
> if (err != OT_ERROR_NONE) {
> iprintf("Failed to retrieve NTP time: %d\r\n", err);
> } else {
> iprintf("NTP client request sent\r\n");
> }
> ntp_interval = 100;
>
> }
> }
> if (GPT0_MIS & (1 << GPT_INT_TATO)) {
…
> if ((ntp_client.state == NTP_CLIENT_INIT)
> && ntp_interval) {
> ntp_interval--;
> }
> ntp_client_process(&ntp_client);
…
> GPT0_ICR = (1 << GPT_INT_TATO);
> gptimer_oneshot32(GPT0_BASE, gpt0_period);
> }
> }
> }
Now, I'm attempting to test this client with `ntpd` running on my host,
which also runs the NCP.
What I have tried so far:
1. trying to get `ntpd` to listen to the IANA-assigned ff05::101
multicast address and having the clients send to that address. -- Device
reports OT_ERROR_INVALID_SOURCE_ADDRESS. This is possibly due to this
bug:
https://github.com/openthread/wpantund/issues/207
2. trying to send to the all-nodes link-local multicast address ff02::1,
again device reports OT_ERROR_INVALID_SOURCE_ADDRESS. Doing this works
fine for CoAP, so there's clearly some magic that happens somewhere that
figures out what source address to use, it is not obvious to me what
that magic is.
3. hard-coding a unicast address then calling `ip -6 addr add
${ADDRESS}/64 dev wpan0` on my host to assign the address. -- Device
sends packets allegedly, but I don't receive them on the host (according
to `tcpdump`).
4. hard-coding the MeshLocalPrefix seen in `wpanctl` in the code. --
Re-flashing the device requires me to leave then re-join the WPAN, at
which point I have a *different* address, and I'm back to square one.
Hard coding a unicast address is obviously not a good solution. I'd
like to avoid this as much as possible long-term, although in my case
today I'm just testing a proof-of-concept, it's acceptable there.
I'm also trying to avoid messing around with the CLI, because there's no
way to add new functions to it without modifying OpenThread itself from
what I can see.
Out of all the options, using the ff05::101 address seems the most
technically correct, and I've seen multicast to ff02::1 work with CoAP,
so it's doable in theory.
Has anyone managed to successfully send a raw UDP message to a multicast
group on OpenThread?
Regards,
--
_ ___ Stuart Longland - Systems Engineer
\ /|_) | T:
+61 7 3535 9619
\/ | \ | 38b Douglas Street F:
+61 7 3535 9699
SYSTEMS Milton QLD 4064
http://www.vrt.com.au