主頁 >  其他 > JavaEE精英進階課學習筆記《博學谷》

JavaEE精英進階課學習筆記《博學谷》

2021-08-11 08:20:28 其他

第1章 億可控系統分析與設計

DownloadJavaEE精英進階課

提qu碼:xb2k

學習目標

  • 了解物聯網應用領域及發展現狀
  • 能夠說出億可控的核心功能
  • 能夠畫出億可控的系統架構圖
  • 能夠完成億可控環境的準備并了解億可控的功能結構
  • 完成設備管理相關功能的開發

1.物聯網行業分析

1.1 什么是物聯網

物聯網(英文:Internet of Things,縮寫:IoT)起源于傳媒領域,是資訊科技產業的第三次革命,物聯網是指通過資訊傳感設備,按約定的協議,將任何物體與網路相連接,物體通過資訊傳播媒介進行資訊交換和通信,以實作智能化識別、定位、跟蹤、監管等功能, V(cmL46679910)

在物聯網應用中有三項關鍵技術,分別是感知層、網路傳輸層和應用層,

中國式物聯網定義:

最簡潔明了的定義:物聯網(Internet of Things)是一個基于互聯網、傳統電信網等資訊承載體,讓所有能夠被獨立尋址的普通物理物件實作互聯互通的網路,它具有普通物件設備化、自治終端互聯化和普適服務智能化3個重要特征,

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-M9buAq7M-1628513245731)(images/1-1.png)]

上圖中出現了四個概念,我們這里分別解釋一下:

兩化融合是資訊化和工業化的高層次的深度結合, 是指以資訊化帶動工業化、以工業化促進資訊化,走新型工業化道路;兩化融合的核心就是資訊化支撐,追求可持續發展模式,

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年傾力打造的中國目前首家 一款集網約專車、智慧停車、汽車租賃、汽車金融,以及其他智慧出行領域創新商業模式于一體的高端智慧交通整體解決方案 [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 分別達 12%、29%,提升一倍多,預計2020年有超過 65%企業和組織將應用物聯網產品和方案,近年來,我國物聯網市場規模不斷擴大,2012年的 3650 億元增長到 2017 年的 11605 億元,年復合增長率高達 25%,

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KRD9bsWJ-1628513245734)(images/1-2.png)]

2012-2017年我國物聯網市場規模(億元)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jLhCUwAK-1628513245737)(images/1-3.png)]

全球物聯網滲透率變化

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VdeyotnC-1628513245739)(images/1-4.png)]

消費級物聯網:仍處于初級階段

消費級IOT預計快速增長,

(1)全球:2017全球消費級IOT硬體銷售額達4859億美元,同比增長29.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市場規模:V(cmL46679910)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BrxpSZPn-1628513245741)(images/1-5.png)]
中國消費級IOT市場規模:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jB5mJXP5-1628513245744)(images/1-6.png)]
全球及中國IOT終端數量:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1f4gaz10-1628513245746)(images/1-7.png)]

2.億可控需求分析

2.1 需求概述

? 億可控作為一個中臺,對設備運行狀況進行實時在線監測、預警,不做業務相關的功能,

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-NTNA0JHO-1628513245749)(images/1-14.png)]

? 核心功能串列:

? (1)報文資料采集與指標決議 :整個系統的資料來源是通過接收設備發送過來的報文訊息,在系統中定義主題和訊息內容欄位的指標資料為過濾條件,從而對訊息進行收集和分析,

? (2)報警監控 : 通過和系統中定義的各種告警級別資料進行對比,一旦發現觸發到告警級別的訊息,就會通過和告警關聯配置的webhook來將告警資訊透傳到其它系統

? (3)GPS定位監控 :采集每臺設備的GPS定位,并提供設備位置查詢功能,

? (4)資料看板 : 提供豐富的自定義資料看板,

2.2 業務架構圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qCiUBa83-1628513245752)(images/1-19.png )]

從上圖我們可以看到,真個系統從業務上分為6大功能模塊:圖形監控模塊、資料詳情展示模塊、看板管理模塊、設備管理模塊、報警管理模塊、系統管理模塊,

2.3 核心業務描述

產品原型地址:

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

詳見資源提供的《億可控PRD檔案》

3.億可控系統架構

3.1 系統架構圖

整個系統的技術架構圖如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lw4risdz-1628513245754)(images/1-10.png)]

預制資料將放入MySQL里進行存盤,設備上報的指標資料包括告警資料將存入influxDB中,設備的地理位置資訊資料存入到ES中以便后期搜索,為了提高系統的運行穩定性,有些頻繁訪問的資料儲存在redis中,因為考慮到設備上報的資料是非常頻繁的,如果單單只依靠MySQL資料庫的話,會很容易將MySQL服務器的CPU的占用率搞到100%,從而會引發整個系統的崩潰無法使用,

