如何基于three.js(webgl)引擎架构,研发一套通过配置就能自动生成的3D机房系统
序:
这几年观察下来,大部分做物联网三维可视化解决方案的企业或个人, 基本都绕不开3D机房。包括前面也讲过这样的案例《使用webgl(three.js)创建自动化抽象化3D机房,3D机房模块详细介绍(抽象版一)》 《 使用webgl(three.js)创建科技版3D机房,3D机房微模块详细介绍(升级版三)—— 1》
随着技术的快速发展,机房的数量和规模也在不断扩大。然而,传统的数据中心管理方式已经无法满足现代社会的需求。在这种情况下,3D机房数据中心应运而生。
顾名思义,三维机房数据中心是指利用三维仿真技术,将数据中心的空间信息、设备信息、人员流动信息等各类信息集成在三维模型中,实现数据中心的全面可视化。这种新型的数据中心管理方式,能够提高管理效率,降低运营成本,提升数据中心的可靠性。
但是,三维机房解决方案已经发展了好多年,逃不开建模,数据连接,个性化定制。一个机房项目,开发周期长,研发成本高。不说如何颠覆一下这部分行业应用,也得想想如何提升一下效率。
综述,低代码模式的三维机房解决方案呼之欲出。当然还是基于three.js(webgl)引擎架构
我们还是闲话少叙,切入正题。
前言:
首先,我们要确定目标与需求。
目标:低代码生成三维机房系统。
全套完备的三维数据中心系统,目标任务过于繁重,所以先得将目标切割,先完成低代码模式下的单个机房或者是微模块的前端三维方案。这就符合了自我效能理论,分割事务,及时得到正向反馈,不断完成小目标,看到成效,最终才能做出结果。
需求:通过上面的目标分割,我们可以简单概述出需求。简单一句话,通过配置,快速生成3D机房,包括其常用的业务逻辑。
这里我们明确了包含常用业务逻辑,而个性化特殊化的业务需求我们可以在完成这部分后,基于现有系统做叠加与拓展。为了方便拓展,先用简易系统要考虑到合理性与延续性。
综上所述,我们要做一个通过简单配置即可自动生成一个3D机房前端系统。后续我们再通过做一个工具,通过工具拖拉拽来代替写配置这一步。
一、效果展示
1.1、机房效果
通过简单配置生成一个带有微模块、单排柜以及动环设备的机房模型
根据数据自动生成机柜内部设备
1.2、json配置
分析行业需求,提炼配置信息
房间建筑:长宽高属性,以及门窗属性。这里必须且必要省掉墙的皮肤属性、不规则房间特性等等
设备:类型、位置,尺寸、关联数据id、这里要放弃设备细节。考虑的越多,越不容易完成目标
通过上面分析,我们可以基本得出一个简单的配置信息
1.2.1、建筑房间配置:
{
"type": "wall",
"name": "wall_4", //名称
"size": {
"x": 8000, //墙长度
"z": 100, //墙厚度
"y": 1000 //墙体高度
}, //墙的起始点位置
"startPosition": { //墙体的起始位置 默认是墙体的左下角
"x": -4000,
"y": 0,
"z": 2700
},
"doorHoles": [ //门
{
"id": "door_001",//门禁设备id
"type": 2, //0 x方向单门 1 x反方向单门 2 双门 3表示窗户洞
"start": 400, //相对于尺寸参数的x 离0多长 比如400 表示门洞离x 0点400
"width": 600, //门洞宽
"height": 700, //门洞高
"thickness": 40 //门厚度
},
{
"type": 3,
"start": 2600,
"width": 2000,
"height": 700,
"rideHeight": 100, //窗户离墙的底边高度
"thickness": 10 //窗的厚度
}
],
},
1.2.2、机柜配置
a、冷通道配置
{
"id": "101", //冷通道id 唯一
"type": "minRoom", //冷通道类型
"dataId": "101", //数据id 唯一
"position": { //冷通道位置 是指冷通道中心点在场景中的位置
"x": -2000,
"y": 0,
"z": 0
},
"rotationDir": "Z", //冷通道门对准的方向 X 表示坐标系x轴方向 Z表示坐标系z方向
"rackLength": 9, //冷通道单边机柜的个数
"children": [//冷通道内设备
{
"id": "1_1", //设备id
"type": "ljkt", //设备类型 取值范围:ljkt ltg rack 分别表示列间空调 列头柜 机柜
"dataId": "1_1", //数据id
"row": "1", //表示在冷通道哪一排 取值1或者2 在第一排 或者第二排
"col": "1", //表示在某排第几个
"width": 0.5//占用宽度比例
},
]
..........
},
b、单排柜配置
{
"id": "1_1", //机柜id 自定义 唯一性 建议跟数据库资产id保持一致
"type": "rack", //类型
"name": "rack_1_1", //机柜模型名称 唯一性
"dataId": "1_1", //机柜数据id 这里是指数据库存储的机柜资产id
"position": { //机柜位置 是指机柜中心点在场景中的位置
"x": -2550,
"y": 450,
"z": 1315
},
}
1.2.3、设备配置
{ //温湿度传感器
"type": "wdcgq",//设备类型
"id": "2",//id 保持全局唯一
"dataId": "wd1",//数据id
"position": {//模型中心点在场景中的位置
"x": 0,
"y": 1200,
"z": 0
},"scale": {//缩放 所有值不可为0
"x": 1,
"y": 1,
"z": 1
}
}
1.3、业务逻辑
上面的配置,机房模型已经生成,接下来就是基于模型与数据,生成功能逻辑
例如、利用率、温度云图、承重、告警等等
温度云图
承重、功耗
二、代码解析
2.1、合理封装
封装分为两部分
第一部分是模型封装,更加不同类型 以及属性生成模型/
例如:
* 创建普通地板
* @param {any} name 名称 floor
* @param {any} size 尺寸 {x:8000,z:5000,y:100} 长 宽 厚
* @param {any} CenterPosition 中心点位置 {x:0,z:-60,y:0}
* @param {any} rotation 旋转 {x:0,y:0,z:0} 角度用
*/
function createFloor(name, size, CenterPosition, rotation) {
......
return model;
}
/**
* 创建机房空气地板
* @param {any} name 名称 floor
* @param {any} size 尺寸 {x:8000,z:5000,y:100} 长 宽 厚
* @param {any} CenterPosition 中心点位置 {x:0,z:-60,y:0}
* @param {any} rotation 旋转 {x:0,y:0,z:0} 角度用
*/
function createDataCenterFloor(name, size, CenterPosition, rotation) { ......
return model;
}
/**
* 创建墙体
* @param {any} name 名称 wall_4
* @param {any} size 尺寸{x:8000,z:100,y:1000} 长 厚 高
* @param {any} startPosition 起始点位置 { "x": -4858.313, "y": 0, "z": 1264.35 }
* @param {any} doorHoles 门洞 [
{
type:2 ,//0 x方向单门 1 x反方向单门 2 双门 3窗户
start: 400,//相对于尺寸参数的x 离0多长 比如400 表示门洞离x 0点400
width:600,//门洞宽
height:700,//门洞高
thickness:40,//门洞厚度
rideHeight:100//离地高度
} ] * @param {any} rotation 旋转 {x:0,y:0,z:0}
*/
function createWall(name,type, size, startPosition, doorHoles, rotation) {
......
return buildwall;
}
第二部分是封装业务逻辑
将每部分业务逻辑单独封装到方法类中
例如:温度云图
//=======================================================温度=======================================================
function Tempture() { } Tempture.prototype.temptureSpaceState = 0;
//温度显示
Tempture.prototype.showTemptureMap = function (callBack) {
var _this = this;
if (_this.temptureSpaceState == 0) {
$("#backBtn").fadeIn();
layer.closeAll();
$("#toolbar").fadeOut();
_this.temptureSpaceState = 1;
_this.createHeatMapModels("temptureObj", callBack);
_this.hideAllMsg();
} else {
_this.temptureSpaceState = 0;
_this.hideAllTemptureMapObjs();
} }
Tempture.prototype.hideAllTemptureMapObjs = function () {
WT3DObj.destoryObj("temptureObj");
for (var i = 0; i < 20; i++) {
WT3DObj.destoryObj("temptureObj_" + i);
}
}
//创建热力图
Tempture.prototype.createHeatMapModels = function (name, callBack) {
var _this = this;
var scaleRate = 1;
if (roomConfig.buildData.baseConfig && roomConfig.buildData.baseConfig.normRackSize) {
scaleRate = roomConfig.buildData.baseConfig.normRackSize.width / 350;
}
_this.getHeatMapDataValue(function (_data) {
var modeljson = ...;
WT3DObj.InitAddObject(modeljson);
for (var i = 0; i < 10; i++) {
modeljson.position.y += (roomConfig.maxheight / 10) / scaleRate;
modeljson.name = name + "_" + i;
modeljson.values = _data.data;
WT3DObj.InitAddObject(modeljson);
}
}, callBack);
};
Tempture.prototype.getHeatMapDataValue = function (suc, callBack) {
webapi.getTemptureValue(function (result) { var heatMapData = {}; $.each(result, function (_reindex, _reobj) {
heatMapData["d_" + _reobj.id] = _reobj;
}); ...
var rdata = {
max: 100,
data: datas
};
if (suc) {
suc(rdata);
}
if (callBack) {
callBack(mtemp);
}
});
}
2.2、业务隔离
switch (id) {
case "div_btn_1"://异常设备
{
clearInterval(_this.alarmSetintervalIndex);
$("#btn_1").fadeTo(100, 1);
if ($("#btn_1").attr("title") == "告警监控") {
$("#btn_1").attr("title", "关闭告警闪动");
$("#btn_1").attr("src", "../img/pageimg2/ycsbclose.png");
modelBussiness.closeAlarm();
} else {
_this.flashAlarmBtn();
modelBussiness.startAlarm();
$("#btn_1").attr("src", "../img/pageimg2/ycsb.png");
$("#btn_1").attr("title", "告警监控");
}
}
break;
case "div_btn_2"://空间
{
modelBussiness.currentState = 22;
modelBussiness.showSpaceRate();
}
break;
case "div_btn_3"://U位
{
modelBussiness.currentState = 23;
modelBussiness.showUsageMap();
} break;
case "div_btn_4":
{
modelBussiness.currentState = 24;
modelBussiness.showTemptureMap();
}//温度 break;
case "div_btn_5"://承重
{
modelBussiness.currentState = 25;
modelBussiness.showBearing();
}
break;
case "div_btn_6"://功率
{
modelBussiness.currentState = 26;
modelBussiness.showEnergyRate();
}
break; }
});
三、主要难点
3.1、如何封装模型、提炼参数
- 选择关键参数:在模型中可能有很多参数,需要选择出一些关键的参数。例如,一些对模型性能影响较大的参数,或者一些表示模型复杂度的参数等。
- 定义计算方法:对于每个关键参数,需要定义一个计算方法。
- 提取参数:在模型预测时,需要提取出这些关键参数的值。
- 可视化参数:对于一些关键参数,可能还需要进行可视化,以便于理解和优化模型。
3.2、如何在生成的不同房间模型下,还能展现业务功能
- 定义业务功能:首先需要明确每个房间所需展现的业务功能
- 集成业务功能:将所定义的各项业务功能集成到三维房间模型中
- 交互式展示:将三维房间模型与业务功能进行交互式展示。
- 场景模拟:根据实际使用场景,模拟不同场景下的业务功能展示。
3.3、如何做数据分离
统一webapi数据文件,这里主要处理获取数据,数据过滤
/*
数据接口
*/
function WebAPI() {
this.serverHead = "";//idc/
this.roomid = getQueryString("room") ? getQueryString("room") : "1";
this.CabInfosCache = null;//机柜数据缓存
this.OtherDevsCache = null;//所有设备缓存
this.ServerDevsCache = {};//所有设备缓存
this.AllDevsCache = null;//所有设备缓存
this.alarmCache = [];//告警缓存
this.modelAlarmCache = {};//模型对应告警缓存
this.wsSocket = null;
//告警闪动对应的颜色
this.alarmColors = {
"L1": 0xff0000,
"L2": 0xff6600,
"L3": 0xffff00,
"L4": 0x0096ff,
}
this.urls = {
enables: "/dataDemo/enable.json",//功能开启关闭接口
buildData: "/dataDemo/buildData.json",//创建模型接口
racks: "/dataDemo/racks.json",//机柜信息
useRates:"/dataDemo/useRates.json",//机柜利用率
temperatures: "/dataDemo/tempTureData.json",//温度数据
bearing: "/dataDemo/beringRate.json",//承重
euRate: "/dataDemo/euRate.json",//功耗
uvInfos: "/dataDemo/uDetail.json",//u位信息
otherDevs: "/dataDemo/otherDev.json",//其它动环设备
DevData: "/dataDemo/otherDevValue.json",//动环设备实时数据
queryInfos: "/dataDemo/search.json",//查询接口
alarms: "/dataDemo/alarm.json",//告警
wsurl: "xxxx",//websocket地址 }
}
WebAPI.prototype.getEnables = function () {
var _this = this;
var url = this.serverHead + this.urls.enables + "?roomId=" + this.roomid;
url += "&r=" + Math.random();
var enables = null;
httpGetSyn(url, function (response) {
if (response && response.data) {
enables = response.data;
}
}, function (err) {
console.log(err);
});
return enables;
}
.......
由于篇幅原因,我们本节课先到这里,后面我们更新如何创建一个可编辑工具完成配置
其它相关文章:
如何使用webgl(three.js)实现煤矿隧道、井下人员定位、掘进面、纵采面可视化解决方案——第十九课(一)
如何使用webgl(three.js)实现3D消防、3D建筑消防大楼、消防数字孪生、消防可视化解决方案——第十八课(一)
webgl(three.js)3D光伏,3D太阳能能源,3D智慧光伏、光伏发电、清洁能源三维可视化解决方案——第十六课
如何用webgl(three.js)搭建一个3D库房,3D仓库3D码头,3D集装箱,车辆定位,叉车定位可视化孪生系统——第十五课
webgl(three.js)实现室内三维定位,3D定位,3D楼宇bim、实时定位三维可视化解决方案——第十四课(定位升级版)
使用three.js(webgl)搭建智慧楼宇、设备检测、数字孪生——第十三课
如何用three.js(webgl)搭建3D粮仓、3D仓库、3D物联网设备监控-第十二课
如何用webgl(three.js)搭建处理3D隧道、3D桥梁、3D物联网设备、3D高速公路、三维隧道桥梁设备监控-第十一课
如何用three.js实现数字孪生、3D工厂、3D工业园区、智慧制造、智慧工业、智慧工厂-第十课
使用webgl(three.js)创建3D机房,3D机房微模块详细介绍(升级版二)
如何用webgl(three.js)搭建一个3D库房-第一课
如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室,-第二课
使用webgl(three.js)搭建一个3D建筑,3D消防模拟——第三课
使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课
如何用webgl(three.js)搭建不规则建筑模型,客流量热力图模拟
使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课(炫酷版一)
使用webgl(three.js)搭建3D智慧园区、3D大屏,3D楼宇,智慧灯杆三维展示,3D灯杆,web版3D,bim管理系统——第六课
如何用webgl(three.js)搭建处理3D园区、3D楼层、3D机房管线问题(机房升级版)-第九课(一)
如何基于three.js(webgl)引擎架构,研发一套通过配置就能自动生成的3D机房系统的更多相关文章
- 前后端数据交互处理基于原生JS模板引擎开发
json数据错误处理,把json文件数据复制到----> https://www.bejson.com/ 在线解析json 这样能直观的了解到是否是json数据写错,在控制台打断点,那里错误打那 ...
- 关于webStrom-11.1配置less且自动生成.css和自动压缩为.min.css/.min.js
网上看过很多配置思路,自己总结了以下, 就把我个人配置的顺序以及材料分享下,webstrom以下简称WB 1.配置less需要安装nodejs,自行安装.因为要用到npm.我是直接把npm解压到C盘根 ...
- 游戏引擎架构Note1
[游戏引擎架构] 1.第14章介绍的对游戏性相关系统的设计非常有价值.各个开发人员几乎都是凭经验设计,很少见有书籍对这些做总结. 5.通过此书以知悉一些知名游戏作品实际上所采用的方案. 6.书名中的架 ...
- 基于Vue.js的Web视频播放器插件vue-vam-video@1.3.6 正式发布
前言 今日正式发布一款基于Vue.js的Web视频播放器插件.可配置,操作灵活.跟我一起来体验吧! 线上地址体验 基于vue3.0和vue-vam-video,我开发了一款在线视频播放器. 网址: h ...
- 如何设计一个基于Node.js和Express的网站架构?
前言 今年七月份,我和几个小伙伴们合伙建立了一个开发团队.业务开展如火如荼的同时,团队宣传就提上了日程,所以迫切需要搭建公司网站出来.确定目标后我们就开始考虑如果构建一个企业网站.先是进行业内调查,看 ...
- 基于 Angularjs&Node.js 云编辑器架构设计及开发实践
基于 Angularjs&Node.js 云编辑器架构设计及开发实践 一.产品背景 二.总体架构 1. 前端架构 a.前端层次 b.核心基础模块设计 c.业务模块设计 2. Node.js端设 ...
- JS模板引擎:基于字符串拼接
目的 编写一个基于字符串拼接的js模板引擎雏形,这里并不会提供任何模板与数据的绑定. 基本原理 Javascript中创建函数的方式有多种,包括: 1. var func = function () ...
- 基于React Native的移动平台研发实践分享
转载:http://blog.csdn.net/haozhenming/article/details/72772787 本文目录: 一.React Native 已经成为了移动前端技术的趋势 二.基 ...
- 基于AWS的云服务架构最佳实践
ZZ from: http://blog.csdn.net/wireless_com/article/details/43305701 近年来,对于打造高度可扩展的应用程序,软件架构师们挖掘了若干相关 ...
- 基于 Docker 的微服务架构实践
本文来自作者 未闻 在 GitChat 分享的{基于 Docker 的微服务架构实践} 前言 基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 D ...
随机推荐
- kafka学习笔记02
kafka拥有与其他几个消息队列同样的本事: ①缓冲/削峰:控制和优化数据经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况. 应用场景:双十一秒杀活动,将用户消息写入消息队列中,我 ...
- .Net 472&6.0 Razor编译时的小差异
前言 几个月前在进行着.Net 472到6.0的升级,复用原有代码,在对Razor进行迁移中,发现原运行正常的代码,却存在报错,深入研究发现是Core下对Razor编译有一些变动. 问题复现 472 ...
- 前端Vue组件之仿京东拼多多领取优惠券弹出框popup 可用于电商商品详情领券场景使用
随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身.通过组件化开发,可以有效 ...
- 一文搞懂什么是 API
在我学习软件开发之前,API 听起来像是一种啤酒(IPA,印度淡色艾尔).如今我经常使用这个术语,事实上最近我还尝试在酒吧里点了一个 API,结果酒保给了我一个: 404 资源未找到的回应 无论是在科 ...
- win10使用Docker Desktop启动mysql报错:Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:3306 -> 0.0.0.0:0: listen tcp 0.0.0.0:3306:
问题描述 今天上班用wind10电脑启动Docker Desktop使用MySQL,突然间报了一个错,错误如下: Error response from daemon: Ports are not a ...
- K8S | Deployment应用编排
目录 一.背景 二.Deployment组件 1.简介 2.语法说明 三.基础用例 1.创建操作 2.查看信息 3.更新操作 4.删除操作 四.进阶用例 1.回滚操作 2.伸缩操作 3.暂停与恢复 五 ...
- zabbix 使用监控项原型(自动发现规则)
以kafka为例,需要先对 topic-parttion 做发现,脚本如下 cat topic_parttion_discovery.py #!/usr/bin/env python import j ...
- KVM vm time setting
- config file $ grep clock vm02.xml <clock offset='utc'> </clock> - NTP server $ s vm02 ...
- 关于quartus II的导入以前的工程,QSF文件出现的错误的解决方案。
在有时候打开以前的工程,或者别人做好的例程会遇到一些报错信息.具体报错信息如下: 报错信息语句行: 在文件QSF文件中有几行出错,显示错误读取,即不能打开工程.打开文件发现该几行的PIN 使能信号处于 ...
- python 镜像
https://pypi.douban.com/simple/ 豆瓣源 pip install -i https://pypi.douban.com/simple/ pymysql # pymys ...