锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Java物联网企业级项目 亿可控系统分析与设计

时间:2023-02-23 18:30:00 sn针插座连接器

第1章 亿可控系统分析与设计

学习目标

  • 了解物联网的应用和发展现状
  • 能说出亿可控核心功能
  • 能画出亿可控系统架构图
  • 能够准备和了解亿可控环境的功能结构
  • 完成设备管理相关功能的开发

1.物联网行业分析

1.1 物联网是什么?

物联网(英文:Internet of Things,缩写:IoT)它起源于媒体领域,是信息技术产业的第三次革命。物联网是指通过信息传感设备将任何物体与网络连接,并通过信息传输媒体进行信息交换和通信,以实现智能识别、定位、跟踪、监督等功能。

感知层、网络传输层和应用层是物联网应用中的三大关键技术。

中式物联网定义:

最简洁明了的定义:物联网(Internet of Things)它是一个基于互联网、传统电信网络和其他信息载体的网络,允许所有可以独立找到的普通物理对象实现互联。它具有三个重要特点:普通对象设备、自主终端互联和智能普通服务。

上图中念出现在上图中,这里分别解释一下:

两化融合是信息化与工业化的深度结合, 是指以信息化推动工业化,以工业化推动信息化,走新的工业化道路;两个现代化融合的核心是信息支持,追求可持续发展模式。

M2M全称Machine to Machine,指数据从一个终端传输到另一个终端,即机器与机器之间的对话。

射频识别(RFID)是 Radio Frequency Identification 缩写。其原理是在阅读器和标签之间进行非接触式数据通信,以达到识别目标的目的。RFID 的应用非常广泛,典型应用有动物晶片、汽车晶片防盗器、门禁管制、停车场管制、生产线自动化、物料管理。

传感网它是传感器网络的缩写。传感器网络是一门集计算机、通信、网络、智能计算、传感器、嵌入式系统、微电子等领域于一体的新兴学科。它将大量多种传感器节点(集传感、采集、处理、收发于一体)组成自主网络,实现物理世界的动态智能协同感知。

从上图可以看出,物联网涵盖了上述四个领域。

一句式理解物联网

通过信息传感设备将所有物品与互联网连接起来,进行信息交换,即物相息,实现智能识别和管理。

历史溯源

当中国在1999年提出物联网的概念时,它被称为传感网络。中国科学院早在1999年就开始了传感网络的研发。与其他国家相比,中国的技术研发水平处于世界前列,具有同发优势和重大影响力。
国际电信联盟于2005年11月27日在突尼斯举行的信息社会峰会上(ITU)发布了《ITU互联网报告2005:物联网正式提出了物联网的概念。
2009年8月24日,中国移动总裁王建宙在台湾的公开演讲中也提到了物联网的概念。
工业和信息化部总工程师朱宏仁在2009年中国工业运营夏季报告会上表示,物联网是一个新概念,到2009年还没有公认的概念。他说,总的来说,物联网是指各种传感器和现有的互联网相互连接的新技术。
物联网是在计算机互联网的基础上使用的RFID、无线数据通信等技术,构建覆盖世界万物的Internet of Things”。在这个网络中,物品(商品)可以在没有人干预的情况下交流。其本质是利用射频自动识别(RFID)通过计算机互联网实现商品(商品)的自动识别和信息的互联和共享。
物联网概念的出现打破了以往的传统思维。过去的想法一直是物理基础设施和IT一方面是机场、公路、建筑物,另一方面是数据中心、个人电脑、宽带等。在物联网时代,钢筋混凝土和电缆将与芯片和宽带相结合,从这个意义上说,基础设施更像是一个新的地球。因此,一些业内人士认为物联网和智能电网是智能地球的有机组成部分。

1.2 物联网应用领域

1、智能家居
智能家居采用先进的计算机技术和智能硬件(氦氪)wifi、Zigbee、蓝牙、NB-iot等),物联网技术和通信技术将与家具生活中的各种子系统有机结合,使家居生活更加舒适、方便、有效、安全。智能家居主要包括智能
扬声器、智能灯、智能插座、智能、智能恒温器、清扫机器人等。