一些基本的配置放入到了consul的配置中心,考慮到系統的橫向擴展能力,將整個系統基于Consul做注冊中心來搭組建一個微服務,

3.2 資料庫設計

mysql資料庫有5個表:

管理員表tb_admin

列名資料型別說明
idint表主鍵id,自增
login_namevarchar(50)登錄賬號
passwordvarchar(60)密碼
typetinyint型別 1:超級管理員 2:普通用戶 目前作為保留欄位
boardvarchar(50)看板串列

指標配置表tb_quota

列名資料型別說明
idint表主鍵id
namevarchar(50)指標名稱
unitvarchar(20)指標單位
subjectvarchar(50)報文主題
value_keyvarchar(50)指標值欄位
sn_keyvarchar(50)設備識別碼欄位
webhookvarchar(1000)web鉤子
value_typevarchar(10)指標欄位型別,Double、Inteter、Boolean
reference_valuevarchar(100)參考值

報警配置表tb_alarm

列名資料型別說明
idint表主鍵id,自增
namevarchar(50)報警指標名稱
quota_idint關聯指標名稱
operatorvarchar(10)運算子
thresholdint報警閾值
levelint報警級別 1:一般 2:嚴重
cycleint沉默周期(以分鐘為單位)
webhookvarchar(1000)web鉤子地址

面板配置表tb_board

列名資料型別說明
idint表主鍵id,自增
admin_idint管理員id
namevarchar(50)看板名稱
quotavarchar(100)指標
devicevarchar(100)設備
systemtinyint是否是系統看板
disabletinyint是否不顯示

GPS配置表tb_gps

列名數據型別說明
idbigint表主鍵id
subjectvarchar(50)報文主題
sn_keyvarchar(50)設備識別碼欄位
typetinyint型別(單欄位、雙欄位)
value_keyvarchar(50)經緯度欄位
separationvarchar(10)經緯度分隔符
longitudevarchar(20)經度欄位
latitudevarchar(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)
);
==V(cmL46679910)==
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 工程結構決議

專案主體框架截圖如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Pjp9PypR-1628513245757)(images/1-12.png)]

目前專案主要分為兩個部分: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方法用于創建指標
V(cmL46679910)

/**
 * 創建指標
 * @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

列名資料型別說明
deviceIdkeyword設備編號
alarmboolean是否告警
alarmNamekeyword告警名稱
levelinteger告警級別
onlineboolean是否在線
statusboolean開關
tagkeyword標簽

5.1.3 代碼實作

(1)創建索引庫(打開kibana創建 http://192.168.200.128:5601/)

PUT /devices
{
    "mappings": {
        "properties": {
            "deviceId": {
                "type": "keyword"
            },
            "alarm": {
                "type": "boolean"
            },
            "alarmName": {
                "type": "keyword"
            },
            "level": {
                "type": "integer"
            },
            "online": {
                "type": "boolean"
            },
            "status": {
                "type": "boolean"
            },
            "tag": {
                "type": "keyword"
            }
        }
    }
}

(2)pom.xml添加配置

<!--es相關依賴-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.7.1</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.7.1</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>7.7.1</version>
</dependency>
<!--es相關依賴結束-->

(3)在組態檔中添加配置,以下配置添加到spring節點下


  elasticsearch:
    rest:
      uris: http://192.168.200.128:9200

(4)創建包com.yikekong.dto , 創建用于封裝設備的DTO類

package com.yikekong.dto;

import lombok.Data;

import java.io.Serializable;

/**
 * 設備DTO
 */
@Data
public class DeviceDTO implements Serializable {

    private String deviceId;//設備編號

    private Boolean alarm;// 是否告警

    private String alarmName;//告警名稱

    private Integer level;//告警級別

    private Boolean online;//是否在線

    private String tag;// 標簽

    private Boolean status;//開關狀態
        
}

(5)創建com.yikekong.es包,包下創建ESRepository類,并撰寫添加設備的方法

package com.yikekong.es;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.yikekong.dto.DeviceDTO;
import com.yikekong.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;

@Component
@Slf4j
public class ESRepository{

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 添加設備
     * @param deviceDTO
     */
    public  void addDevices(DeviceDTO deviceDTO){
        if(deviceDTO==null ) return;
        if(deviceDTO.getDeviceId()==null) return;
        IndexRequest request=new IndexRequest("devices");
        try {
            String json = JsonUtil.serialize(deviceDTO);
            Map map = JsonUtil.getByJson(json, Map.class);
            request.source(map);
            request.id(deviceDTO.getDeviceId());
            restHighLevelClient.index(request, RequestOptions.DEFAULT);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("設備添加發生例外");
        }
    }
}

