提交 66ed7cf7 编写于 作者: Xeden's avatar Xeden

1.1.08 BETA 版,添加了对MQTT的支持,fix.修复了simulation device下多dot的node name支持

上级 9ef10bbc
......@@ -46,7 +46,8 @@
"report": "报表",
"activate": "激活",
"about": "关于",
"language": "语言"
"language": "语言",
"mqtt_client": "MQTT 客户端"
},
"main": {
"does_not_exist": " 不存在",
......@@ -197,5 +198,55 @@
"the_server_will_stop_after_you_restart": "系统有可能在重启间隔停止服务",
"yes_restart_it": "确认,重启!",
"restart_successfully": "服务重启成功"
},
"page_mqtt_client": {
"devs": "设备",
"name": "名称",
"addr": "地址",
"type": "类型",
"length": "长度",
"note": "说明",
"value": "值",
"opt": "操作",
"send": "发送",
"copy": "复制",
"append": "新增",
"removeLast": "删除最后",
"insert": "插入",
"remove": "删除",
"moveUp": "上移",
"moveDown": "下移",
"rowEmpty": "无数据",
"device_setting": "设备配置",
"node_configure": "节点配置",
"refresh": "刷新",
"apply": "应用",
"title": "监控",
"subtitle": "压力化成设备出入口",
"plc_entry_status": "PLC 入口状态",
"plc_exits_status": "PLC 出口状态",
"mes_stat": "MES 状态",
"sys_auto_running": "自动模式(Auto)",
"stat": "STAT",
"entry": "入口",
"equipment_entry_point": "设备入口记录",
"reset": "复位",
"clear": "清除",
"exits": "出口",
"new_device": "新加设备",
"delete": "删除设备",
"restart_server": "重启服务",
"stop_server": "停止服务",
"start_server": "启动服务",
"filter": "过滤",
"state": "状态",
"scan_rate": "扫描频率(ms)",
"send_every_scan": "扫描并发布",
"deadband": "变化率(%)",
"addnew": "添加",
"last_scan": "最后扫描",
"last_value": "最后值",
"close": "关闭",
"pls_select_nodes_you_need": "选择需要转传的点位"
}
}
\ No newline at end of file
......@@ -46,7 +46,8 @@
"report": "Report",
"activate": "Activate",
"about": "About",
"language": "Language"
"language": "Language",
"mqtt_client": "MQTT Client"
},
"main": {
"does_not_exist": "does not exist",
......@@ -199,5 +200,57 @@
"the_server_will_stop_after_you_restart": "The server may stop before it restarted.",
"yes_restart_it": "yes, restart!",
"restart_successfully": "restart successfully"
},
"page_mqtt_client": {
"devs": "Devs",
"name": "Name",
"addr": "Addr",
"type": "Type",
"length": "Length",
"note": "Note",
"value": "Value",
"opt": "Opt",
"send": "Send",
"copy": "Copy",
"append": "Append",
"removeLast": "Remove Last",
"insert": "Insert",
"remove": "Remove",
"moveUp": "Move Up",
"moveDown": "Move Down",
"rowEmpty": "Empty",
"device_setting": "Device Setting",
"node_configure": "Node Configure",
"refresh": "Refresh",
"apply": "Apply",
"title": "Dashboard",
"subtitle": "for pressure forming equipment",
"plc_entry_status": "PLC Entry",
"plc_exits_status": "PLC Exits",
"printer_01_status": "Printer 01",
"printer_02_status": "Printer 02",
"mes_stat": "MES Status",
"sys_auto_running": "Auto Running",
"stat": "STAT",
"entry": "Entry",
"equipment_entry_point": "equipment entry point",
"reset": "Reset",
"clear": "Clear",
"exits": "Exits",
"new_device": "New Device",
"delete": "Delete",
"restart_server": "Restart Server",
"stop_server": "Stop Server",
"start_server": "Start Server",
"filter": "filter",
"state": "State",
"scan_rate": "Scan rate(ms)",
"send_every_scan": "Send every scan",
"deadband": "Deadband(%)",
"addnew": "AddNew",
"last_scan": "Last scan",
"last_value": "Last value",
"close": "Close",
"pls_select_nodes_you_need": "Please select nodes you need"
}
}
\ No newline at end of file
// global value
var g_version = "v1.0.24 BETA";
var g_version = "v1.1.08 BETA";
$("[name='lb_version']").html("2020 © LECPServer By Leanboard Tech Ltd  |  " + g_version + "  ");
JsProxyAPI.setTitle("LECPServer " + g_version)
JsProxyAPI.setNotifyIcon("logo.ico");
......@@ -8,10 +8,12 @@ JsProxyAPI.setNotifyTitle("LECPServer");
var g_plc_data = null; // plc当前数据
var g_user_login = ""; // 当前登陆用户
var g_handler_plc = {};
var g_handler_mqtt_client = {};
var g_handler_db = null;
var g_modules_conf = null;
var g_settings_conf = null;
var g_sync_worker_lock = null;
var g_mqtt_client_data = null;
// PLC的返回状态,包括入口和出口,可以分别进行报警和显示
// Online和Offline只看入口即可
......@@ -53,8 +55,6 @@ function load_modules_conf() {
}
}
// 读取 plc.conf 配置信息
function load_plc_conf() {
let s = JsProxyAPI.fileRead("./plc.conf");
......@@ -74,6 +74,26 @@ function load_plc_conf() {
}
}
// 读取 mqtt.conf 配置信息
function load_mqtt_conf() {
let s = JsProxyAPI.fileRead("./mqtt.conf");
if (s == "") {
alert("mqtt.conf " + i18next.t('main.does_not_exist'));
g_mqtt_client_data = { "NODES": {}, "DEVS": {}, "WEBAPI": { "PORT": 8088 } }
JsProxyAPI.fileWrite("mqtt.conf", JSON.stringify(g_mqtt_client_data, null, "\t"));
return false;
}
try {
g_mqtt_client_data = JSON.parse(s);
return true;
} catch (e) {
alert(i18next.t('main.incorrect_format_of_file') + " mqtt.conf:" + e);
return false;
}
}
function deepCopy(target) {
let copyed_objs = [];//此数组解决了循环引用和相同引用的问题,它存放已经递归到的目标对象
function _deepCopy(target) {
......@@ -149,6 +169,23 @@ function get_guid() {
// =======================================================================
// =======================================================================
// 数组判定是否一致
function equar(a, b) {
// 判断数组的长度
if (a.length !== b.length) {
return false
} else {
// 循环遍历数组的值进行比较
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false
}
}
return true;
}
}
// 延时函数
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
......@@ -283,10 +320,81 @@ function insert_dashboard_data(msg, type = "default", zone = "entry") {
// =======================================================================
// =======================================================================
// 初始化MQTT服务器
function init_mqtt_server() {
if (g_mqtt_client_data['MQTTSERVER']['START'] == true) {
let r = JsProxyAPI.mqttServerStart(g_mqtt_client_data['MQTTSERVER']['PORT'],
function (success, handler) {
console.log(success, handler);
},
function (clientId, topic, payload) {
console.log(clientId, topic, payload);
}
);
}
}
// 初始化 WebAPI 服务器
function init_webapi_server() {
// 获取点位的值
function findStrIndex(str, cha, num) {
let x = str.indexOf(cha);
for (let i = 0; i < num; i++) {
x = str.indexOf(cha, x + 1);
}
return x;
}
function plc_get_node_dev(key, plc_data) {
// 查询key是否存在
let dot_count = (key.match(/\./g) || []).length;
if (dot_count < 2) {
return null;
}
let a = key.split(".", 2);
let root = a[0];
let dev = a[1];
let node = key.substr(key.length - (key.length - findStrIndex(key, ".", 1) - 1));
if (root != "NODES") {
return null;
}
if (typeof (plc_data['NODES'][dev]) == "undefined") {
return null;
} else {
return dev;
}
}
function plc_read_node(key, plc_data, ch_node = "value") {
// 查询key是否存在
let dot_count = (key.match(/\./g) || []).length;
if (dot_count < 2) {
return null;
}
let a = key.split(".", 2);
let root = a[0];
let dev = a[1];
let node = key.substr(key.length - (key.length - findStrIndex(key, ".", 1) - 1));
if (root != "NODES") {
return null;
}
if (typeof (plc_data['NODES'][dev]) == "undefined") {
return null;
}
if (typeof (plc_data['NODES'][dev][node]) == "undefined") {
return null;
}
return plc_data['NODES'][dev][node][ch_node];
}
/*
function plc_read_node(key, plc_data, ch_node = "value") {
// 查询key是否存在
try {
......@@ -325,6 +433,7 @@ function init_webapi_server() {
return null;
}
}
*/
let r = JsProxyAPI.webAPIStart(g_plc_data['WEBAPI']['PORT'],
function (success, handler) {
......@@ -415,10 +524,10 @@ function init_webapi_server() {
if (rt == null || err) {
rts[i] = null;
// return JSON.stringify({ "errcode": 4055, "errmsg": "Node [" + node + "] is not exists", "rtval": rts });
}else{
} else {
rts[i] = rt;
}
}
return JSON.stringify({ "errcode": 0, "errmsg": "", "rtval": rts });
}
......@@ -446,6 +555,10 @@ function init_webapi_server() {
let dev = plc_get_node_dev(node, g_plc_data);
let done = 0;
if (g_plc_status[dev]['online'] == false) {
return JSON.stringify({ "errcode": 4013, "errmsg": "Device " + dev + " is offline" });
}
// 如果是模拟驱动模式,直接写入本buffer值
if (g_plc_data['DEVS'][dev]['PLC_DRIVER'] == "simulation") {
let rt = plc_read_node(node, g_plc_data, "addr");
......@@ -453,7 +566,8 @@ function init_webapi_server() {
return JSON.stringify({ "errcode": 4057, "errmsg": "Node [" + node + "] is not exists", "rtval": rt });
}
let a = node.split(".");
g_plc_data['NODES'][dev][a[a.length - 1]]['value'] = j['value'];
let addr = node.replace(a[0] + "." + a[1] + ".", "");
g_plc_data['NODES'][dev][addr]['value'] = j['value'];
return JSON.stringify({ "errcode": 0, "errmsg": "" });
}
......@@ -917,7 +1031,7 @@ async function init_plc_device(dev) {
return;
return new Promise((resolve, reject) => {
// 欧姆龙fins协议
// 按照不同协议类型来进行连接
let dd = g_modules_conf[d['PLC_DRIVER']];
let type = dd['TYPE'];
let string_reverse = false;
......@@ -1487,6 +1601,8 @@ if (!load_modules_conf()) {
load_settings_conf();
// 启动系统
load_plc_conf();
// 读取mqtt配置
load_mqtt_conf();
// 初始化PLC连接
init_plc();
// 初始化数据库
......@@ -1495,6 +1611,9 @@ if (!load_modules_conf()) {
//初始化WebApi服务器
init_webapi_server()
//初始化mqtt服务器
init_mqtt_server();
if (g_settings_conf != null) {
let s = g_settings_conf['DISPLAY_SCREEN'];
if (s == 0 || s == 1) {
......
......@@ -131,7 +131,7 @@
<div class="col-lg-12 col-xs-12 col-sm-12">
<div class="portlet light">
<div class="portlet-title">
<div class="caption" style="width: 80%;">
<div class="caption" style="width: 60%;">
<div class="col-md-4">
<span class="caption-subject bold uppercase font-dark"
data-i18n="page_dashboard.node_configure">Node Configure</span>
......
<!-- BEGIN PAGE HEADER-->
<!-- BEGIN PAGE BAR -->
<!--
<div class="page-bar">
<ul class="page-breadcrumb">
<li>
</li>
<li>
<span></span>
</li>
</ul>
</div>
-->
<!-- END PAGE BAR -->
<!-- BEGIN PAGE TITLE-->
<div name="main_page_mqtt_client">
<!--
<h1 class="page-title"><span data-i18n="page_mqtt_client.title">mqtt_client</span>
<small><span data-i18n="page_mqtt_client.subtitle">for pressure forming equipment</span></small>
</h1>
-->
<!-- END PAGE TITLE-->
<!-- END PAGE HEADER-->
<div class="row">
<div class="col-md-2">
<div class="portlet light ">
<div class="portlet-title">
<div class="caption" data-toggle="collapse" data-target=".todo-project-list-content">
<span class="caption-subject font-green-sharp bold uppercase"
data-i18n="page_mqtt_client.devs">Devs </span>
<span class="caption-helper visible-sm-inline-block visible-xs-inline-block">click to view
project list</span>
</div>
<div class="actions">
<div class="btn-group">
<a class="btn green btn-circle btn-outline btn-sm todo-projects-config" href="javascript:;"
data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
<i class="icon-settings"></i> &nbsp;
<i class="fa fa-angle-down"></i>
</a>
<ul class="dropdown-menu pull-right">
<li>
<a href="javascript:;" data-i18n="page_mqtt_client.new_device"
name="btn_mqtt_client_page_new_device"> New Device </a>
</li>
<li>
<a href="javascript:;" data-i18n="page_mqtt_client.delete"
name="btn_mqtt_client_page_delete_device"> Delete
</a>
</li>
<li class="divider"> </li>
<li>
<a href="javascript:;" data-i18n="page_mqtt_client.restart_server"
name="btn_mqtt_client_page_restart_server"> Restart Server
</a>
</li>
<!--
<li>
<a href="javascript:;" data-i18n="page_mqtt_client.disable"> Disable
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<div class="portlet-body todo-project-list-content">
<div class="todo-project-list">
<ul class="nav nav-stacked profile-nav" name="page_mqtt_client_device_list">
<!--
<li>
<a href="javascript:;" > AirAsia Ads </a>
</li>
<li>
<a href="javascript:;"> HSBC Promo </a>
</li>
<li class="active">
<a href="javascript:;"> GlobalEx</a>
</li>
<li>
<a href="javascript:;"> Empire City </a>
</li>
<li>
<a href="javascript:;"> AirAsia Ads </a>
</li>
<li>
<a href="javascript:;"> Loop Inc Promo </a>
</li>
-->
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-10" style="padding-left: 0px;padding-right: 0px;">
<!--PLC配置-->
<div class="col-lg-12 col-xs-12 col-sm-12">
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<span class="caption-subject bold uppercase font-dark"
data-i18n="page_mqtt_client.device_setting">Device Setting</span>
</div>
<div class="actions">
<a href="javascript:;" class="btn btn-sm btn-circle default easy-pie-chart-reload"
name="btn_mqtt_client_page_apply">
<i class="fa fa-check"></i> <span data-i18n="page_mqtt_client.apply">Apply</span> </a>
</div>
</div>
<div class="portlet-body form">
<form class="form-horizontal" role="form">
<div class="form-body">
<div class="form-group" name="page_mqtt_client_device_settings">
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">MQTT_DRIVER</label>
<div class="col-md-7"><select class="form-control"
name="mqtt_client_page_input_settings" data-tags="MQTT_DRIVER">
<option value="mqtt_client">MQTT Client</option>
</select></div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">IP</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="IP" class="form-control" placeholder="IP" value="127.0.0.1">
</div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">PORT</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="PORT" class="form-control" placeholder="PORT" value="502">
</div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">ClIENT_ID</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="ClIENT_ID" class="form-control" placeholder="ClIENT_ID"
value=""></div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">TOPIC</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="TOPIC" class="form-control" placeholder="TOPIC" value="">
</div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">SCAN_RATE</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="SCAN_RATE" class="form-control" placeholder="SCAN_RATE" value="1000">
</div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px;"><label
class="col-md-5 control-label">LAST_SCAN</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="LAST_SCAN" class="form-control" placeholder="LAST_SCAN" value="">
</div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px; display: none;"><label
class="col-md-5 control-label">USERNAME</label>
<div class="col-md-7"><input type="text" name="mqtt_client_page_input_settings"
data-tags="USERNAME" class="form-control" placeholder="USERNAME"
value=""></div>
</div>
<div class="col-lg-4 col-xs-4 col-sm-4"
style="padding-left: 0px;padding-right: 0px; padding-bottom: 5px; display: none;"><label
class="col-md-5 control-label">PASSWORD</label>
<div class="col-md-7"><input type="password"
name="mqtt_client_page_input_settings" data-tags="PASSWORD"
class="form-control" placeholder="PASSWORD" value=""></div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<!--PLC点位配置-->
<div class="col-lg-12 col-xs-12 col-sm-12">
<div class="portlet light">
<div class="portlet-title">
<div class="caption" style="width: 60%;">
<div class="col-md-4">
<span class="caption-subject bold uppercase font-dark"
data-i18n="page_mqtt_client.node_configure">Node Configure</span>
</div>
<div class="col-md-8">
<div class="form-group">
<h5 class="col-md-3 control-label" data-i18n="page_mqtt_client.filter">Filter</h5>
<div class="col-md-9">
<input type="text" class="form-control input-inline input-medium" placeholder=""
name="txt_mqtt_client_page_filter">
</div>
</div>
</div>
</div>
<div class="actions">
<a href="javascript:;" class="btn btn-sm btn-circle default easy-pie-chart-reload"
name="btn_mqtt_client_page_addnew">
<i class="fa fa-plus"></i> <span data-i18n="page_mqtt_client.addnew">AddNew</span>
</a>
<!--
<a href="javascript:;" class="btn btn-sm btn-circle default easy-pie-chart-reload"
name="btn_mqtt_client_page_refresh">
<i class="fa fa-repeat"></i> <span data-i18n="page_mqtt_client.refresh">Refresh</span>
</a>
-->
<a href="javascript:;" class="btn btn-sm btn-circle default easy-pie-chart-reload"
name="btn_mqtt_client_page_apply">
<i class="fa fa-check"></i> <span data-i18n="page_mqtt_client.apply">Apply</span> </a>
</div>
</div>
<div class="portlet-body">
<div>
<table id="dt_mqtt_client_item_list" border="1" style="width: 100% !important;">
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 设备配置 -->
<div id="dlg_page_mqtt_addnew" class="modal fade" tabindex="-1" style="top: 100px; width:800px">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
<h4 class="modal-title" data-i18n="page_mqtt_client.device_setting">设备配置</h4>
</div>
<div class="modal-body">
<p data-i18n="page_mqtt_client.pls_select_nodes_you_need"> 选择需要转传的点位. </p>
<div class="row">
<div class="col-md-4" style="padding-right:0px;">
<div class="form-group">
<div class="col-md-12" style="padding-left:0px;padding-right:0px;">
<select class="form-control" style="line-height: 200px;height:200px;"
name="sel_page_mqtt_device_select" size="1">
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
<option>Option 4</option>
<option>Option 5</option>
</select>
</div>
</div>
</div>
<div class="col-md-8" style="padding-left:0px;">
<div class="form-group">
<div class="col-md-12" style="padding-left:0px;padding-right:0px;">
<select multiple="" class="form-control" style="line-height: 200px;height:200px;"
name="sel_page_mqtt_nodes_select">
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
<option>Option 4</option>
<option>Option 5</option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" data-dismiss="modal" class="btn btn-outline dark" data-i18n="page_mqtt_client.close">Close</button>
<button type="button" class="btn green" name="btn_page_mqtt_apply" data-i18n="page_mqtt_client.apply">Apply</button>
</div>
</div>
</div>
\ No newline at end of file
此差异已折叠。
......@@ -43,6 +43,9 @@
<link href="../assets/global/plugins/bootstrap-sweetalert/sweetalert.css" rel="stylesheet" type="text/css" />
<link href="../assets/global/plugins/datatables/datatables.min.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="../assets/global/plugins/bootstrap-toastr/toastr.min.css">
<link href="../assets/global/plugins/bootstrap-modal/css/bootstrap-modal-bs3patch.css" rel="stylesheet"
type="text/css" />
<link href="../assets/global/plugins/bootstrap-modal/css/bootstrap-modal.css" rel="stylesheet" type="text/css" />
<script src="../assets/global/flags/iconfont.js"></script>
......@@ -145,6 +148,12 @@
white-space: nowrap;
}
.table-sm .form-control-input-readonly input{
background-color: lightgrey;
pointer-events: none;
border: 1px solid grey;
}
.table-sm .form-control-sm {
width: 80px;
}
......@@ -254,7 +263,8 @@
</li>
<li>
<a href="#" data-target="language">
<i class="fa fa-language"></i> <span data-i18n="page_left_menu.language"> Language
<i class="fa fa-language"></i> <span data-i18n="page_left_menu.language">
Language
</span>
</a>
</li>
......@@ -364,12 +374,19 @@
</a>
</li>
<li class="nav-item">
<a href="javascript:;" class="nav-link nav-toggle" data-target="mqtt_client">
<i class="fa fa-chain"></i>
<span class="title" data-i18n="page_left_menu.mqtt_client">MQTT Client</span>
</a>
</li>
<li class="heading">
<h3 class="uppercase" data-i18n="page_left_menu.system">System</h3>
</li>
<li class="nav-item">
<a href="javascript:;" class="nav-link nav-toggle" data-target="http_debugger">
<i class="icon-docs"></i>
<i class="fa fa-bug"></i>
<span class="title" data-i18n="page_left_menu.http_debugger">HTTP Debugger</span>
</a>
</li>
......@@ -581,10 +598,10 @@
lng = "";
if (window.localStorage)
lng = localStorage["lng"];
if (typeof (lng) == "undefined"){
if (typeof (lng) == "undefined") {
lng = "cn";
}
if (lng == ""){
if (lng == "") {
lng = "cn";
}
i18next.use(i18nextXHRBackend);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册