2、智慧交通
智能交通是以物联网、互联网、云计算为代表的智能传感技术、信息网络技术、通信传输技术和数据处理技术的综合交通系统,在更大的时空范围内发挥作用 [2] 。智能交通是以智能路网、智能出行、智能设备、智能物流、智能管理为重要内容,以信息技术高度集成、信息资源综合应用为主要特征的新型交通发展模式。依托迪蒙科技在云计算、物联网、大数据、金融科技等领域的丰富发展经验和雄厚的技术积累,目前是中国第一个历时三年的努力建设 集网上叫车、智能停车、汽车租赁、汽车金融等智能旅游领域创新商业模式于一体的高端智能交通整体解决方案 [3] 。

4、智能电网
智能电网是一种集传感、通信、计算、决策和控制为一体的综合数字复合系统。通过获取电网各级节点资源和设备的运行状态,实现能源流、信息流和业务流的高度集成,提高电力系统的运行稳定性,最大限度地提高设备效率,提高安全可靠性,节能减排,提高用户供电质量,提高可再生能源利用效率。

4、智慧城市
智慧城市是利用信息和通信技术手段感知、分析和整合城市运营核心系统的关键信息,智能响应民生、环保、公共安全、城市服务、工商活动等各种需求。本质是利用先进的信息技术实现城市的智能管理和运营,为城市人民创造更好的生活,促进城市的和谐可持续发展。
随着人类社会的不断发展,未来城市将承载越来越多的人口。目前,我国正处于城市化加速发展的时期,部分地区的城市疾病问题日益严重。为了解决城市发展问题,实现城市可持续发展,建设智慧城市已成为当今世界城市发展不可逆转的历史趋势。
智慧城市建设已在国内外许多地区开展,并取得了智慧上海、智慧双流等国内成果;新加坡的智慧国家计划和韩国的智慧国家计划U-City计划”等 。

5.其他领域:智能汽车、智能建筑、智能水务、智能商业、智能工业、安全城市、智能农业、智能安全、智能医疗等。

1.3 物联网发展现状

消费级IOT蓬勃发展,仍处于初级阶段

物联网通过相关设备将物与物、人联网。

(1)规模:全球物联网产业规模 2008 500亿美元的年增长 2018 年仅 1510 亿美元,复合年均增长率达到 11.7%。2017年,中国物联网产业规模达到 11500亿元,自 2011 2009-2017年进一步加速 复合年均增长率达到 26.我国物联网发展速度比全球平均水平快9%。

(2)渗透:全球物联网行业渗透率 2013、2017 分别达 预计2020年将超过12%和29%,增长一倍多 65%的企业和组织将应用物联网产品和解决方案。近年来,中国物联网市场规模不断扩大,2012年 3650 亿元增长到 2017 年的 11605 年复合增长率高达1亿元 25%。

2012-2017年中国物联网市场规模(亿元)

全球物联网渗透率的变化

消费物联网:仍处于初级阶段

消费级IOT预计快速增长。

(1)全球:2017全球消费水平IOT硬件销售额达到4859亿美元,同比增长299亿美元.5%,2015-2017 复合增速达 26.0%。2022 年销售额有望达到 15502 亿美元,2017-2022 复合年均增长率达到 26.1%。全球消费水平 IOT 市场规模呈现进一步加速的趋势。

(2)中国大陆: 2017 中国大陆消费水平 IOT 硬件销售额达到 1188 亿美元,同比增长 30.0%,2015-2017 复合增速达 28.9%。2022年销售额达到预期 3118 亿美元, 2017-2022 复合年均增长率达到 21.3%。2017年前,由于小米等公司的快速发展,中国的消费水平 IOT 2017年整体发展速度快于全球平均水平 年后在中国消费 IOT 全球消费水平仍保持快速发展 IOT 会发展得更快。(3)连接设备:全球消费级 IOT 终端数量 2017年达 49 亿个, 2015-2017 复合年均增长率达到 27.7%,预计 2022 年达 153亿个, 2017-2022 复合年均增长率达到 25.4%。 2017 中国消费级 IOT 世界上终端数量达到 26.5%,预计 2022 年比增加到 29.4%, 2017-2022 预计复合增长率将达到 28.2%。

