WEB组态可视化软件(B/S)

WEB组态可视化软件

1 B/S组态软件

它是一个独立的产品,包含编辑器(设计时)和运行环境(运行时)两大模块,我们将其命名为——WEB组态可视化软件(下称“组态软件”)。

2 组态概念

组态(Configure)的概念来自于20世纪70年代中期出现的第一代集散控制系统(Distributed Control System),可以理解为“配置”、“设定”、“设置”等,是指通过人机开发界面,用类似“搭积木”的简单方式来搭建软件功能,而不需要编写计算机程序。我们也可称之为“二次开发”,组态软件即为“二次开发平台”。

3 组态产品呈现

组态软件是个怎样的产品?
先做一个概述:组态软件通过浏览器操作组态工具、浏览组态画面,实现工程管理、组态编辑以及组态运行三大功能。通过实现图元组态、可视化图表组态、数据库组态的配置与关联,完成基于Web服务的实时数据监控与服务端的多用户访问等。

从用户操作与界面呈现的角度来说,组态软件采用标准HTML5技术,基于B/S架构进行开发,支持Web端呈现,在浏览器端即可完成便捷的人机交互,简单的拖拽即可完成可视化页面的编排设计。此外,由于组态软件功能较为复杂,为降低使用门槛,组态软件进行了模块集成化,旨在简化用户的操作步骤,提高用户的工作效率。

从软件架构来说,组态软件具备高度的开放性。随着应用场景的逐渐增加,软件必然需要进行功能扩展,因此,组态软件不仅支持多种数据接口,也提供了二次开发接口,可以由用户自行完成二次开发。组态软件在功能上集成了大量通用模块和个性化模块,以实现不同行业用户的需求。针对具体的用户,软件支持定制化模块的开发与配置,实现“即插即用“。

软件的运行逻辑并不复杂,除了基础的组态管理外,主要可分为组态编辑和组态运行两个部分。用户需要在组态编辑环境中使用组态软件提供的组态功能(图元、图表、数据库)进行组态设置、建立网络拓扑、绘制数据显示界面、配置各种系统参数(如数据采集频率)等;然后在组态运行环境中运行已经组态好的应用系统,包括数据实时监控、场景展示等。

两者之间的关系如图所示:

4 功能特点

  • 基于html5,B/S架构
  • 支持 2D、2.5D、3D多种呈现模式
  • 可视化拖拽编辑、简单易用
  • 支持云端/本地等部署方式,多终端使用
  • 提供丰富的行业标准元器件图元库
  • 提供行业模板和组件,支持自定义模板和图纸管理
  • 提供定制开发服务
  • 支持Http、WebSocket等主流协议,支持扩展更多协议
  • 支持嵌入第三方系统或者集成平台,也可作为独立平台
  • 具备延续性、可扩展性、封装性(易学易用)、通用性、开放性
  • 周密的系统安全防范

软件主要功能模块有组态管理、组态编辑、组态运行三大模块:

  1. 组态管理

管理模块的详细功能与其他软件大同小异,系统管理通过分级权限保障系统的安全;工程管理则是对组态文件的建立、提交、删除、恢复等基本操作提供入口。
2. 组态编辑

本模块是组态软件的核心模块,软件绝大部分操作都在这一个模块里面进行。

主要操作对象有画布、图元、可视化图表以及数据库。针对画布与图元这类基础对象,软件提供诸如调整尺寸、属性、复制、粘贴、增删、合并、拆分、绑定跳转页面/事件等操作,搭建可视化页面的基础架构。

可视化图表是页面展示的主要形式,因此,除了针对图元的基本操作之外,软件还提供了样式设计、文本属性以及运行参数设置,确保图表在可视化页面的展示效果。

数据库作为系统的数据源,需要与组态形成关联,为组态提供数据。软件支持配置组态关联的数据库信息、绑定图元/可视化图表对应实时/历史数据源、设置图元/可视化图表数据源触发事件等功能。


  1. 组态运行

本模块将为各类应用场景提供实际的运行功能,具体如下所示:

  • 解析组态画面编辑文件
  • 绘制动态实时监控页面
  • 关联图元及可视化图表数据源
  • 可视化图表数据导出
  • 网络通信检测
  • 设置可视化图表运行参数
  • 失效数据检测处理等

5 组态软件应用场景

