中州养老:华为云设备管理接口开发全流程

需求分析

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

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

表结构设计

E-R图

数据库字段

接口分析

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

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

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

环境集成

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

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

endpoint

测试客户端能否连接成功

java 复制代码
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 {


    @Autowired
    private IoTDAClient client;

    /**
     * 查询公共实例下的所有产品
     * @throws Exception
     */
    @Test
    public 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中

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

    }

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

查询所有产品列表

Controller

从redis中查询数据并返回

java 复制代码
/**
     * 查询所有产品列表
     *
     * @return
     */
    @Override
    public 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的条件查询我们想要的姓名,年龄等

java 复制代码
/**
     * 老人分页查询
     * @param status
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public 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层的逻辑

java 复制代码
    /**
     * 注册设备
     * @param deviceDto
     */
    @Override
    public 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

java 复制代码
   /**
     * 获取设备详细信息
     */
    @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中返回给前端

java 复制代码
   /**
     * 查询设备详情
     *
     * @return
     */
    @Override
    public 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
     */
    @Override
    public 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);

    }
相关推荐
咕噜企业分发小米2 天前
阿里云与华为云基因测序数据同步的日志内容中,哪些字段对于故障排查最为关键?
数据库·阿里云·华为云
qq_316837754 天前
使用post方式上传文件到华为云obs
华为云
咕噜企业分发小米5 天前
阿里云与华为云基因测序数据同步安全性对比?
阿里云·华为云·云计算
咕噜企业分发小米5 天前
阿里云与华为云基因测序数据同步延迟对比?
阿里云·华为云·云计算
洲洲不是州州5 天前
APP与华为云和设备端的通信
华为云·手机apk·云端通信
咕噜企业分发小米5 天前
阿里云与华为云基因测序数据同步的日志格式是什么?
阿里云·华为云·云计算
咕噜企业分发小米6 天前
阿里云和华为云基因测序数据同步的审计日志如何查看?
阿里云·oracle·华为云
咕噜企业分发小米6 天前
阿里云与华为云基因测序数据分析中如何优化成本?
阿里云·华为云·云计算
咕噜企业分发小米6 天前
阿里云与华为云基因测序数据分析如何实现数据协同?
阿里云·华为云·云计算
咕噜企业分发小米6 天前
阿里云与华为云基因测序数据分析中如何实现数据共享?
阿里云·华为云·云计算