18bool emit_option(uint8_t *out,
size_t *o,
size_t cap, uint16_t delta,
const uint8_t *val, uint16_t vlen)
36 dext[0] = (uint8_t)(delta - 13);
42 uint16_t x = (uint16_t)(delta - 269);
43 dext[0] = (uint8_t)(x >> 8);
53 lext[0] = (uint8_t)(vlen - 13);
59 uint16_t x = (uint16_t)(vlen - 269);
60 lext[0] = (uint8_t)(x >> 8);
64 if (start + 1 + dexn + lexn + vlen > cap)
66 out[(*o)++] = (uint8_t)((dn << 4) | ln);
67 for (
int i = 0; i < dexn; i++)
68 out[(*o)++] = dext[i];
69 for (
int i = 0; i < lexn; i++)
70 out[(*o)++] = lext[i];
71 for (uint16_t i = 0; i < vlen; i++)
77size_t wisun_build_coap(uint8_t type, uint8_t code, uint16_t msg_id,
const uint8_t *token, uint8_t tkl,
78 const char *uri_path,
const uint8_t *payload,
size_t plen, uint8_t *out,
size_t cap)
80 if (!out || tkl > 8 || (tkl && !token) || (plen && !payload))
83 if (cap < (
size_t)(4 + tkl))
85 out[o++] = (uint8_t)(0x40 | ((type & 0x03) << 4) | (tkl & 0x0F));
87 out[o++] = (uint8_t)(msg_id >> 8);
88 out[o++] = (uint8_t)msg_id;
89 for (uint8_t i = 0; i < tkl; i++)
94 const char *p = uri_path;
103 while (*p && *p !=
'/')
105 uint16_t seglen = (uint16_t)(p - seg);
106 uint16_t delta = (uint16_t)(11 - last);
107 if (!emit_option(out, &o, cap, delta, (
const uint8_t *)seg, seglen))
114 if (o + 1 + plen > cap)
117 for (
size_t i = 0; i < plen; i++)
118 out[o++] = payload[i];
123void wisun_init(WisunFan *fan,
const DetIp *border_router, WisunNode *storage,
size_t cap)
128 fan->border_router = *border_router;
130 memset(&fan->border_router, 0,
sizeof(fan->border_router));
131 fan->nodes = storage;
132 fan->cap = storage ? cap : 0;
136int wisun_node_register(WisunFan *fan,
const DetIp *addr, uint32_t now)
138 if (!fan || !fan->nodes || !addr)
141 if (wisun_node_find(fan, addr, &idx))
143 fan->nodes[idx].joined =
true;
144 fan->nodes[idx].last_seen = now;
147 if (fan->count >= fan->cap)
149 fan->nodes[fan->count].addr = *addr;
150 fan->nodes[fan->count].joined =
true;
151 fan->nodes[fan->count].last_seen = now;
152 return (
int)fan->count++;
155bool wisun_node_find(
const WisunFan *fan,
const DetIp *addr,
size_t *idx)
157 if (!fan || !fan->nodes || !addr)
159 for (
size_t i = 0; i < fan->count; i++)
169size_t wisun_joined_count(
const WisunFan *fan)
171 if (!fan || !fan->nodes)
174 for (
size_t i = 0; i < fan->count; i++)
175 if (fan->nodes[i].joined)
190void put(Buf *b,
const char *s)
194 size_t sl = strnlen(s, b->cap + 1);
195 if (b->len + sl >= b->cap)
200 memcpy(b->p + b->len, s, sl);
205size_t wisun_nodes_json(
const WisunFan *fan,
char *out,
size_t cap)
207 if (!fan || !out || cap == 0)
209 Buf b = {out, cap, 0,
true};
211 for (
size_t i = 0; i < fan->count; i++)
217 put(&b,
"{\"addr\":\"");
219 put(&b,
"\",\"joined\":");
220 put(&b, fan->nodes[i].joined ?
"true" :
"false");
size_t det_ip_format(const DetIp *ip, char *out, size_t cap)
Format ip into out as its RFC 5952 canonical text.
bool det_ip_equal(const DetIp *a, const DetIp *b)
True if a and b are the same family and address.
#define DET_IP_STR_MAX
Longest text an det_ip_format can produce, including the NUL (RFC 5952 v4-mapped).
A v4 or v6 address in network (big-endian) byte order.
Wi-SUN FAN border-router connector (DETWS_ENABLE_WISUN).