组态软件的出现,为解决实际工程问题提供了一种崭新的方法,用户通过类似“搭积木”的简单方式来完成自己所需要的软件功能,不需要编辑计算机程序。组态软件能够很好地解决各类场景中存在的种种问题,使用户能根据自己的管理对象和管理目的的任意组态,完成最终的场景控制自动化、数据可视化。主要适应场景如下:

  • 配电
  • 工业(控制)
  • 智能楼宇
  • 变电站管理
  • 电厂电气
  • 配电室监控
  • 冶金工艺流程控制
  • 水力自动控制
  • 石油智能控制系统等

6 经典的案例

6.1 某通信基站的组态可视化

本项目采用2.5D的形式进行可视化展示,2.5D技术使用三维建模方式,构建立体效果,同时增加了2D的光照和2D各种方法,系统的功能具有很好的延展性。系统在项目中可以进行数据结构更换、tips效果优化、选中效果、设备告警、油箱动态油量显示、油机开关机功能,支持自动布局多种布局方式,可进行接口对接,支持基站多设备的添加,设备基本信息的查看等功能。

7 具体实现

7.1 设计时

7.1.1 表单输入

基于HTML5进行表单输入,前端给ui打上id标签

<li data-cIndex='16'><img src="./images/icons/door.png" class="CNicons" alt=""><a id="a_16"   class=" controlName" group="">门禁</a></li>


<tr id="tr_i_DoorState" style=" display:none;">
	<td></td>
	<td class="txt i_attrName">门状态点</td>
	<td class="txt">
	   <input type="text" id="i_DoorState" name="DoorState" style="width:150px;">
	</td>
</tr>
<tr id="tr_i_OpenStateValue" style=" display:none;">
	<td></td>
	<td class="txt i_attrName">门打开值</td>
	<td class="txt">
		<select id="i_OpenStateValue" name="openValue">
			<option value="0">0</option>
			<option value="1">1</option>
		</select>
	</td>
</tr>
<tr id="tr_i_OpenDoorState" style=" display:none;">
	<td></td>
	<td class="txt i_attrName">开门控制点</td>
	<td class="txt">
		<input type="text" id="i_OpenDoorState" name="OpenDoorState" style="width:150px;">
	</td>
</tr>
<tr id="tr_i_linkdeviceid" style=" display:none;">
	<td></td>
	<td class="txt" id="td_i_linkdeviceid_tit">联动点</td>
	<td class="txt i_attrName">
		<input id="i_linkdeviceid" class="input0" value="" style="width:150px;">
	</td>
</tr>
<tr id="tr_i_CardReader" style=" display:none;">
	<td></td>
	<td class="txt" id="td1">读头</td>
	<td class="txt i_attrName">
		<input id="i_CardReader" name="CardReader" class="input0" value="" style="width:150px;">
	</td>
</tr>


7.1.2 js脚本

