需求分析

点击同步数据时,要把华为云的数据拉取到我们的系统中

对于新增设备操作,实际上这些参数与华为云产品我们添加设备时的参数是一样的

表结构设计

E-R图

数据库字段

接口分析

对于设备中的数据,我们既要再IOT平台存储,又要在数据库中存储.之所以保存两份数据的原因:

IOT平台中只是维护了基础的设备信息,并没有跟业务数据进行绑定,比如,设备属于哪个位置,绑定了哪个老人。

对于我们要实现的功能,华为云提供了丰富的接口

环境集成

IOT平台目前已经给提供了完整的SDK,我们在conmon模块引入华为云的两个依赖

我们添加关于IOT的配置并修改

endpoint

测试客户端能否连接成功

package com.zzyl.test;import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.ListProductsRequest;
import com.huaweicloud.sdk.iotda.v5.model.ListProductsResponse;
import com.huaweicloud.sdk.iotda.v5.model.Page;
import com.huaweicloud.sdk.iotda.v5.model.ProductSummary;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
public class IoTDeviceTest {@Autowiredprivate IoTDAClient client;/*** 查询公共实例下的所有产品* @throws Exception*/@Testpublic void selectProduceList() throws Exception {ListProductsRequest listProductsRequest = new ListProductsRequest();listProductsRequest.setLimit(50);ListProductsResponse response = client.listProducts(listProductsRequest);List<ProductSummary> products = response.getProducts();System.out.println(products);}}

功能开发

从物联网平台同步产品列表

Controller层就是一个简单的post请求

