SpringBoot与Californium整合,实现物联网设备低功耗通信系统

物联网
CoAP是一种专门为物联网设备设计的轻量级协议,特别适用于资源受限的环境。它通过简单的二进制消息格式、高效的传输机制和RESTful架构,使得在低带宽、高延迟和不可靠网络条件下进行通信变得容易。

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.


责任编辑:武晓燕 来源: Java知识日历
相关推荐

2023-06-29 16:11:19

物联网LPWA网络

2015-11-16 14:19:50

2018-09-11 04:31:19

低功耗广域网LPWAN物联网

2022-09-28 15:41:47

智能建筑物联网

2015-09-23 11:36:06

2015-10-19 11:37:04

物联网广域网低功耗

2020-12-10 18:39:36

低功耗广域网LPWAN物联网

2019-09-17 15:25:34

WAN物联网技术

2021-04-13 15:11:19

物联网LoRa和BLEIoT

2016-03-17 09:38:58

物联网广域网络

2019-06-04 05:00:48

物联网低功耗广域网商业建筑

2016-01-11 17:01:49

Wi-FiHaLow物联网

2024-01-16 14:53:15

物联网IOT蜂窝漫游

2021-07-21 11:34:12

物联网IOT

2020-03-29 23:12:34

物联网LPWANIOT

2020-04-03 10:27:38

物联网智慧城市技术

2018-10-11 05:07:19

物联网通信IOT

2021-08-12 16:55:37

物联网设备通信物联网

2022-05-30 11:24:57

物联网电源低功耗

2023-03-08 11:30:56

点赞
收藏

51CTO技术栈公众号