5.1.4 單元測驗

撰寫單元測驗

import com.yikekong.YkkApplication;
import com.yikekong.dto.DeviceDTO;
import com.yikekong.es.ESRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = YkkApplication.class)
@RunWith(SpringRunner.class)
public class EsTest {

    @Autowired
    private ESRepository esRepository;

    @Test
    public void testAdd(){
        DeviceDTO deviceDTO=new DeviceDTO();
        deviceDTO.setDeviceId("123456");
        deviceDTO.setStatus(true);
        deviceDTO.setAlarm(false);
        deviceDTO.setLevel(0);
        deviceDTO.setAlarmName("");
        deviceDTO.setOnline(true);
        deviceDTO.setTag("");
        esRepository.addDevices(deviceDTO);
    }
}

查詢資料,驗證運行結果

GET devices/_search
{
  "query": {
    "match_all": {}
  }
}

5.2 根據設備ID查詢設備

5.2.1 需求分析

根據id從elasticsearch中查詢設備資訊,在之后的報文決議的邏輯中需要呼叫此方法來實作設備的查詢,

5.2.2 代碼實作

ESRepository類添加方法

/**
 * 根據設備id 查詢設備
 * @param deviceId  設備id
 * @return
 */
public DeviceDTO searchDeviceById(String deviceId){
    SearchRequest searchRequest=new SearchRequest("devices");
    SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.termQuery("_id",deviceId));
    searchRequest.source(searchSourceBuilder);
    try {
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        long hitsCount = hits.getTotalHits().value;
        if(hitsCount<=0) return null;
        DeviceDTO deviceDTO=null;
        for(SearchHit hit:hits){
            String hitResult = hit.getSourceAsString();
            deviceDTO=JsonUtil.getByJson(hitResult,DeviceDTO.class  );
            deviceDTO.setDeviceId(deviceId);
            break;
        }
        return deviceDTO;

    } catch (IOException e) {
        e.printStackTrace();
        log.error("查詢設備例外");
        return null;
    }
}

5.2.3 單元測驗

撰寫單元測驗方法,驗證代碼是否正確

@Test
public void testSearchById(){

    DeviceDTO deviceDTO = esRepository.searchDeviceById("123456");
    try {
        String json = JsonUtil.serialize(deviceDTO);
        System.out.println(json);

    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }

}

5.3 設定設備狀態

5.3.1 需求分析

當我們不需要接收某設備的報文,可以將其關閉,已經關閉的設備對接收的報文指標不做任何處理,

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-A3vpfMkU-1628513245760)(images/1-15.png)]

5.3.2 API 介面

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AMfqrtGl-1628513245764)(images/1-16.png)]

5.3.3 代碼實作

(1)ESRepository類添加方法實作對設備的開與關,

/**
 * 更新設備狀態
 * @param deviceId
 * @param status
 * @return
 */
public boolean updateStatus(String deviceId,Boolean status){
    UpdateRequest updateRequest=new UpdateRequest("devices",deviceId)
            .doc( "status",status );
    try {
        restHighLevelClient.update( updateRequest,RequestOptions.DEFAULT );
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        log.error("更新設備狀態出錯");
        return false;
    }
}

(2)DeviceService新增方法定義

/**
 * 更改設備狀態
 * @param deviceId
 * @param status
 * @return
 */
boolean setStatus(String deviceId, Boolean status);

DeviceServiceImpl實作方法

@Autowired
private ESRepository esRepository;

@Override
public boolean setStatus(String deviceId, Boolean status) {
    DeviceDTO deviceDTO = findDevice(deviceId);
    if( deviceDTO==null ) return false;
    return esRepository.updateStatus(deviceId,status);
}

/**
 * 根據設備id查詢設備
 * @param deviceId
 * @return
 */
private DeviceDTO findDevice(String deviceId){
    DeviceDTO deviceDTO = esRepository.searchDeviceById(deviceId);
    return deviceDTO;
}

(3)DeviceController新增方法

/**
 * 設定狀態的介面
 * @param deviceVO
 * @return
 */
@PutMapping("/status")
public boolean setStatus(@RequestBody DeviceVO deviceVO){
    return deviceService.setStatus(deviceVO.getSn(),deviceVO.getStatus());
}

5.3.4 介面測驗

(1)運行YkkApplication啟動工程