全球消费级IOT市场规模:

中国消费级IOT市场规模:

全球及中国IOT终端数量:

2.1亿可控需求分析

2.1 需求概述

作为中间平台,亿可控对设备运行状况进行实时在线监控和预警,不做业务相关功能。

核心功能列表:

(1)报纸数据采集及指标分析 :整个系统的数据源是通过接收设备发送的报纸信息,在系统中定义主题和信息内容段的指标数据为过滤条件,从而对消息进行收集和分析。

​ (2)报警监控 : 通过和系统中定义的各种告警级别数据进行对比,一旦发现触发到告警级别的消息,就会通过和告警关联配置的webhook来将告警信息透传到其它系统

​ (3)GPS定位监控 :采集每台设备的GPS定位,并提供设备位置查询功能。

​ (4)数据看板 : 提供丰富的自定义数据看板。

2.2 业务架构图

从上图我们可以看到,真个系统从业务上分为6大功能模块:图形监控模块、数据详情展示模块、看板管理模块、设备管理模块、报警管理模块、系统管理模块。

2.3 核心业务描述

产品原型地址:

https://app.mockplus.cn/run/prototype/yYVLQlJ-YN6/JhE4uVilt/4nw_LQ8n7

详见资源提供的《亿可控PRD文档》

3.亿可控系统架构

3.1 系统架构图

整个系统的技术架构图如下:

预制数据将放入MySQL里进行存储,设备上报的指标数据包括告警数据将存入influxDB中,设备的地理位置信息数据存入到ES中以便后期搜索。为了提高系统的运行稳定性,有些频繁访问的数据储存在redis中,因为考虑到设备上报的数据是非常频繁的,如果单单只依靠MySQL数据库的话,会很容易将MySQL服务器的CPU的占用率搞到100%,从而会引发整个系统的崩溃无法使用。

一些基本的配置放入到了consul的配置中心,考虑到系统的横向扩展能力,将整个系统基于Consul做注册中心来搭组建一个微服务。

3.2 数据库设计

mysql数据库有5个表:

管理员表tb_admin

列名 数据类型 说明
id int 表主键id,自增
login_name varchar(50) 登录账号
password varchar(60) 密码
type tinyint 类型 1:超级管理员 2:普通用户 目前作为保留字段
board varchar(50) 看板列表

指标配置表tb_quota

列名 数据类型 说明
id int 表主键id
name varchar(50) 指标名称
unit varchar(20) 指标单位
subject varchar(50) 报文主题
value_key varchar(50) 指标值字段
sn_key varchar(50) 设备识别码字段
webhook varchar(1000) web钩子
value_type varchar(10) 指标字段类型,Double、Inteter、Boolean
reference_value varchar(100) 参考值

报警配置表tb_alarm

列名 数据类型 说明
id int 表主键id,自增
name varchar(50) 报警指标名称
quota_id int 关联指标名称
operator varchar(10) 运算符
threshold int 报警阈值
level int 报警级别 1:一般 2:严重
cycle int 沉默周期(以分钟为单位)
webhook varchar(1000) web钩子地址

面板配置表tb_board

列名 数据类型 说明
id int 表主键id,自增
admin_id int 管理员id
name varchar(50) 看板名称
quota varchar(100) 指标
device varchar(100) 设备
system tinyint 是否是系统看板
disable tinyint 是否不显示

GPS配置表tb_gps

列名 数据类型 说明
id bigint 表主键id
subject varchar(50) 报文主题
sn_key varchar(50) 设备识别码字段
type tinyint 类型(单字段、双字段)
value_key varchar(50) 经纬度字段
separation varchar(10) 经纬度分隔符
longitude varchar(20) 经度字段
latitude varchar(20) 维度字段

4.基础代码解析

4.1 环境准备

4.1.1 加载虚拟机镜像

使用课程配套的虚拟机镜像。

