CoAP是一种专门为物联网设备设计的轻量级协议,特别适用于资源受限的环境。它通过简单的二进制消息格式、高效的传输机制和RESTful架构,使得在低带宽、高延迟和不可靠网络条件下进行通信变得容易。
哪些公司使用Californium?
- Intel Corporation在其 IoT 平台和开发工具中集成 Californium 以支持 CoAP 协议。
- IBM利用 Californium 在其 IoT 和边缘计算解决方案中实现高效的数据传输。
- 西门子使用 Californium 在其 IoT 解决方案中实现低功耗设备的通信。
- Bosch Rexroth利用 Californium 支持其工业 IoT 应用程序中的 CoAP 通信。
- Infineon Technologies 在其嵌入式系统和 IoT 解决方案中集成 Californium 以支持 CoAP 协议。
- 爱立信在其 IoT 平台中使用 Californium 实现高效的设备间通信。
- Texas Instruments Inc.提供基于 Californium 的开发套件和示例代码,助力开发者构建 IoT 应用。
- ABB Ltd.在其智能制造解决方案中利用 Californium 实现高效的数据交换和控制。
- Cisco Systems, Inc.在其 IoT 平台上使用 Californium 实现低延迟和可靠的设备通信。
Californium的特点
- 轻量级: 适合资源受限的设备。
- 可靠传输: 支持确认消息(CON)、非确认消息(NON)和重置消息(RST)。
- 多播支持: 允许向一组设备发送请求。
- 观察机制: 客户端可以订阅资源变化,实时接收更新。
- 安全性: 支持DTLS(Datagram Transport Layer Security)加密。
- RESTful架构: 使用HTTP方法(GET, POST, PUT, DELETE),便于与现有Web服务集成。
Californium的核心组件
- CoapClient: 用于创建CoAP客户端,发送请求并处理响应。
- CoapServer: 用于创建CoAP服务器,处理来自客户端的请求。
- CoapResource: 定义CoAP资源,处理特定路径上的请求。
- CoapExchange: 提供请求和响应的上下文,便于处理具体业务逻辑。
代码实操
<!-- Spring Boot Web Dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Californium Spring Boot Starter -->
<dependency>
<groupId>org.eclipse.californium</groupId>
<artifactId>californium-spring-boot-starter-server</artifactId>
<version>2.6.0</version>
</dependency>
<!-- Spring Data JPA for database operations -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
application.properties
# MySQL 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/iot_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=rootpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Hibernate 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
Device实体类
package com.example.coapserver.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
publicclass Device {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 设备ID,自增主键
private String deviceId; // 设备唯一标识符
private String type; // 设备类型
privatedouble temperature; // 温度数据
privateboolean active; // 设备是否激活
// Getter 和 Setter 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getTemperature() {
return temperature;
}
public void setTemperature(double temperature) {
this.temperature = temperature;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
仓库接口
package com.example.coapserver.repository;
import com.example.coapserver.entity.Device;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DeviceRepository extends JpaRepository<Device, Long> {
Device findByDeviceId(String deviceId); // 根据设备ID查找设备
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
Controller
package com.example.coapserver.controller;
import com.example.coapserver.entity.Device;
import com.example.coapserver.repository.DeviceRepository;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.spring.annotation.CoapController;
import org.eclipse.californium.spring.annotation.CoapGetMapping;
import org.eclipse.californium.spring.annotation.CoapObserveRelation;
import org.eclipse.californium.spring.annotation.CoapPutMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@RestController
@CoapController
@RequestMapping("/api")
publicclass SensorDataController {
privatestaticfinal Logger logger = LoggerFactory.getLogger(SensorDataController.class);
@Autowired
private DeviceRepository deviceRepository; // 注入设备仓库
// 存储传感器数据的并发哈希映射
private ConcurrentHashMap<String, Double> sensorDataMap = new ConcurrentHashMap<>();
private AtomicInteger observeCounter = new AtomicInteger(0); // 观察计数器
/**
* 注册新设备
*
* @param device 要注册的设备对象
* @return 注册结果
*/
@PostMapping("/register")
public ResponseEntity<String> registerDevice(@RequestBody Device device) {
if (deviceRepository.findByDeviceId(device.getDeviceId()) != null) {
returnnew ResponseEntity<>("设备已注册", HttpStatus.BAD_REQUEST);
}
device.setActive(true);
deviceRepository.save(device);
logger.info("注册设备: {}", device.getDeviceId());
returnnew ResponseEntity<>("设备注册成功", HttpStatus.CREATED);
}
/**
* 更新传感器数据
*
* @param sensorId 传感器ID
* @param payload 数据负载(温度值)
*/
@CoapPutMapping("/sensors/{sensorId}")
public void updateSensorData(@PathVariable String sensorId, byte[] payload) {
String dataStr = new String(payload);
try {
double data = Double.parseDouble(dataStr);
Optional<Device> deviceOpt = Optional.ofNullable(deviceRepository.findByDeviceId(sensorId));
if (deviceOpt.isPresent()) {
Device device = deviceOpt.get();
device.setTemperature(data);
deviceRepository.save(device);
sensorDataMap.put(sensorId, data);
logger.info("收到传感器 {} 的数据: {}", sensorId, data);
checkAndAlert(sensorId, data);
observeCounter.incrementAndGet(); // 触发观察者通知
} else {
logger.warn("未知的传感器ID: {}", sensorId);
}
} catch (NumberFormatException e) {
logger.error("传感器 {} 的数据格式无效: {}", sensorId, dataStr);
}
}
/**
* 获取传感器数据
*
* @param sensorId 传感器ID
* @return 传感器数据
*/
@CoapGetMapping("/sensors/{sensorId}")
public String getSensorData(@PathVariable String sensorId) {
return sensorDataMap.getOrDefault(sensorId, "无数据").toString();
}
/**
* 提供一个可观察的资源,用于实时订阅传感器状态的变化
*
* @return 观察计数器值
*/
@CoapObserveRelation
@CoapGetMapping("/observe")
public String observeSensors() {
int count = observeCounter.get();
logger.info("观察传感器,计数器: {}", count);
return String.valueOf(count); // 返回计数器值以触发观察者通知
}
/**
* 获取所有已注册的设备信息
*
* @return 设备列表
*/
@GetMapping("/devices")
public List<Device> getAllDevices() {
return deviceRepository.findAll();
}
/**
* 检查温度并触发警报
*
* @param sensorId 传感器ID
* @param temperature 温度值
*/
private void checkAndAlert(String sensorId, double temperature) {
if (temperature > 30.0) {
logger.warn("高温警报:传感器 {} 的温度为 {}°C", sensorId, temperature);
// 在这里可以添加发送警报的通知逻辑
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
Application
package com.example.coapserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CoapServerApplication {
public static void main(String[] args) {
SpringApplication.run(CoapServerApplication.class, args);
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
测试
为了测试CoAP协议,我们可以使用Californium提供的命令行工具来发送CoAP请求。
我已经安装Californium CLI工具。你也可以从Californium GitHub仓库 (https://github.com/eclipse/californium)下载并编译。很简单的!
更新传感器数据
cf-cli put coap://localhost:5683/api/sensors/sensor1 --payload "25.5"
- 1.
输出:
Sending PUT request to coap://localhost:5683/api/sensors/sensor1
Response from coap://localhost:5683/api/sensors/sensor1:
Code: 2.04 Changed
Payload:
- 1.
- 2.
- 3.
- 4.
获取传感器数据
cf-cli get coap://localhost:5683/api/sensors/sensor1
- 1.
输出:
Sending GET request to coap://localhost:5683/api/sensors/sensor1
Response from coap://localhost:5683/api/sensors/sensor1:
Code: 2.05 Content
Options: [Content-Format:text/plain]
Payload: 25.5
- 1.
- 2.
- 3.
- 4.
- 5.