(2)測驗介面,為了方便測驗,我們采用vscode的Rest Client插件來進行測驗,腳本是課程提供的“資料\測驗\yikekong.http” ,用vscode打開,找到以下腳本

####修改設備狀態########
PUT   http://{{hostname}}:{{port}}/device/status HTTP/1.1
Authorization: {{Authorization}}
Content-Type: {{contentType}}

{
    "sn":"123456",
    "status":true
}

我們可以修改status值后 點擊 Send Request 鏈接進行測驗

5.4 設定設備標簽

5.4.1 需求分析 V(cmL46679910)

我們為了方便之后對設備進行查詢,我們可以對每個設備設定一個或多個標簽,在前端界面上沒有更新設備標簽的功能,此功能只對外部系統提供呼叫的介面,

5.4.2 代碼實作

(1)ESRepository類添加方法

/**
 * 更新設備標簽
 * @param deviceId
 * @param tags
 * @return
 */
public boolean updateDeviceTag(String deviceId,String tags){
    UpdateRequest updateRequest=new UpdateRequest("devices",deviceId)
            .doc( "tag",tags );
    try {
        restHighLevelClient.update( updateRequest,RequestOptions.DEFAULT );
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        log.error("更新設備標簽出錯");
        return false;
    }
}

(2)DeviceService新增方法

/**
 * 更新設備標簽
 * @param deviceId
 * @param tags
 * @return
 */
boolean updateTags(String deviceId,String tags);

DeviceServiceImpl實作方法

@Override
public boolean updateTags(String deviceId, String tags) {
    DeviceDTO deviceStatus = findDevice(deviceId);
    if(deviceStatus == null) return false;
    esRepository.updateDeviceTag(deviceId,tags);
    return true;
}

(3)DeviceController新增方法

/**
 * 設定標簽的介面
 * @param deviceVO
 * @return
 */
@PutMapping("/tags")
public boolean setTags(@RequestBody DeviceVO deviceVO){
    return deviceService.updateTags(deviceVO.getSn(),deviceVO.getTags());
}

(4)AuthFilter類的doFilter新增代碼,對tags放行

//tag介面不校驗token
if(path.contains("/device/tags")){
	filterChain.doFilter(servletRequest, servletResponse);
	return;
}

5.4.3 介面測驗

(1)啟動工程

(2)找到以下腳本,進行測驗

####設定設備標簽############
PUT   http://{{hostname}}:{{port}}/device/tags HTTP/1.1
Content-Type: {{contentType}}

{
    "sn":"123456",
    "tags":"學校"
}

5.5 更新設備告警資訊

5.5.1 需求分析

當設備發送過來的報文中的指標資訊達到告警級別,我們應該更新elasticsearch中的更新設備告警資訊(是否告警、告警級別、告警名稱)

5.5.2 代碼實作

ESRepository類添加方法

/**
 * 更新設備告警資訊
 * @param deviceDTO
 * @return
 */
public boolean updateDevicesAlarm(DeviceDTO deviceDTO){
    UpdateRequest updateRequest=new UpdateRequest("devices",deviceDTO.getDeviceId())
            .doc(   "alarm",deviceDTO.getAlarm(),//是否告警
                    "level",deviceDTO.getLevel(),//告警級別
                    "alarmName",deviceDTO.getAlarmName() );//告警名稱
    try {
        restHighLevelClient.update( updateRequest,RequestOptions.DEFAULT );
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        log.error("更新設備告警資訊出錯");
        return false;
    }
}

5.5.3 單元測驗

撰寫單元測驗,在TestES中新增測驗方法

@Test
public void testAlarm(){
    DeviceDTO deviceDTO=new DeviceDTO();
    deviceDTO.setDeviceId("123456");
    deviceDTO.setAlarm(true);
    deviceDTO.setLevel(1);
    deviceDTO.setAlarmName("溫度過高");

    esRepository.updateDevicesAlarm(deviceDTO);

}

5.6 更新在線狀態

5.6.1 需求分析

在線狀態是指這個設備是否在線,如果設備存在網路故障就會導致設備離線,億可控系統可以監測設備的在線和離線狀態

5.6.2 代碼實作

我們這里需要在ESRepository類添加方法用于更新在線狀態,

/**
 * 更新在線狀態
 * @param deviceId
 * @param online
 * @return
 */
public boolean updateOnline(String deviceId,Boolean online){
    UpdateRequest updateRequest=new UpdateRequest("devices",deviceId)
            .doc( "online",online );
    try {
        restHighLevelClient.update( updateRequest,RequestOptions.DEFAULT );
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        log.error("更新在線狀態出錯");
        return false;
    }
}

5.6.3 單元測驗

撰寫單元測驗,在TestES中新增測驗方法

