Constrained Application Protocol (CoAP) 是专为受限设备设计的 Web 传输协议,适用于物联网场景。
| 特性 | CoAP | HTTP |
|---|---|---|
| 传输 | UDP | TCP |
| 头部 | 4 字节+ | 几十字节 |
| 方法 | GET/POST/PUT/DELETE | GET/POST/PUT/DELETE |
| 资源发现 | 支持 | 可选 |
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Ver | T | TKL | Code | Message ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Token (if any, TKL bytes) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++++++++++++-+-+-+-+-+-+-+-+
| Options (if any) ...
+-+-+-+-+-+-+-+-+++++++++++++++++++++++++++++++++-+-+-+-+-+-+-+-+
| Payload (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++++++++++++-+-+-+-+-+-+-+-+
CONFIG_COAP=y
CONFIG_COAP_NETWORKING=y
CONFIG_COAP_MESSAGE_MAX_SIZE=1152
#include <zephyr/net/coap.h>
#include <zephyr/net/coap_link_format.h>
// CoAP 资源定义
static struct coap_resource resources[] = {
{
.path = "sensor/temperature",
.get = get_temperature,
.post = post_temperature,
},
{
.path = "led",
.put = put_led,
},
{}
};
// GET 处理器
static int get_temperature(struct coap_resource *resource,
struct coap_packet *request,
struct coap_packet *response,
uint8_t *data,
uint16_t data_len,
struct sockaddr *addr,
socklen_t addr_len) {
char payload[32];
int len = snprintf(payload, sizeof(payload),
"{\"temp\":%d}", temperature);
coap_packet_append_payload(response, payload, len);
coap_header_set_code(response, COAP_RESPONSE_CODE_CONTENT);
return 0;
}
// 发送 CoAP GET 请求
int coap_get(const char *uri) {
struct coap_packet request;
uint8_t request_token[8];
uint8_t request_data[128];
// 构建请求
coap_packet_init(&request, request_data, sizeof(request_data),
1, COAP_TYPE_CON,
8, coap_next_token(request_token, 8),
coap_next_id(), COAP_METHOD_GET, NULL);
// 添加 URI 路径
coap_packet_append_option(&request, COAP_OPTION_URI_PATH,
"sensor", 6);
// 发送请求
return send_request(&request, addr, addr_len);
}
// 观察者列表
static sys_slist_t observers;
// 注册观察者
static int observe_register(struct coap_resource *resource,
struct coap_packet *request,
struct coap_observer *observer) {
sys_slist_append(&observers, &observer->node);
return 0;
}
// 通知观察者
static void notify_observers(struct coap_resource *resource,
uint8_t *data, size_t len) {
sys_snode_t *node;
struct coap_observer *observer;
SYS_SLIST_FOR_EACH_NODE(&observers, node) {
observer = CONTAINER_OF(node, struct coap_observer, node);
// 发送通知(具体实现取决于当前 socket/context 组织方式)
send_notification(observer, data, len);
}
}
这部分更适合作为“概念迁移”理解,而不是 Zephyr/NCS 当前的标准 CoAP 用法。
BLE / IEEE 802.15.4 → IPv6 → UDP → CoAP
CoAP 的安全版本通常称为 CoAPS,本质上是在 UDP socket 之上叠加 DTLS。
coap_dtls_init() 当成通用接口// PSK 预共享密钥
static uint8_t psk_id[] = "client1";
static uint8_t psk_key[] = {0x01, 0x02, 0x03, /*...*/};
CoAP Client → CoAP Proxy → HTTP Server
CoAP-HTTP 代理属于网关层设计,通常包含三步:
这里不建议把某个 http_request 结构体和 http_client_req() 直接写成通用模板,因为实际工程里 HTTP 层封装差异很大。
// 资源:/temperature
static int get_temperature(struct coap_resource *resource,
struct coap_packet *request,
struct coap_packet *response,
uint8_t *data, uint16_t data_len,
struct sockaddr *addr, socklen_t addr_len) {
int temp = read_temperature_sensor();
snprintf(data, data_len, "%d", temp);
coap_packet_append_payload(response, data, strlen(data));
return 0;
}
// 资源:/led
static int put_led(struct coap_resource *resource,
struct coap_packet *request,
struct coap_packet *response,
uint8_t *data, uint16_t data_len,
struct sockaddr *addr, socklen_t addr_len) {
// 解析 JSON: {"on": true}
bool led_on = parse_led_state(data, data_len);
set_led(led_on);
coap_header_set_code(response, COAP_RESPONSE_CODE_CHANGED);
return 0;
}
# GET 请求
coap-client -m get coap://192.168.1.100/sensor/temperature
# PUT 请求
coap-client -m put -e '{"on":true}' coap://192.168.1.100/led