根据id,通过js来面向dom元素编程,如果时vue,angular,react则直接可绑定数据,面向数据编程。通过js来对拖动,点击,修改,保存等事件进行编程;

	//门状态点
	$('#i_DoorState').focus(function(){
		var stateName = $(this).attr('name');
		selectDevState(stateName);
	});
	//门打开控制点
	$('#i_OpenDoorState').focus(function(){
		var stateName = $(this).attr('name');
		selectDevState(stateName);
	});
	//读头
	$('#i_CardReader').focus(function(){
		var stateName = $(this).attr('name');
		selectDevState(stateName);
	});
				else if(devIndex==16){//门禁
					$('#tr_i_OpenStateValue').show();
					$('#tr_i_DoorState').show();
					$('#tr_i_OpenDoorState').show();
					$('#tr_i_CardReader').show();

如,如下保存点击事件可保存配置属性成json,生成json文件或者post给后台服务加载到数据库。

$('#a_save').click(function(){
	var row = $('#MonitoringSiteTable').datagri('getSelected');
	if(row){
		var devArr= $('.dev');
		for(var i=0;i<devArr.length;i++){
			if(devArr.eq(i).css('outline-style'!=='none'){
				var upId = devArr.eq(i).attr('id');
				switch(stateName){
					case 'devname':
						$('#i_deviceid').val(rowdevname);
						deviced[upId].devname=rowdevname;
						if(deviced[upId].devIndex==8){
							
							var txt = textShowMod(upId);	
							var textID = 'p'+upI+'img';
							$('#'+textID).text(txt)css({color:deviced[upId]fontColor});
							textAlign(devId);
						}else if(deviced[upId]devIndex==14){
							devArr.eq(i).find('span')text(row.devname).css{color:'#555'display:'inline-block'position:'absolute'bottom:'10px'});
						}else if(deviced[upId]devIndex==5){
							moniShowMode(upId);
							var textID = 'p'+upI+'img';
							$('#'+textID).css{color:deviced[upId]fontColor});
						}else if(deviced[upId]devIndex==15){
							devArr.eq(i).find('span')text(row.devname).css{color:'#555'position:'absolute'bottom:'10px',left:'0px'};
						}
						break;
					case 'OpenDoorState':
						$('#i_OpenDoorState').val(rowdevname);
						deviced[upId].OpenDoorState =row.devname;
						break;
					case 'DoorState':
						$('#i_DoorState').val(rowdevname);
						deviced[upId].DoorState = rowdevname;
						break;
					case 'CardReader':
						$('#i_CardReader').val(rowdevname);
						deviced[upId].CardReader =row.devname;
						break;
					case 'linkorgid':
						$('#i_linkorgid').val(roworgname);
						deviced[upId].linkorgid=roworgname;
						break;

7.2 运行时

7.2.1 前端给ui打上id标签

	<div id="centerTabs" class="easyui-tabs" style="width:100%;height:100%;">
		<div title="组态图设计" id="contentBox" data-options="closable:false" style="padding:4px;position:relative;">
			<div id="resizeBox" style="position:relative;width:100%;height:100%;z-index:2;border:1px solid #ccc;overflow:hidden;" data-Box="bgBox"></div>
		</div>
		<div title="预览" data-options="closable:false" style="padding:4px;position:relative;" id="previewBox">
			
		</div>
	</div>

7.2.2 js脚本

需要先从数据库或者*.json加载控件的配置数据,来展现完成的控件属性,然后去对应的后台接口,或者devicedata.json(后台服务生成),来更新当前设备的实时数据。
定时刷新设备实时数据,其余定时刷新实时数据的代码太长,这里不粘贴,自行补全。

	//预览
	$('#centerTabs').tabs({
		onSelect:function(title,index){
			if(title=="预览"){
				preview();
			}else if(title=="组态图设计"){
				clearInterval(intervalId);
				if($('.video').length>0){
					var video = $('.video').eq(0);
					$('#resizeBox').append(video);
					var devId = video.attr('id');
					video.css('outline-style',deviced[devId].outlineStyle);
					if(video.css('outline-style')!=='none'){
						$('#'+devId+'img').show();
					}
					$('#'+devId).resizable({
						disabled:false
					});
					deviced[devId].ocx.DisConnectAllChannel();
				}else if($('.chart').length>0){
					var chart = $('.chart');
					for(var j=0;j<chart.length;j++){
						$('#resizeBox').append(chart.eq(j));
						var devId = chart.eq(j).attr('id');
						chart.eq(j).css('outline-style',deviced[devId].outlineStyle);
						$('#'+devId).resizable({
							disabled:false
						});
					}
				}
				$('#previewBox').empty();
				for(var i in deviced){
					if(deviced[i].devIndex==14){
						deviced[i].option.series[0].data[0].value=50;
						deviced[i].Chart = echarts.init(document.getElementById(i+'img')); 
						deviced[i].Chart .setOption(deviced[i].option,true);
					}else if(deviced[i].devIndex==15){
						deviced[i].dial = new canvasPanel();
						deviced[i].dial.bgColor = deviced[i].panelColor;
						deviced[i].dial.splitNum = deviced[i].lineValue;
						deviced[i].dial.MaxNum=parseInt(deviced[i].dmaxvalue);
						deviced[i].dial.MinNum = parseInt(deviced[i].dminvalue);
						deviced[i].dial.init(i+'img');
					}else if(deviced[i].devIndex==24){
						deviced[i].data = [];
						clearInterval(deviced[i].chartInterval);
					}
				}
			}
		}
	});

8 小结

  • 设计时,根据配置属性,生成配置json文件,或者配置后台服务,通过webapi接口持久化配置到db;
  • 运行时,从数据库或者配置文件来生成定制的控件,根据配置参数来加载实时json或者去实时接口ajax或者websocket拿数据;

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://www.cnblogs.com/JerryMouseLi/p/14082036.html

posted @ 2020-12-03 18:49  JerryMouseLi  阅读(404)  评论(0编辑  收藏