@Test
public void testOnline(){
    esRepository.updateOnline("123456",false);
}

5.7 分頁查詢設備

5.7.1 需求分析

有兩個頁面需要實作分頁查詢設備

(1)設備管理,如下圖效果,需要設備編號、標簽作為查詢條件分頁查詢

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-M9xsfZNI-1628513245768)(images/1-13.png)]

(2)設備詳情,如下圖效果,需要設備狀態、標簽、設備編號作為查詢條件分頁查詢

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-E3RFMZf2-1628513245771)(images/1-18.png)]

設備詳情頁比設備管理多了一個“設備狀態”的查詢條件,設備狀態有四個值:在線(0)、離線(1)、一般告警(2)、嚴重告警(3) ,

為了不讓代碼冗余,我們這兩個功能可以用同一個方法實作,

5.7.2 代碼實作

ESRepository類添加方法

/**
 * 分頁查詢設備
 * @param page 頁碼
 * @param pageSize 頁大小
 * @param deviceId 設備編號
 * @param tags 標簽
 * @param state 狀態
 * @return
 */
public Pager<DeviceDTO> searchDevice(Long page,Long pageSize,String deviceId,String tags,Integer state){

    SearchRequest searchRequest=new SearchRequest("devices");
    SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
    //條件查詢
    BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
    //設備編號
    if(!Strings.isNullOrEmpty(deviceId)) {
        boolQueryBuilder.must(QueryBuilders.wildcardQuery("deviceId", deviceId + "*"));
    }
    //標簽
    if(!Strings.isNullOrEmpty(tags) ){
        boolQueryBuilder.must(QueryBuilders.wildcardQuery("tag","*"+tags+"*"));
    }
    //狀態(在線狀態和告警狀態)  0:在線  1:離線  2:一般告警  3:嚴重告警
    if(state!=null){
        if(state.intValue()==0){
            boolQueryBuilder.must( QueryBuilders.termQuery("online",true));
        }
        if(state.intValue()==1){
            boolQueryBuilder.must( QueryBuilders.termQuery("online",false));
        }
        if(state.intValue()==2){
            boolQueryBuilder.must( QueryBuilders.termQuery("level",1));
        }
        if(state.intValue()==3){
            boolQueryBuilder.must( QueryBuilders.termQuery("level",2));
        }
    }
    sourceBuilder.query(boolQueryBuilder);
    //分頁
    sourceBuilder.from( (page.intValue()-1)*pageSize.intValue()  );
    sourceBuilder.size( pageSize.intValue() );
    sourceBuilder.trackTotalHits(true);

    //排序
    sourceBuilder.sort("level", SortOrder.DESC);//告警級別高的排前面
    searchRequest.source(sourceBuilder);
    try {
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        List<DeviceDTO> devices= Lists.newArrayList();
        for(SearchHit hit: searchHits){
            String hitResult = hit.getSourceAsString();
            DeviceDTO deviceDTO = JsonUtil.getByJson(hitResult, DeviceDTO.class);
            devices.add(deviceDTO);
        }
        Pager<DeviceDTO> pager=new Pager<>(   searchResponse.getHits().getTotalHits().value,pageSize );
        pager.setItems(devices);
        return  pager;
    } catch (IOException e) {
        e.printStackTrace();
        log.error("查詢設備失敗");
        return null;
    }
}

(2)DeviceService新增方法定義

/**
 * 搜索設備
 * @param page
 * @param pageSize
 * @param sn
 * @param tag
 * @return
 */
Pager<DeviceDTO> queryPage(Long page, Long pageSize, String sn, String tag, Integer status);

DeviceServiceImpl實作方法

@Override
public Pager<DeviceDTO> queryPage(Long page, Long pageSize, String sn, String tag, Integer status) {
    return  esRepository.searchDevice(page,pageSize,sn,tag,status);
}

(3)DeviceController新增方法

/**
 * 分頁搜索設備
 * @param page
 * @param pageSize
 * @param sn
 * @param tag
 * @return
 */
@GetMapping
public Pager<DeviceDTO> findPage(@RequestParam(value = "page",required = false,defaultValue = "1") Long page,
                                 @RequestParam(value = "pageSize",required = false,defaultValue = "10") Long pageSize,
                                 @RequestParam(value = "sn",required = false) String sn,
                                 @RequestParam(value = "tag",required = false) String tag){
    return deviceService.queryPage(page,pageSize,sn,tag,null);
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293039.html

標籤:其他

上一篇:從Angular 轉向VUE,再做一次菜鳥

下一篇:能耗管理系統-物聯網之(一)mysql使用總結

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more