网络连接建议使用NAT模式。

本课程讲义中提供的代码,192.168.200.128为宿主机IP,如果你加载镜像后不是此IP请自行调整。

已安装好docker环境,并已拉取了所需镜像,开箱即用。

4.1.2 MySQL建库建表

连接虚拟机的mysql ,用户名root ,密码root123

创建数据库ykk,创建表

create table if not exists tb_admin
(
	id int auto_increment
		primary key,
	login_name varchar(50) null comment '登录名',
	password varchar(60) null comment '密码',
	type tinyint null comment '类型 1超级管理员 0普通用户',
	board varchar(50) null comment '看板'
);

create table if not exists tb_alarm
(
	id int auto_increment comment 'id'
		primary key,
	name varchar(50) null comment '报警名称',
	quota_id int null comment '指标id',
	operator varchar(10) null comment '运算符',
	threshold int null comment '报警阈值',
	level int null comment '报警级别 1一般 2严重',
	cycle int null comment '沉默周期(分钟)',
	webhook varchar(1000) null comment 'web钩子',
	constraint tb_alarm_name_uindex
		unique (name)
);

create table if not exists tb_board
(
	id int auto_increment comment 'id'
		primary key,
	admin_id int default 1 null comment '管理员id',
	name varchar(50) null comment '看板名称',
	quota varchar(100) default '0' null comment '指标(趋势时设置)',
	device varchar(100) null comment '设备(累计)',
	`system` tinyint default 0 null comment '是否是系统看板',
	disable tinyint default 0 null comment '是否不显示',
	constraint tb_board_name_uindex
		unique (name)
);


create table if not exists tb_gps
(
	id int not null comment 'id'
		primary key,
	subject varchar(50) null comment '主题',
	sn_key varchar(50) null comment '设备识别码字段',
	single_field tinyint null comment '类型(单字段、双字段)',
	value_key varchar(50) null comment '经纬度字段',
	separation varchar(10) null comment '经纬度分隔符',
	longitude varchar(20) null comment '经度字段',
	latitude varchar(20) null comment '维度字段',
	constraint tb_gps_subject_uindex
		unique (subject)
);

create table if not exists tb_quota
(
	id int auto_increment comment 'id'
		primary key,
	name varchar(50) null comment '指标名称',
	unit varchar(20) null comment '指标单位',
	subject varchar(50) null comment '报文主题',
	value_key varchar(50) null comment '指标值字段',
	sn_key varchar(50) null comment '设备识别码字段',
	webhook varchar(1000) null comment 'web钩子',
	value_type varchar(10) null comment '指标字段类型,Double、Inteter、Boolean',
	reference_value varchar(100) null comment '参考值',
	constraint tb_quota_name_uindex
		unique (name)
);

4.1.3 Consul添加配置

(1)进入Consul

打开浏览器,输入地址 http://192.168.200.128:8500/

(2)创建配置 key为 config/backend-service/data value如下

spring: 
  datasource:
    url: jdbc:mysql://192.168.200.128:3306/ykk?useUnicode=true&autoReconnect=true&autoReconnectForPools=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: root123
    driver-class-name: com.mysql.jdbc.Driver
  redis:
    host: 192.168.200.128
    port: 6379
    database: 0
    lettuce:
      pool:
        max-active: 10
        max-wait: -1
        max-idle: 5
        min-idle: 1
      shutdown-timeout: 100
    timeout: 1000
    password:  

4.2 工程结构解析

项目主体框架截图如下:

目前项目主要分为两个部分:ykk-common和ykk-backend。

ykk-common模块存放系统的一些基础通用性定义,包括通用异常定义、数据库联接定义、还有一些常量定义。

ykk-backend模块是我们后台逻辑的实现代码,里面按照具体的功能实现拆分到了具体的包里。

4.3 核心代码解析

4.3.1 用户登录与JWT校验

(1)用户登录业务逻辑