servic层,我们调用华为云的接口请求获得产品的列表存入到Redis中

 /*** 同步产品列表*/@Overridepublic void syncProductList(){//请求参数ListProductsRequest listProductsRequest=new ListProductsRequest();//设置条数listProductsRequest.setLimit(50);//发起请求ListProductsResponse response=client.listProducts(listProductsRequest);if(response.getHttpStatusCode()!=200){throw new BaseException("物联网接口 - 查询产品,同步失败");}//存储到redisredisTemplate.opsForValue().set(CacheConstants.IOT_ALL_PRODUCT_LIST,JSONUtil.toJsonStr(response.getProducts()));}

此时打开redis图形化界面,所有数据均已经存储到redis中

查询所有产品列表

Controller

从redis中查询数据并返回

/*** 查询所有产品列表** @return*/@Overridepublic List<ProductVo> allProduct(){//从redis中查询数据String jsonStr=redisTemplate.opsForValue().get(CacheConstants.IOT_ALL_PRODUCT_LIST);//如果数据为空,则返回一个空集合if(StringUtils.isEmpty(jsonStr)){return Collections.emptyList();}//解析数据,并返回return JSONUtil.toList(jsonStr,ProductVo.class);}

前后端联调查看结果

查询已经入住的老人列表

接口文档

对于分页查询接口,传入分页数量和每页数量

通过传入的状态作为mp的条件查询我们想要的姓名,年龄等

/*** 老人分页查询* @param status* @param pageNum* @param pageSize* @return*/@Overridepublic TableDataInfo pageQuery(Integer status,Integer pageNum,Integer pageSize){//分页查询老人数据//创建条件构建器LambdaQueryWrapper<Elder> queryWrapper=new LambdaQueryWrapper<>();//创建分页对象Page<Elder> page=new Page<>(pageNum,pageSize);//按照状态查询if(ObjectUtil.isNotNull(status)){queryWrapper.eq(Elder::getStatus,status);}//sql返回结果,只展示主键、名字、身份照号、床位编号queryWrapper.select(Elder::getId,Elder::getName,Elder::getIdCardNo,Elder::getBedNumber);//执行查询page=page(page,queryWrapper);//返回分页结果return getDataTable(page);}/*** 封装分页结果* @param page* @return*/private TableDataInfo getDataTable(Page<Elder> page){//封装分页结果TableDataInfo tableDataInfo=new TableDataInfo();tableDataInfo.setTotal(page.getTotal());tableDataInfo.setCode(HttpStatus.SUCCESS);tableDataInfo.setMsg("请求成功");tableDataInfo.setRows(page.getRecords());return tableDataInfo;}

注册设备

在Controller层,我们传入设备信息

service层的逻辑

/*** 注册设备* @param deviceDto*/@Overridepublic void registerDevice(DeviceDto deviceDto){//判断设备名称是否重复LambdaQueryWrapper<Device> queryWrapper=new LambdaQueryWrapper<>();queryWrapper.eq(Device::getDeviceName,deviceDto.getDeviceName());if(count(queryWrapper)>0){throw new BaseException("设备名称已存在,请重新输入");}//检验设备标识码是否重复LambdaQueryWrapper<Device> queryWrapperNodeId=new LambdaQueryWrapper<>();queryWrapperNodeId.eq(Device::getNodeId,deviceDto.getNodeId());if(count(queryWrapperNodeId)>0){throw new BaseException("设备标识码已存在,请重新输入");}//校验同一位置是否绑定了同一类产品LambdaQueryWrapper<Device> condition=new LambdaQueryWrapper<>();condition.eq(Device::getProductKey,deviceDto.getProductKey()).eq(Device::getLocationType,deviceDto.getLocationType()).eq(Device::getPhysicalLocationType,deviceDto.getPhysicalLocationType()).eq(Device::getBindingLocation,deviceDto.getBindingLocation());if(count(condition)>0){throw new BaseException("该老人/位置已绑定该产品,请重新选择");}//iot中新增设备AddDeviceRequest request=new AddDeviceRequest();AddDevice body=new AddDevice();body.withProductId(deviceDto.getProductKey());body.withDeviceName(deviceDto.getDeviceName());body.withNodeId(deviceDto.getNodeId());request.withBody(body);AuthInfo authInfo=new AuthInfo();//秘钥String secret=UUID.randomUUID().toString().replaceAll("-","");authInfo.withSecret(secret);body.setAuthInfo(authInfo);AddDeviceResponse response;try{response=client.addDevice(request);}catch(Exception e){e.printStackTrace();throw new BaseException("物联网接口 - 注册设备,调用失败");}//设备数据保存到数据库//属性拷贝Device device=BeanUtil.toBean(deviceDto,Device.class);//设备id、设备绑定状态device.setIotId(response.getDeviceId());//秘钥device.setSecret(secret);//在数据库中新增设备try{save(device);}catch(Exception e){throw new BaseException("同一个位置不能绑定同类型的产品");}}

测试

查看设备上报的数据

前端传入Controller层物联网设备的id

   /*** 获取设备详细信息*/@GetMapping("/{iotId}")@ApiOperation("获取设备详细信息")@ApiImplicitParams({@ApiImplicitParam(name = "iotId", value = "物联网设备id", required = true, dataTypeClass = String.class)})public AjaxResult getInfo(@PathVariable("iotId") String iotId){return success(deviceService.queryDeviceDetail(iotId));}/*** 查询设备上报数据*/@GetMapping("/queryServiceProperties/{iotId}")@ApiOperation("查询设备上报数据")@ApiImplicitParams({@ApiImplicitParam(name = "iotId", value = "物联网设备id", required = true, dataTypeClass = String.class)})public AjaxResult queryServiceProperties(@PathVariable("iotId") String iotId){AjaxResult ajaxResult=deviceService.queryServiceProperties(iotId);return ajaxResult;}

service层通过Controller层传入的iotId查询数据库中的设备信息,调用华为的物联网接口查询华为云中设备的实时信息,将数据封装到deviceVo中返回给前端

   /*** 查询设备详情** @return*/@Overridepublic DeviceDetailVo queryDeviceDetail(String iotId){//查询数据库Device device=getOne(Wrappers.<Device>lambdaQuery().eq(Device::getIotId,iotId));if(ObjectUtil.isEmpty(device)){return null;}//调用华为云物联网接口ShowDeviceRequest request=new ShowDeviceRequest();request.setDeviceId(iotId);ShowDeviceResponse response;try{response=client.showDevice(request);}catch(Exception e){log.info("物联网接口 - 查询设备详情,调用失败:{}",e.getMessage());throw new BaseException("物联网接口 - 查询设备详情,调用失败");}//属性拷贝DeviceDetailVo deviceVo=BeanUtil.toBean(device,DeviceDetailVo.class);deviceVo.setDeviceStatus(response.getStatus());String activeTimeStr=response.getActiveTime();if(StringUtils.isNotEmpty(activeTimeStr)){LocalDateTime activeTime=LocalDateTimeUtil.parse(activeTimeStr,DatePattern.UTC_MS_PATTERN);//日期时区转换activeTime=activeTime.atZone(ZoneId.from(ZoneOffset.UTC)).withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDateTime();deviceVo.setActiveTime(activeTime);}return deviceVo;}/*** 查询设备上报数据** @param iotId* @return*/@Overridepublic AjaxResult queryServiceProperties(String iotId){ShowDeviceShadowRequest request=new ShowDeviceShadowRequest();request.setDeviceId(iotId);ShowDeviceShadowResponse response=client.showDeviceShadow(request);if(response.getHttpStatusCode()!=200){throw new BaseException("物联网接口 - 查询设备上报数据,调用失败");}List<DeviceShadowData> shadow=response.getShadow();if(CollUtil.isEmpty(shadow)){List<Object> emptyList=Collections.emptyList();return AjaxResult.success(emptyList);}//返回数据JSONObject jsonObject=JSONUtil.parseObj(shadow.get(0).getReported().getProperties());List<Map<String, Object>>list=new ArrayList<>();//处理上报时间日期LocalDateTime activeTime=LocalDateTimeUtil.parse(shadow.get(0).getReported().getEventTime(),"yyyyMMdd'T'HHmmss'Z'");//日期时区转换LocalDateTime eventTime=activeTime.atZone(ZoneId.from(ZoneOffset.UTC)).withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDateTime();jsonObject.forEach((k,v)->{Map<String, Object> map=new HashMap<>();map.put("functionId",k);map.put("value",v);map.put("eventTime",eventTime);list.add(map);});return AjaxResult.success(list);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96392.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96392.shtml
英文地址,请注明出处:http://en.pswp.cn/web/96392.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Llama-Factory微调Qwen2.5-VL从数据集制作到部署记录

Llama-Factory微调Qwen2.5-VL从数据集制作到部署记录 电脑环境配置&#xff1a; 1.ubuntu24 2.3090(24G) 3.Cuda12.9 一、数据集制作 我的数据集主要是对图像内容进行描述 1.Label-studio制作数据集 这是最原始的从零开始制作数据集的方法&#xff0c;不建议这样做&#xff01;…

【蓝桥杯真题67】C++数位和为偶数的数 第十五届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解

C++数位和为偶数的数 第十五届蓝桥杯青少年创意编程大赛C++选拔赛真题 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 1、C++专栏 电子学会C++一级历年真题解析 电子学会C++二级历年真题解析

【计算机网络 | 第11篇】宽带接入技术及其发展历程

文章目录宽带接入技术详解数字传输系统技术演进早期电话网的传输技术演变数字传输系统技术演进&#xff1a;从碎片到统一宽带接入技术 ADSLADSL的基本原理与非对称特性DMT调制技术&#xff1a;多子信道并行传输ADSL接入网组成电话分离器的设计原理与优势ADSL的升级&#xff1a;…

(论文速读)SCSegamba:用于结构裂纹分割的轻量级结构感知视觉曼巴

论文题目&#xff1a;SCSegamba: Lightweight Structure-Aware Vision Mamba for Crack Segmentation in Structures&#xff08;用于结构裂纹分割的轻量级结构感知视觉曼巴&#xff09;会议&#xff1a;CVPR2025摘要&#xff1a;不同场景下的结构裂缝像素级分割仍然是一个相当…

《苏超风云》亮相时尚大赏,成短剧行业发展新风向

当男频短剧凭借《一品布衣》五天横扫10亿播放的数据宣告逆袭&#xff0c;短剧市场格局正经历深刻洗牌。风口之下&#xff0c;头条视听、中皋文旅、国内时尚视觉与短视频创作领域的头部厂牌“大湾视频”携手下场&#xff0c;打造精品男频短剧《苏超风云》&#xff0c;剑指2025年…

HTML5新年元旦网站源码

新年主题网站开发概述 本项目基于HTML5、CSS3与JavaScript技术栈&#xff0c;打造了一个功能丰富、交互体验流畅的新年主题网站&#xff0c;涵盖文化展示、互动娱乐与社交分享三大核心模块&#xff0c;通过现代化前端技术实现沉浸式节日氛围营造。 1.1、核心功能架构 网站采…

CentOS 7 下iscsi存储服务配置验证

一、环境说明 centos7服务器*2服务器ip&#xff1a;服务端10.10.10.186 客户端10.10.10.184服务端存储卷sda1提前关闭防火墙&#xff0c;或开放默认 iSCSI 使用 3260 端口 二、服务端&#xff08;Target&#xff09;配置 安装 iSCSI target 服务 yum install -y targetcli syst…

立即数、栈、汇编与C函数的调用

一、立即数在 ARM 架构中&#xff0c;立即数是指在指令中直接编码的常量值&#xff0c;而不是通过寄存器或内存引用的值立即数的特点编码限制&#xff1a;ARM指令是固定长度的&#xff08;32位&#xff09;&#xff0c;因此立即数不能占用太多位数。典型的算术和逻辑指令通常只…

贪心算法与动态规划:数学原理、实现与优化

贪心算法与动态规划&#xff1a;数学原理、实现与优化 引言&#xff1a;算法选择的本质 在计算机科学领域&#xff0c;算法选择的本质是对问题特征的数学建模与求解策略的匹配。贪心算法与动态规划作为两种经典的优化算法&#xff0c;分别在不同问题域展现出独特优势。本文将从…

Leetcode 刷题记录 21 —— 技巧

Leetcode 刷题记录 21 —— 技巧 本系列为笔者的 Leetcode 刷题记录&#xff0c;顺序为 Hot 100 题官方顺序&#xff0c;根据标签命名&#xff0c;记录笔者总结的做题思路&#xff0c;附部分代码解释和疑问解答&#xff0c;01~07为C语言&#xff0c;08及以后为Java语言&#xf…

Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示

把这两个开关打开&#xff0c;然后刷新gradle文件

Java中方法重写与重载的区别

目录 1. 方法重载 (Overload) 什么是方法重载&#xff1f; 重载的特点&#xff1a; 重载的示例&#xff1a; 重载的调用&#xff1a; 2. 方法重写 (Override) 什么是方法重写&#xff1f; 重写的特点&#xff1a; 重写的示例&#xff1a; 重写的调用&#xff1a; 3.…

微信小程序发送订阅消息-一次订阅,一直发送消息。

实现思路长期订阅要求太高&#xff0c;需要政府、公共交通等单位才有资格&#xff0c;所以只能使用一次性订阅。 就像是买奶茶&#xff0c;下单以后&#xff0c;会弹出让用户订阅消息那种。以买奶茶为例:用户第一次下单成功&#xff0c;点击了订阅消息。&#xff08;一般都有三…

408 Request Timeout:请求超时,服务器等待客户端发送请求的时间过长。

408 Request Timeout 是 HTTP 状态码之一&#xff0c;表示客户端在发送请求时&#xff0c;服务器等待的时间过长&#xff0c;最终放弃了处理该请求。此问题通常与网络延迟、客户端配置、服务器设置或者应用程序的性能有关。1. 常见原因1.1 客户端问题网络连接延迟或不稳定&…

MongoDB面试集锦

该书的使用的MongoDB版本是 4.2.01、什么是NoSQL数据库&#xff1f;NoSQL和RDBMS有什么区别&#xff1f;在那些情况下使用和不使用NoSQL数据库&#xff1f;NoSQL是非关系型数据库&#xff0c;NoSQLNot Only SQL 。关系型数据库采用的是结构化的数据&#xff0c;NoSQL采用的是键…

直击JVM面试题

JVM组成 JVM JVM 就是 Java 程序的运行环境&#xff0c;它通过 类加载、字节码执行、内存管理、GC、线程调度 等机制&#xff0c;让 Java 实现了 跨平台、自动内存管理和高效执行。 它是一个抽象的计算机&#xff0c;能执行以 字节码&#xff08;.class 文件&#xff09; 为单…

地球系统模式(CESM)实践技术应用及进阶

目前通用地球系统模式&#xff08;Community Earth System Model&#xff0c;CESM&#xff09;在研究地球的过去、现在和未来的气候状况中具有越来越普遍的应用。CESM由美国NCAR于2010年07月推出以来&#xff0c;一直受到气候学界的密切关注。近年升级的CESM2.0在大气、陆地、海…

StarRocks导入数据-使用 Broker Load 进行异步导入

目录 一、背景 二、实操 三、查看导入进度 一、背景 将hive库数据表导入starrocks. 二、实操 LOAD LABEL user_behavior (DATA INFILE("hdfs://<hdfs_ip>:<hdfs_port>/user/amber/user_behavior_ten_million_rows.parquet")INTO TABLE user_behavior…

c语言,识别到黑色就自动开枪,4399单击游戏狙击战场,源码分享,豆包ai出品

不好用&#xff0c;识别速度慢&#xff0c;有时候识别不准确#include <windows.h> #include <stdio.h> #include <math.h> HDC hdcScreen; void leftClick(); void RGBtoHSV(int r, int g, int b, int* h, int* s, int* v); int fuzzyFindColor(int x1, int…

电动汽车充电标准之 — SAE J1772“电动汽车传导充电连接器”简介

SAE J1772&#xff08;通常读作 "J seventeen seventy-two"&#xff09;是由美国汽车工程师学会&#xff08;SAE&#xff09;制定的&#xff0c;针对电动汽车传导充电连接器的北美标准。它规范了电动汽车&#xff08;EV&#xff09;与充电设备&#xff08;EVSE&#…