package com.yikekong.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.yikekong.entity.AdminEntity;
import com.yikekong.mapper.AdminMapper;
import com.yikekong.service.AdminService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper,AdminEntity> implements AdminService{ 
        
    @Override
    public Integer login(String loginName, String password) { 
        
        if(Strings.isNullOrEmpty(loginName) || Strings.isNullOrEmpty(password)){ 
        
            return -1;
        }
        QueryWrapper<AdminEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(AdminEntity::getLoginName,loginName);
        AdminEntity adminEntity = this.getOne(queryWrapper);
        if(adminEntity == null)
            return -1;

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if(passwordEncoder.matches(password,adminEntity.getPassword())){ 
        
            return adminEntity.getId();
        }

        return -1;
    }
}

(2)用户登录控制器类

@RestController
public class AdminController{ 
        
    @Autowired
    private AdminService adminService;

    @PostMapping("/login")
    public LoginResultVO login(@RequestBody AdminVO admin){ 
        
        LoginResultVO result = new LoginResultVO();
        Integer adminId = adminService.login(admin.getLoginName(),admin.getPassword());
        if(adminId < 0){ 
        
            result.setLoginSuccess(false);
            return result;
        }
        result.setAdminId(adminId);
        String token = JwtUtil.createJWT(adminId);
        result.setToken(token);
        result.setLoginSuccess(true);

        return result;
    }
}

(3)登录校验

httpfilter包里AuthFilter是我们jwt的过滤器,主要来校验jwt token,该类的实现如下:

package com.yikekong.httpfilter;


import org.elasticsearch.common.Strings;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@WebFilter(urlPatterns = "/*",filterName = "authFilter")
public class AuthFilter implements Filter{ 
        
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
        
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        HttpServletResponse resp = (HttpServletResponse)servletResponse;
        String path = ((HttpServletRequest) servletRequest).getServletPath();
        //如果访问的是login接口,不进行jwt token校验
        if(path.equals("/login")){ 
        
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        String authToken = ((HttpServletRequest) servletRequest).getHeader("Authorization");
        //如何header中不存在Authorization的值,直接返回校验失败
        if(Strings.isNullOrEmpty(authToken)){ 
        
            ((HttpServletResponse) servletResponse).setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }

        try { 
        
            JwtUtil.parseJWT(authToken);
        } catch (Exception e) { 
        
            //jwt校验失败,返回
            ((HttpServletResponse) servletResponse).setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

4.3.2 指标管理-创建指标

QuotaController的create方法用于创建指标

/** * 创建指标 * @param vo * @return */
@PostMapping
public boolean create(@RequestBody QuotaVO vo){ 
        
    QuotaEntity quotaEntity = new QuotaEntity();
    BeanUtils.copyProperties(vo,quotaEntity);
    return quotaService.save(quotaEntity);
}

此方法接收的vo类,是前端的封装视图对象。有很多时候,前端传递过来的数据与我们后端数据库对应的不一定完全一致,所以我们通常的做法是创建一个单独的vo类,用于与前端进行数据的传输。这样如果前端传递的数据对象发送结构变化,并不会影响到后端数据库结构。

BeanUtils.copyProperties(vo,quotaEntity); 用于对象数据的拷贝,如果两个对象有相同的属性,会自动复制属性,这样可以避免在代码中出现大量的setter方法。

5. 设备管理

5.1 设备添加

5.1.1 需求分析

在亿可控系统中,我们不能也不需要从系统界面中添加设备。设备的添加,是在亿可控接收到设备发过来的报文,解析后保存的。由于物联网类的应用所使用的设备数量可能非常庞大,而对这部分数据的读写频率又很频繁,所以我们使用elasticsearch作为设备的数据库。

5.1.2 索引库结构设计

设备库 device

列名 数据类型 说明
deviceId keyword 设备编号
alarm boolean 是否告警
alarmName keyword 告警名称
level integer 告警级别
online boolean 是否在线
status boolean 开关
tag keyword 标签

5.1.3 代码实现

(1)创建索引库(打开kibana创建 http://192.168.200.128:5601/)

PUT /devices
{ 
        
    "mappings": { 
        
        "properties": { 
        
            "deviceId": { 
        
                "type" 

相关文章