refactor: 移除 in 信号类型 (全栈 — datacenter/libplc/webserver/前端/测试)
in 信号的核心功能 (获取 out 指针 + 变更回调) 已被 dc_signal_out_link_with_callback 完全覆盖, 其独立的 saddr 命名空间 没有实际业务价值. 后端: - datacenter API: 删除 dc_signal_in/dc_signal_in_with_callback/dc_get_in_signal_info - dc_signal_in.cpp 已删除, g_dc_in/dc_core_find_in 移除 - libplc: 2 处 dc_signal_in → dc_signal_out_link_with_callback - webserver: 移除 WS_SIG_IN 枚举值, ws_sig_add_in 函数, g_ws_sig_names / dc_data 中的 in 分支 前端: - router.js / signals.js / datacenter.js / ui.js / i18n.js / dashboard.js / signal-store.js / index.html: 移除所有 in 导航/页面/Tab/翻译 - 测试: test_datacenter.cpp 移除 test_in_signal
This commit is contained in:
parent
efacf3eaa8
commit
ccb26007e2
|
|
@ -70,7 +70,6 @@
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
I18n.init();
|
I18n.init();
|
||||||
SignalStore.restore();
|
|
||||||
document.getElementById('lang-select').value = I18n.current;
|
document.getElementById('lang-select').value = I18n.current;
|
||||||
document.getElementById('nav-version').textContent = I18n.t('app.version');
|
document.getElementById('nav-version').textContent = I18n.t('app.version');
|
||||||
document.getElementById('nav-title').textContent = I18n.t('app.title');
|
document.getElementById('nav-title').textContent = I18n.t('app.title');
|
||||||
|
|
@ -87,10 +86,12 @@
|
||||||
if (!data || typeof data !== 'object') return;
|
if (!data || typeof data !== 'object') return;
|
||||||
MonitorRing.push('↓', JSON.stringify(data).substring(0, 200));
|
MonitorRing.push('↓', JSON.stringify(data).substring(0, 200));
|
||||||
|
|
||||||
if (data.out || data.in || data.yk || data.ao || data.param) {
|
if (data.type === 'dc_data') {
|
||||||
|
if (typeof DcPage !== 'undefined' && DcPage.onDcData) DcPage.onDcData(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.out || data.yk || data.ao || data.param) {
|
||||||
SignalStore.update(data);
|
SignalStore.update(data);
|
||||||
var sigPages = ['#out','#in','#yk','#ao','#param','#datacenter','#plc_debug'];
|
|
||||||
if (sigPages.indexOf(Router.currentHash) >= 0) Router.dispatch(Router.currentHash);
|
|
||||||
}
|
}
|
||||||
/* ---- 命令列表:渲染到终端面板 ---- */
|
/* ---- 命令列表:渲染到终端面板 ---- */
|
||||||
if (data.type === 'cmd_list' && data.cmds) {
|
if (data.type === 'cmd_list' && data.cmds) {
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ var I18n = {
|
||||||
'nav.section.tools': '工具',
|
'nav.section.tools': '工具',
|
||||||
'nav.dashboard': '仪表盘',
|
'nav.dashboard': '仪表盘',
|
||||||
'nav.out': '开出信号',
|
'nav.out': '开出信号',
|
||||||
'nav.in': '开入信号',
|
|
||||||
'nav.yk': '遥控信号',
|
'nav.yk': '遥控信号',
|
||||||
'nav.ao': '参数设置',
|
'nav.ao': '参数设置',
|
||||||
'nav.param': '定值管理',
|
'nav.param': '定值管理',
|
||||||
|
|
@ -65,7 +64,6 @@ var I18n = {
|
||||||
'dash.url': '地址',
|
'dash.url': '地址',
|
||||||
'dash.status': '状态',
|
'dash.status': '状态',
|
||||||
'dash.out.desc': '开出信号注册',
|
'dash.out.desc': '开出信号注册',
|
||||||
'dash.in.desc': '开入信号链接',
|
|
||||||
'dash.yk.desc': '遥控信号管理',
|
'dash.yk.desc': '遥控信号管理',
|
||||||
'dash.ao.desc': '模拟输出参数',
|
'dash.ao.desc': '模拟输出参数',
|
||||||
'dash.param.desc': '定值区参数',
|
'dash.param.desc': '定值区参数',
|
||||||
|
|
@ -84,7 +82,6 @@ var I18n = {
|
||||||
'signal.saddr': '信号地址',
|
'signal.saddr': '信号地址',
|
||||||
'signal.desc': '描述',
|
'signal.desc': '描述',
|
||||||
'signal.type': '数据类型',
|
'signal.type': '数据类型',
|
||||||
'signal.link': '链接目标',
|
|
||||||
'signal.ctrl': '控制类型',
|
'signal.ctrl': '控制类型',
|
||||||
'signal.ctrl_direct': '直控',
|
'signal.ctrl_direct': '直控',
|
||||||
'signal.ctrl_sbo': '选控 (SBO)',
|
'signal.ctrl_sbo': '选控 (SBO)',
|
||||||
|
|
@ -153,6 +150,7 @@ var I18n = {
|
||||||
'plc_config.help': '点击节点选中 | 拖拽移动 | 点击输出圆点→点击输入圆点连线 | 滚轮缩放 | 拖拽空白区平移',
|
'plc_config.help': '点击节点选中 | 拖拽移动 | 点击输出圆点→点击输入圆点连线 | 滚轮缩放 | 拖拽空白区平移',
|
||||||
|
|
||||||
/* Toast */
|
/* Toast */
|
||||||
|
'toast.val_required': '请输入值',
|
||||||
'toast.ws_error': 'WebSocket 未连接',
|
'toast.ws_error': 'WebSocket 未连接',
|
||||||
'toast.saddr_required': '信号地址不能为空',
|
'toast.saddr_required': '信号地址不能为空',
|
||||||
'toast.add_sent': '添加请求已发送',
|
'toast.add_sent': '添加请求已发送',
|
||||||
|
|
@ -189,7 +187,6 @@ var I18n = {
|
||||||
'nav.section.tools': 'Tools',
|
'nav.section.tools': 'Tools',
|
||||||
'nav.dashboard': 'Dashboard',
|
'nav.dashboard': 'Dashboard',
|
||||||
'nav.out': 'Out Signals',
|
'nav.out': 'Out Signals',
|
||||||
'nav.in': 'In Signals',
|
|
||||||
'nav.yk': 'YK Controls',
|
'nav.yk': 'YK Controls',
|
||||||
'nav.ao': 'AO Parameters',
|
'nav.ao': 'AO Parameters',
|
||||||
'nav.param': 'Param Settings',
|
'nav.param': 'Param Settings',
|
||||||
|
|
@ -218,7 +215,6 @@ var I18n = {
|
||||||
'dash.url': 'URL',
|
'dash.url': 'URL',
|
||||||
'dash.status': 'Status',
|
'dash.status': 'Status',
|
||||||
'dash.out.desc': 'Output signal registrations',
|
'dash.out.desc': 'Output signal registrations',
|
||||||
'dash.in.desc': 'Input signal links',
|
|
||||||
'dash.yk.desc': 'Remote control signals',
|
'dash.yk.desc': 'Remote control signals',
|
||||||
'dash.ao.desc': 'Analog output parameters',
|
'dash.ao.desc': 'Analog output parameters',
|
||||||
'dash.param.desc': 'Setting zone parameters',
|
'dash.param.desc': 'Setting zone parameters',
|
||||||
|
|
@ -237,7 +233,6 @@ var I18n = {
|
||||||
'signal.saddr': 'Signal Address',
|
'signal.saddr': 'Signal Address',
|
||||||
'signal.desc': 'Description',
|
'signal.desc': 'Description',
|
||||||
'signal.type': 'Data Type',
|
'signal.type': 'Data Type',
|
||||||
'signal.link': 'Link Target',
|
|
||||||
'signal.ctrl': 'Control Type',
|
'signal.ctrl': 'Control Type',
|
||||||
'signal.ctrl_direct': 'Direct',
|
'signal.ctrl_direct': 'Direct',
|
||||||
'signal.ctrl_sbo': 'SBO',
|
'signal.ctrl_sbo': 'SBO',
|
||||||
|
|
@ -305,6 +300,7 @@ var I18n = {
|
||||||
'plc_config.help': 'Click node to select | Drag to move | Click output pin → input pin to wire | Scroll to zoom | Drag empty area to pan',
|
'plc_config.help': 'Click node to select | Drag to move | Click output pin → input pin to wire | Scroll to zoom | Drag empty area to pan',
|
||||||
|
|
||||||
/* Toast */
|
/* Toast */
|
||||||
|
'toast.val_required': 'Value required',
|
||||||
'toast.ws_error': 'WebSocket not connected',
|
'toast.ws_error': 'WebSocket not connected',
|
||||||
'toast.saddr_required': 'Signal address is required',
|
'toast.saddr_required': 'Signal address is required',
|
||||||
'toast.add_sent': 'Add request sent',
|
'toast.add_sent': 'Add request sent',
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
Router.register('#dashboard', function(c) {
|
Router.register('#dashboard', function(c) {
|
||||||
var types = [
|
var types = [
|
||||||
{ t: 'out', key: 'nav.out', descKey: 'dash.out.desc', color: 'var(--accent)' },
|
{ t: 'out', key: 'nav.out', descKey: 'dash.out.desc', color: 'var(--accent)' },
|
||||||
{ t: 'in', key: 'nav.in', descKey: 'dash.in.desc', color: 'var(--accent2)' },
|
|
||||||
{ t: 'yk', key: 'nav.yk', descKey: 'dash.yk.desc', color: 'var(--warning)' },
|
{ t: 'yk', key: 'nav.yk', descKey: 'dash.yk.desc', color: 'var(--warning)' },
|
||||||
{ t: 'ao', key: 'nav.ao', descKey: 'dash.ao.desc', color: 'var(--success)' },
|
{ t: 'ao', key: 'nav.ao', descKey: 'dash.ao.desc', color: 'var(--success)' },
|
||||||
{ t: 'param', key: 'nav.param', descKey: 'dash.param.desc', color: '#a78bfa' },
|
{ t: 'param', key: 'nav.param', descKey: 'dash.param.desc', color: '#a78bfa' },
|
||||||
|
|
@ -16,7 +15,7 @@ Router.register('#dashboard', function(c) {
|
||||||
var cards = types.map(function(t) {
|
var cards = types.map(function(t) {
|
||||||
var count = SignalStore.get(t.t).length;
|
var count = SignalStore.get(t.t).length;
|
||||||
return '<div class="dash-card" onclick="window.location.hash=\'#' + t.t + '\'">'
|
return '<div class="dash-card" onclick="window.location.hash=\'#' + t.t + '\'">'
|
||||||
+ '<div class="dash-card-icon">' + Icon.get(t.icon === 'out' ? 'signal' : t.icon === 'in' ? 'link' : t.icon === 'yk' ? 'zap' : t.icon === 'ao' ? 'sliders' : 'settings') + '</div>'
|
+ '<div class="dash-card-icon">' + Icon.get(t.t === 'out' ? 'signal' : t.t === 'yk' ? 'zap' : t.t === 'ao' ? 'sliders' : 'settings') + '</div>'
|
||||||
+ '<div class="dash-card-count">' + count + '</div>'
|
+ '<div class="dash-card-count">' + count + '</div>'
|
||||||
+ '<div class="dash-card-label">' + I18n.t(t.key) + '</div>'
|
+ '<div class="dash-card-label">' + I18n.t(t.key) + '</div>'
|
||||||
+ '<div style="font-size:11px;color:var(--text-muted);margin-top:4px;">' + I18n.t(t.descKey) + '</div>'
|
+ '<div style="font-size:11px;color:var(--text-muted);margin-top:4px;">' + I18n.t(t.descKey) + '</div>'
|
||||||
|
|
@ -51,7 +50,7 @@ Router.register('#dashboard', function(c) {
|
||||||
|
|
||||||
var DashActions = {
|
var DashActions = {
|
||||||
exportAll: function() {
|
exportAll: function() {
|
||||||
var types = ['out', 'in', 'yk', 'ao', 'param'];
|
var types = ['out', 'yk', 'ao', 'param'];
|
||||||
var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<root>\n';
|
var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<root>\n';
|
||||||
var hasData = false;
|
var hasData = false;
|
||||||
types.forEach(function(st) {
|
types.forEach(function(st) {
|
||||||
|
|
@ -88,7 +87,7 @@ var DashActions = {
|
||||||
var count = 0;
|
var count = 0;
|
||||||
nodes.forEach(function(el) {
|
nodes.forEach(function(el) {
|
||||||
var type = el.getAttribute('type');
|
var type = el.getAttribute('type');
|
||||||
if (['out', 'in', 'yk', 'ao', 'param'].indexOf(type) === -1) return;
|
if (['out', 'yk', 'ao', 'param'].indexOf(type) === -1) return;
|
||||||
el.querySelectorAll('signal').forEach(function(sig) {
|
el.querySelectorAll('signal').forEach(function(sig) {
|
||||||
var saddr = sig.getAttribute('saddr');
|
var saddr = sig.getAttribute('saddr');
|
||||||
if (!saddr || !saddr.trim()) return;
|
if (!saddr || !saddr.trim()) return;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @file datacenter.js
|
* @file datacenter.js
|
||||||
* @brief RTU_ALL_AI 数据中心 — 搜索过滤 + 复选框 + 批量添加到配置页
|
* @brief RTU_ALL_AI 数据中心 — 结构化 JSON 数据 + 搜索过滤 + 批量添加
|
||||||
*/
|
*/
|
||||||
Router.register('#datacenter', function(c) { DcPage.render(c); });
|
Router.register('#datacenter', function(c) { DcPage.render(c); });
|
||||||
|
|
||||||
|
|
@ -37,8 +37,8 @@ var DcPage = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTabs() {
|
function renderTabs() {
|
||||||
var types = ['out', 'in', 'yk', 'ao', 'param'];
|
var types = ['out', 'yk', 'ao', 'param'];
|
||||||
var labels = { out: '注册 (out)', in: '链接注册 (in)', yk: '遥控 (yk)', ao: '参数 (ao)', param: '定值 (param)' };
|
var labels = { out: '注册 (out)', yk: '遥控 (yk)', ao: '参数 (ao)', param: '定值 (param)' };
|
||||||
var el = document.getElementById('dc-tab-bar');
|
var el = document.getElementById('dc-tab-bar');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
var h = '';
|
var h = '';
|
||||||
|
|
@ -80,10 +80,10 @@ var DcPage = (function() {
|
||||||
var thEl = document.getElementById('dc-thead');
|
var thEl = document.getElementById('dc-thead');
|
||||||
if (thEl) thEl.innerHTML = '<th style="width:36px"><input type="checkbox" id="dc-cb-all"'
|
if (thEl) thEl.innerHTML = '<th style="width:36px"><input type="checkbox" id="dc-cb-all"'
|
||||||
+ (allChk ? ' checked' : '') + ' onchange="DcPage._toggleAll()"></th>'
|
+ (allChk ? ' checked' : '') + ' onchange="DcPage._toggleAll()"></th>'
|
||||||
+ '<th>id</th><th>saddr</th><th>desc</th><th>val</th><th>type</th><th>ctrl</th><th>link</th>';
|
+ '<th>id</th><th>saddr</th><th>desc</th><th>type</th>';
|
||||||
|
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
tbody.innerHTML = '<tr class="empty-row"><td colspan="8">' + I18n.t('dc.no_signal') + '</td></tr>';
|
tbody.innerHTML = '<tr class="empty-row"><td colspan="5">' + I18n.t('dc.no_signal') + '</td></tr>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,68 +95,36 @@ var DcPage = (function() {
|
||||||
+ '<td class="cell-mono">' + fmtVal(x.id) + '</td>'
|
+ '<td class="cell-mono">' + fmtVal(x.id) + '</td>'
|
||||||
+ '<td class="cell-mono">' + esc(x.saddr) + '</td>'
|
+ '<td class="cell-mono">' + esc(x.saddr) + '</td>'
|
||||||
+ '<td>' + esc(x.desc || '') + '</td>'
|
+ '<td>' + esc(x.desc || '') + '</td>'
|
||||||
+ '<td class="cell-val">' + fmtVal(x.val) + '</td>'
|
|
||||||
+ '<td class="cell-mono">' + esc(x.type || '') + '</td>'
|
+ '<td class="cell-mono">' + esc(x.type || '') + '</td>'
|
||||||
+ '<td class="cell-mono">' + (x.ctrl_type == 1 ? 'SBO' : 'Direct') + '</td>'
|
+ '</tr>';
|
||||||
+ '<td>' + esc(x.link_saddrs || '') + '</td></tr>';
|
|
||||||
});
|
});
|
||||||
tbody.innerHTML = h;
|
tbody.innerHTML = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDcOutput(text) {
|
/**
|
||||||
if (!text || text.length < 10) return;
|
* @brief 从后端 dc_data JSON 加载信号列表 (替代文本解析)
|
||||||
var types = ['out', 'in', 'yk', 'ao', 'param'], currentType = '';
|
*/
|
||||||
var lines = text.split('\n');
|
function loadFromDcData(dc) {
|
||||||
lines.forEach(function(line) {
|
allData = {};
|
||||||
types.forEach(function(t) {
|
['out', 'yk', 'ao', 'param'].forEach(function(t) {
|
||||||
if (line.indexOf(t + ' signals:') >= 0) currentType = t;
|
if (!dc[t] || !Array.isArray(dc[t])) return;
|
||||||
|
allData[t] = dc[t].map(function(s) {
|
||||||
|
return {
|
||||||
|
id: s.id, saddr: s.saddr || '', desc: s.desc || '',
|
||||||
|
type: s.type || '', ctrl_type: s.ctrl_type || 0,
|
||||||
|
link_saddrs: s.link_saddrs || ''
|
||||||
|
};
|
||||||
});
|
});
|
||||||
if (!currentType) return;
|
|
||||||
if (line.indexOf('---') >= 0 || line.indexOf('saddr') >= 0 || line.indexOf(' id ') >= 0) return;
|
|
||||||
var trimmed = line.trim();
|
|
||||||
if (!trimmed) return;
|
|
||||||
var parts = trimmed.split(/\s+/);
|
|
||||||
if (parts.length < 4) return;
|
|
||||||
var item = {};
|
|
||||||
if (currentType === 'param') {
|
|
||||||
item = { id: parseInt(parts[0]), saddr: parts[1], desc: parts[2], type: parts[3] || '', ctrl_type: parseInt(parts[4]) || 0 };
|
|
||||||
} else if (currentType === 'in') {
|
|
||||||
item = { id: parseInt(parts[0]), saddr: parts[1], desc: parts[2], link_saddrs: parts[3] || '', type: parts[4] || '', val: parts[5] || '' };
|
|
||||||
} else {
|
|
||||||
item = { id: parseInt(parts[0]), saddr: parts[1], desc: parts[2], type: parts[3] || '', val: parts[4] || '' };
|
|
||||||
}
|
|
||||||
allData[currentType] = allData[currentType] || [];
|
|
||||||
allData[currentType].push(item);
|
|
||||||
});
|
});
|
||||||
DcPage._renderTable();
|
DcPage._renderTable();
|
||||||
toast(I18n.t('dc.refreshed'), 'success');
|
toast(I18n.t('dc.refreshed'), 'success');
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshAll() {
|
function refreshAll() {
|
||||||
allData = { out: [], in: [], yk: [], ao: [], param: [] };
|
allData = { out: [], yk: [], ao: [], param: [] };
|
||||||
toast(I18n.t('dc.querying'), 'info');
|
toast(I18n.t('dc.querying'), 'info');
|
||||||
var buf = '', timer = null, done = false;
|
/* 发送 datacenter all 命令,后端会在响应中附加 dc_data JSON */
|
||||||
var handler = function(data, binary) {
|
|
||||||
if (binary) {
|
|
||||||
buf += new TextDecoder().decode(binary);
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = setTimeout(function() {
|
|
||||||
if (done) return; done = true;
|
|
||||||
WsClient.msgCbs = WsClient.msgCbs.filter(function(cb) { return cb !== handler; });
|
|
||||||
parseDcOutput(buf);
|
|
||||||
}, 600);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
WsClient.msgCbs.unshift(handler);
|
|
||||||
WsClient.send({ type: 'cmd', data: 'datacenter all' });
|
WsClient.send({ type: 'cmd', data: 'datacenter all' });
|
||||||
/* 兜底超时, 但只在 600ms 定时器未触发时生效 */
|
|
||||||
setTimeout(function() {
|
|
||||||
if (buf && !done) {
|
|
||||||
done = true;
|
|
||||||
WsClient.msgCbs = WsClient.msgCbs.filter(function(cb) { return cb !== handler; });
|
|
||||||
parseDcOutput(buf);
|
|
||||||
}
|
|
||||||
}, 6000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -176,13 +144,14 @@ var DcPage = (function() {
|
||||||
+ '<span class="dc-sel-label" id="dc-sel-label"></span>'
|
+ '<span class="dc-sel-label" id="dc-sel-label"></span>'
|
||||||
+ '<button class="btn btn-primary btn-sm" onclick="DcPage._addSelected()">' + I18n.t('dc.add_to_config') + '</button>'
|
+ '<button class="btn btn-primary btn-sm" onclick="DcPage._addSelected()">' + I18n.t('dc.add_to_config') + '</button>'
|
||||||
+ '</div>'
|
+ '</div>'
|
||||||
+ '<div class="table-wrap"><table class="signal-table">'
|
+ '<div class="table-wrap"><table class="signal-table dc-table">'
|
||||||
+ '<thead id="dc-thead"></thead>'
|
+ '<thead id="dc-thead"></thead>'
|
||||||
+ '<tbody id="dc-tbody"></tbody>'
|
+ '<tbody id="dc-tbody"></tbody>'
|
||||||
+ '</table></div></div>';
|
+ '</table></div></div>';
|
||||||
renderTabs();
|
renderTabs();
|
||||||
renderTable();
|
renderTable();
|
||||||
},
|
},
|
||||||
|
onDcData: loadFromDcData,
|
||||||
refreshAll: refreshAll,
|
refreshAll: refreshAll,
|
||||||
switchTab: function(t) {
|
switchTab: function(t) {
|
||||||
activeTab = t; searchText = ''; selectedSet = {};
|
activeTab = t; searchText = ''; selectedSet = {};
|
||||||
|
|
|
||||||
|
|
@ -1,68 +1,23 @@
|
||||||
/**
|
/**
|
||||||
* @file signals.js
|
* @file signals.js
|
||||||
* @brief 信号管理页面 — out / in / yk / ao (统一渲染)
|
* @brief 信号管理页面 — out / yk / ao (统一渲染, 标准列: # | saddr | desc | type | val | [ctrl] | 操作)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* ---- Out: 开出信号 (带复选框用于批量删除) ---- */
|
||||||
/* ---- Out ---- */
|
|
||||||
Router.register('#out', function(c) {
|
Router.register('#out', function(c) {
|
||||||
c.innerHTML = renderSignalPage('out',
|
c.innerHTML = renderSignalPage('out', true, null, null);
|
||||||
['<input type="checkbox" style="pointer-events:none;opacity:0">', I18n.t('signal.saddr'), I18n.t('signal.desc'), I18n.t('signal.type')],
|
|
||||||
function(s) { return td(esc(s.type || '?'), 'cell-mono'); },
|
|
||||||
function(s) {
|
|
||||||
return '<div class="btn-group">'
|
|
||||||
+ '<button class="btn btn-sm" onclick="SignalActions.set(\'out\',\'' + esc(s.saddr) + '\')">' + Icon.get('edit') + ' ' + I18n.t('signal.set') + '</button>'
|
|
||||||
+ '<button class="btn btn-danger btn-sm" onclick="SignalActions.del(\'out\',\'' + esc(s.saddr) + '\')">' + Icon.get('trash') + '</button>'
|
|
||||||
+ '</div>';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
[].slice.call(document.querySelectorAll('#tbody-out tr')).forEach(function(tr) {
|
|
||||||
var saddr = (tr.querySelector('.cell-mono') || {}).textContent || '';
|
|
||||||
tr.dataset.saddr = saddr;
|
|
||||||
tr.querySelector('td:first-child').innerHTML = '<input type="checkbox">';
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ---- In ---- */
|
/* ---- YK: 遥控信号 (带控制类型列) ---- */
|
||||||
Router.register('#in', function(c) {
|
|
||||||
c.innerHTML = renderSignalPage('in',
|
|
||||||
['<input type="checkbox" style="pointer-events:none;opacity:0">', I18n.t('signal.saddr'), I18n.t('signal.desc'), I18n.t('signal.link'), I18n.t('signal.type')],
|
|
||||||
function(s) { return td(esc(s.link_saddr || '\u2014'), 'cell-mono') + td(esc(s.type || '?'), 'cell-mono'); },
|
|
||||||
function(s) {
|
|
||||||
return '<button class="btn btn-danger btn-sm" onclick="SignalActions.del(\'in\',\'' + esc(s.saddr) + '\')">' + Icon.get('trash') + '</button>';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
[].slice.call(document.querySelectorAll('#tbody-in tr')).forEach(function(tr) {
|
|
||||||
var saddr = (tr.querySelector('.cell-mono') || {}).textContent || '';
|
|
||||||
tr.dataset.saddr = saddr;
|
|
||||||
tr.querySelector('td:first-child').innerHTML = '<input type="checkbox">';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* ---- YK ---- */
|
|
||||||
Router.register('#yk', function(c) {
|
Router.register('#yk', function(c) {
|
||||||
c.innerHTML = renderSignalPage('yk',
|
c.innerHTML = renderSignalPage('yk', false, I18n.t('signal.ctrl'), function(s) {
|
||||||
[I18n.t('signal.saddr'), I18n.t('signal.desc'), I18n.t('signal.type'), I18n.t('signal.ctrl')],
|
return '<td class="cell-mono">' + (s.ctrl_type == 1 ? I18n.t('signal.ctrl_sbo') : I18n.t('signal.ctrl_direct')) + '</td>';
|
||||||
function(s) { return td(esc(s.type || '?'), 'cell-mono') + td(s.ctrl_type == 1 ? I18n.t('signal.ctrl_sbo') : I18n.t('signal.ctrl_direct'), 'cell-mono'); },
|
});
|
||||||
function(s) {
|
|
||||||
return '<div class="btn-group">'
|
|
||||||
+ '<button class="btn btn-sm" onclick="SignalActions.set(\'yk\',\'' + esc(s.saddr) + '\')">' + Icon.get('edit') + ' ' + I18n.t('signal.set') + '</button>'
|
|
||||||
+ '<button class="btn btn-danger btn-sm" onclick="SignalActions.del(\'yk\',\'' + esc(s.saddr) + '\')">' + Icon.get('trash') + '</button>'
|
|
||||||
+ '</div>';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ---- AO ---- */
|
/* ---- AO: 模拟输出 (带控制类型列) ---- */
|
||||||
Router.register('#ao', function(c) {
|
Router.register('#ao', function(c) {
|
||||||
c.innerHTML = renderSignalPage('ao',
|
c.innerHTML = renderSignalPage('ao', false, I18n.t('signal.ctrl'), function(s) {
|
||||||
[I18n.t('signal.saddr'), I18n.t('signal.desc'), I18n.t('signal.type'), I18n.t('signal.ctrl')],
|
return '<td class="cell-mono">' + (s.ctrl_type == 1 ? I18n.t('signal.ctrl_sbo') : I18n.t('signal.ctrl_direct')) + '</td>';
|
||||||
function(s) { return td(esc(s.type || '?'), 'cell-mono') + td(s.ctrl_type == 1 ? I18n.t('signal.ctrl_sbo') : I18n.t('signal.ctrl_direct'), 'cell-mono'); },
|
});
|
||||||
function(s) {
|
|
||||||
return '<div class="btn-group">'
|
|
||||||
+ '<button class="btn btn-sm" onclick="SignalActions.set(\'ao\',\'' + esc(s.saddr) + '\')">' + Icon.get('edit') + ' ' + I18n.t('signal.set') + '</button>'
|
|
||||||
+ '<button class="btn btn-danger btn-sm" onclick="SignalActions.del(\'ao\',\'' + esc(s.saddr) + '\')">' + Icon.get('trash') + '</button>'
|
|
||||||
+ '</div>';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -37,16 +37,24 @@ var Router = {
|
||||||
|
|
||||||
if (hash === this.currentHash) return;
|
if (hash === this.currentHash) return;
|
||||||
this.currentHash = hash;
|
this.currentHash = hash;
|
||||||
|
|
||||||
updateNavActive(hash);
|
updateNavActive(hash);
|
||||||
|
this._render(hash);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 强制重绘当前页面 (用于 WS 推送刷新, hash 不变)
|
||||||
|
*/
|
||||||
|
reload: function() {
|
||||||
|
if (this.currentHash) this._render(this.currentHash);
|
||||||
|
},
|
||||||
|
|
||||||
|
_render: function(hash) {
|
||||||
var page = this.pages[hash];
|
var page = this.pages[hash];
|
||||||
if (!page) { window.location.hash = '#dashboard'; return; }
|
if (!page) { window.location.hash = '#dashboard'; return; }
|
||||||
|
|
||||||
var titleMap = {
|
var titleMap = {
|
||||||
'#dashboard': I18n.t('dash.title'),
|
'#dashboard': I18n.t('dash.title'),
|
||||||
'#out': I18n.t('nav.out'),
|
'#out': I18n.t('nav.out'),
|
||||||
'#in': I18n.t('nav.in'),
|
|
||||||
'#yk': I18n.t('nav.yk'),
|
'#yk': I18n.t('nav.yk'),
|
||||||
'#ao': I18n.t('nav.ao'),
|
'#ao': I18n.t('nav.ao'),
|
||||||
'#param': I18n.t('nav.param'),
|
'#param': I18n.t('nav.param'),
|
||||||
|
|
@ -70,7 +78,6 @@ var Router = {
|
||||||
var NAV = [
|
var NAV = [
|
||||||
{ h: '#dashboard', key: 'nav.dashboard', icon: 'dashboard' },
|
{ h: '#dashboard', key: 'nav.dashboard', icon: 'dashboard' },
|
||||||
{ h: '#out', key: 'nav.out', icon: 'signal', section: 'signal_mgmt' },
|
{ h: '#out', key: 'nav.out', icon: 'signal', section: 'signal_mgmt' },
|
||||||
{ h: '#in', key: 'nav.in', icon: 'link' },
|
|
||||||
{ h: '#yk', key: 'nav.yk', icon: 'zap' },
|
{ h: '#yk', key: 'nav.yk', icon: 'zap' },
|
||||||
{ h: '#ao', key: 'nav.ao', icon: 'sliders' },
|
{ h: '#ao', key: 'nav.ao', icon: 'sliders' },
|
||||||
{ h: '#param', key: 'nav.param', icon: 'settings' },
|
{ h: '#param', key: 'nav.param', icon: 'settings' },
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,84 @@
|
||||||
/**
|
/**
|
||||||
* @file signal-store.js
|
* @file signal-store.js
|
||||||
* @brief 信号数据缓存 — 接收 WS 推送并更新内存 + localStorage 持久化
|
* @brief 信号数据缓存 — 纯内存, WS 推送驱动, 不持久化 + 增量 DOM 刷新
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
var SignalStore = {
|
var SignalStore = {
|
||||||
data: { out: [], in: [], yk: [], ao: [], param: [] },
|
data: { out: [], yk: [], ao: [], param: [] },
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 合并 WS 推送数据到缓存, 并持久化到 localStorage
|
* @brief 合并 WS 推送数据 + 增量更新可见 DOM (不重刷整页)
|
||||||
* @param {object} push {out:[...], in:[...], ...}
|
|
||||||
*/
|
*/
|
||||||
update: function(push) {
|
update: function(push) {
|
||||||
var self = this;
|
var self = this;
|
||||||
['out', 'in', 'yk', 'ao', 'param'].forEach(function(type) {
|
['out', 'yk', 'ao', 'param'].forEach(function(type) {
|
||||||
if (push[type])
|
if (!push[type]) return;
|
||||||
{
|
var map = {};
|
||||||
var map = {};
|
self.data[type].forEach(function(s) { map[s.saddr] = s; });
|
||||||
self.data[type].forEach(function(s) { map[s.saddr] = s; });
|
push[type].forEach(function(s) { map[s.saddr] = s; });
|
||||||
push[type].forEach(function(s) { map[s.saddr] = s; });
|
self.data[type] = Object.keys(map).map(function(k) { return map[k]; });
|
||||||
self.data[type] = Object.keys(map).map(function(k) { return map[k]; });
|
|
||||||
}
|
/* 增量更新可见页面 DOM (仅更新变化的单元格,不重绘整页) */
|
||||||
|
var tbody = document.getElementById('tbody-' + type);
|
||||||
|
if (!tbody) return;
|
||||||
|
push[type].forEach(function(s) {
|
||||||
|
var row = tbody.querySelector('tr[data-saddr="' + s.saddr.replace(/"/g, '\\"') + '"]');
|
||||||
|
if (!row) return;
|
||||||
|
/* 更新值列 (class=cell-val) */
|
||||||
|
var valCell = row.querySelector('.cell-val');
|
||||||
|
if (valCell && s.val !== undefined) {
|
||||||
|
var nv = (s.val === null || s.val === '') ? '—' : String(s.val);
|
||||||
|
if (valCell.textContent.trim() !== nv) {
|
||||||
|
valCell.textContent = nv;
|
||||||
|
valCell.classList.add('changed');
|
||||||
|
setTimeout(function() { valCell.classList.remove('changed'); }, 600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 更新 ctrl_type 列 (YK/AO) */
|
||||||
|
if (s.ctrl_type !== undefined) {
|
||||||
|
var ctrlCell = row.querySelector('.cell-ctrl');
|
||||||
|
if (ctrlCell) {
|
||||||
|
var ct = (s.ctrl_type == 1) ? (I18n.t('signal.ctrl_sbo') || 'SBO') : (I18n.t('signal.ctrl_direct') || 'Direct');
|
||||||
|
if (ctrlCell.textContent.trim() !== ct) ctrlCell.textContent = ct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Param: 更新定值区值 */
|
||||||
|
if (type === 'param' && s.setting_zone_list) {
|
||||||
|
s.setting_zone_list.forEach(function(z) {
|
||||||
|
var zoneInput = row.querySelector('.param-zone-val[data-zone="' + z.id + '"]');
|
||||||
|
if (zoneInput) {
|
||||||
|
var zv = z.val || '';
|
||||||
|
if (zoneInput.textContent !== zv) zoneInput.textContent = zv;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
this._save();
|
|
||||||
|
/* PLC Debug 页增量刷新 */
|
||||||
|
if (typeof PlcDebugPage !== 'undefined' && PlcDebugPage.incrRefresh) {
|
||||||
|
PlcDebugPage.incrRefresh();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get: function(type) {
|
get: function(type) {
|
||||||
return this.data[type] || [];
|
return this.data[type] || [];
|
||||||
},
|
},
|
||||||
|
|
||||||
addFromPush: function(type, item) {
|
/** @brief 删除信号 (内存 + 立即移除 DOM,不等后端确认) */
|
||||||
this.data[type].push(item);
|
|
||||||
this._save();
|
|
||||||
},
|
|
||||||
|
|
||||||
remove: function(type, saddr) {
|
remove: function(type, saddr) {
|
||||||
this.data[type] = this.data[type].filter(function(s) { return s.saddr !== saddr; });
|
this.data[type] = this.data[type].filter(function(s) { return s.saddr !== saddr; });
|
||||||
this._save();
|
/* 立即从页面移除对应行 */
|
||||||
|
var row = document.querySelector('#tbody-' + type + ' tr[data-saddr="' + saddr.replace(/"/g, '\\"') + '"]');
|
||||||
|
if (row) {
|
||||||
|
row.style.transition = 'opacity 0.2s';
|
||||||
|
row.style.opacity = '0';
|
||||||
|
setTimeout(function() { if (row.parentNode) row.parentNode.removeChild(row); }, 200);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/** @brief 从 localStorage 恢复缓存 */
|
/** @brief 清空所有缓存 (WebSocket 断连时调用) */
|
||||||
restore: function() {
|
clear: function() {
|
||||||
try {
|
this.data = { out: [], yk: [], ao: [], param: [] };
|
||||||
var saved = localStorage.getItem('rtu_signals');
|
|
||||||
if (saved) {
|
|
||||||
var parsed = JSON.parse(saved);
|
|
||||||
if (parsed && parsed.out) { this.data = parsed; }
|
|
||||||
}
|
|
||||||
} catch (e) { /* ignore corrupt data */ }
|
|
||||||
},
|
|
||||||
|
|
||||||
/** @brief 持久化到 localStorage (debounced) */
|
|
||||||
_save: function() {
|
|
||||||
var self = this;
|
|
||||||
if (this._timer) clearTimeout(this._timer);
|
|
||||||
this._timer = setTimeout(function() {
|
|
||||||
try { localStorage.setItem('rtu_signals', JSON.stringify(self.data)); } catch (e) {}
|
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,6 @@ typedef struct
|
||||||
* 全局变量声明
|
* 全局变量声明
|
||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
extern dc_signal_map_t g_dc_out;
|
extern dc_signal_map_t g_dc_out;
|
||||||
extern dc_signal_map_t g_dc_in;
|
|
||||||
extern dc_signal_map_t g_dc_yk;
|
extern dc_signal_map_t g_dc_yk;
|
||||||
extern dc_signal_map_t g_dc_ao;
|
extern dc_signal_map_t g_dc_ao;
|
||||||
extern dc_signal_map_t g_dc_param;
|
extern dc_signal_map_t g_dc_param;
|
||||||
|
|
@ -135,7 +134,6 @@ extern std::unordered_map<std::string, dc_param_meta_t> g_param_metadata;
|
||||||
int dc_core_add(dc_signal_t &signal, dc_signal_map_t &smap);
|
int dc_core_add(dc_signal_t &signal, dc_signal_map_t &smap);
|
||||||
dc_signal_t *dc_core_find(const char *saddr, dc_signal_map_t &smap);
|
dc_signal_t *dc_core_find(const char *saddr, dc_signal_map_t &smap);
|
||||||
dc_signal_t *dc_core_find_out(const char *saddr);
|
dc_signal_t *dc_core_find_out(const char *saddr);
|
||||||
dc_signal_t *dc_core_find_in(const char *saddr);
|
|
||||||
dc_signal_t *dc_core_find_by_id(uint32_t id, dc_signal_map_t &smap);
|
dc_signal_t *dc_core_find_by_id(uint32_t id, dc_signal_map_t &smap);
|
||||||
void dc_core_mark_dirty(dc_signal_t *p_signal);
|
void dc_core_mark_dirty(dc_signal_t *p_signal);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -245,25 +245,6 @@ int dc_signal_out_link_with_callback(const char *saddr, void **p_data,
|
||||||
int dc_set_out_signal_val(const char *saddr, const void *set_data,
|
int dc_set_out_signal_val(const char *saddr, const void *set_data,
|
||||||
const char *module_id);
|
const char *module_id);
|
||||||
|
|
||||||
/* ==================================================================
|
|
||||||
* In 信号注册(输入信号,链接到 out 信号的数据指针)
|
|
||||||
* ================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注册输入信号并链接到输出信号
|
|
||||||
* @param link_saddr 要链接的 out 信号地址
|
|
||||||
* @param p_data 输出:被链接 out 信号的数据指针
|
|
||||||
*/
|
|
||||||
int dc_signal_in(const char *saddr, const char *desc,
|
|
||||||
const char *link_saddr, void **p_data, const char *module_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注册输入信号并绑定回调(回调挂在被链接的 out 信号上)
|
|
||||||
*/
|
|
||||||
int dc_signal_in_with_callback(const char *saddr, const char *desc,
|
|
||||||
const char *link_saddr, void **p_data,
|
|
||||||
dc_out_change_cb_t cb, const char *module_id);
|
|
||||||
|
|
||||||
/* ==================================================================
|
/* ==================================================================
|
||||||
* YK 信号(遥控)
|
* YK 信号(遥控)
|
||||||
* ================================================================== */
|
* ================================================================== */
|
||||||
|
|
@ -419,10 +400,6 @@ int dc_param_register_exec_cb(const char *saddr, dc_async_exec_cb_t exec_cb,
|
||||||
int dc_get_out_signal_info(const char *saddr, char *desc, int desc_len,
|
int dc_get_out_signal_info(const char *saddr, char *desc, int desc_len,
|
||||||
uint8_t *data_type, void **p_data);
|
uint8_t *data_type, void **p_data);
|
||||||
|
|
||||||
/** @brief 查询 in 信号信息 */
|
|
||||||
int dc_get_in_signal_info(const char *saddr, char *desc, int desc_len,
|
|
||||||
uint8_t *data_type, void **p_data);
|
|
||||||
|
|
||||||
/** @brief 查询 AO 信号信息(含参数元数据) */
|
/** @brief 查询 AO 信号信息(含参数元数据) */
|
||||||
int dc_get_ao_signal_info(const char *saddr, char *desc, int desc_len,
|
int dc_get_ao_signal_info(const char *saddr, char *desc, int desc_len,
|
||||||
uint8_t *data_type, dc_param_meta_t *p_meta,
|
uint8_t *data_type, dc_param_meta_t *p_meta,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
#include "dc_internal.h"
|
#include "dc_internal.h"
|
||||||
|
|
||||||
dc_signal_map_t g_dc_out = {};
|
dc_signal_map_t g_dc_out = {};
|
||||||
dc_signal_map_t g_dc_in = {};
|
|
||||||
dc_signal_map_t g_dc_yk = {};
|
dc_signal_map_t g_dc_yk = {};
|
||||||
dc_signal_map_t g_dc_ao = {};
|
dc_signal_map_t g_dc_ao = {};
|
||||||
dc_signal_map_t g_dc_param = {};
|
dc_signal_map_t g_dc_param = {};
|
||||||
|
|
@ -100,12 +99,6 @@ dc_signal_t *dc_core_find_out(const char *saddr)
|
||||||
return dc_core_find(saddr, g_dc_out);
|
return dc_core_find(saddr, g_dc_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief 快捷查找 in 信号 */
|
|
||||||
dc_signal_t *dc_core_find_in(const char *saddr)
|
|
||||||
{
|
|
||||||
return dc_core_find(saddr, g_dc_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief 按 ID 查找信号(O(1)) */
|
/** @brief 按 ID 查找信号(O(1)) */
|
||||||
dc_signal_t *dc_core_find_by_id(uint32_t id, dc_signal_map_t &smap)
|
dc_signal_t *dc_core_find_by_id(uint32_t id, dc_signal_map_t &smap)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
/** @file dc_signal_in.cpp — In 信号注册 */
|
|
||||||
#include "dc_internal.h"
|
|
||||||
|
|
||||||
/** @brief In 信号注册内部实现:关联 out 信号、建立链接、追加回调 */
|
|
||||||
static int dc_in_register_impl(const char *saddr, const char *desc, const char *link_saddr, void **p_data, dc_out_change_cb_t cb, const char *module_id)
|
|
||||||
{
|
|
||||||
if (!g_initialized || !saddr || !link_saddr || !p_data || !module_id)
|
|
||||||
{
|
|
||||||
return DC_ERR_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!link_saddr[0])
|
|
||||||
{
|
|
||||||
return DC_ERR_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dc_core_find_in(saddr))
|
|
||||||
{
|
|
||||||
LOG_E("in %s exists\n", saddr);
|
|
||||||
|
|
||||||
return DC_ERR_EXISTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_signal_t *ps_out = dc_core_find_out(link_saddr);
|
|
||||||
|
|
||||||
if (!ps_out)
|
|
||||||
{
|
|
||||||
LOG_E("link out %s not found\n", link_saddr);
|
|
||||||
|
|
||||||
return DC_ERR_NOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
*p_data = ps_out->vec_p_data[0];
|
|
||||||
|
|
||||||
dc_signal_t sig = {};
|
|
||||||
|
|
||||||
sig.hash = XXH3_128bits(saddr, strlen(saddr));
|
|
||||||
strncpy(sig.saddr, saddr, DC_SADDR_MAX_LEN - 1);
|
|
||||||
|
|
||||||
if (desc)
|
|
||||||
{
|
|
||||||
strncpy(sig.desc, desc, DC_DESC_MAX_LEN - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sig.data_type = ps_out->data_type;
|
|
||||||
strncpy(sig.link_saddr, link_saddr, DC_SADDR_MAX_LEN - 1);
|
|
||||||
sig.vec_p_data = (void **)malloc(sizeof(void *));
|
|
||||||
sig.vec_p_data[0] = *p_data;
|
|
||||||
sig.vec_p_data_count = 1;
|
|
||||||
|
|
||||||
/* out 记录 in 的链接 */
|
|
||||||
char **nl = (char **)realloc(ps_out->link_saddrs, (ps_out->link_count + 1) * sizeof(char *));
|
|
||||||
|
|
||||||
nl[ps_out->link_count] = strdup(saddr);
|
|
||||||
ps_out->link_saddrs = nl;
|
|
||||||
ps_out->link_count++;
|
|
||||||
|
|
||||||
if (cb && ps_out->cb_count < DC_MAX_CALLBACKS)
|
|
||||||
{
|
|
||||||
strncpy(ps_out->cb_list[ps_out->cb_count].module_id, module_id, DC_MODULE_MAX_LEN - 1);
|
|
||||||
ps_out->cb_list[ps_out->cb_count].out_cb = cb;
|
|
||||||
ps_out->cb_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dc_core_add(sig, g_dc_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief 注册 in 信号(链接到 out,无回调) */
|
|
||||||
int dc_signal_in(const char *saddr, const char *desc, const char *link_saddr, void **p_data, const char *module_id)
|
|
||||||
{
|
|
||||||
return dc_in_register_impl(saddr, desc, link_saddr, p_data, NULL, module_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief 注册 in 信号(链接到 out,带变更回调) */
|
|
||||||
int dc_signal_in_with_callback(const char *saddr, const char *desc, const char *link_saddr, void **p_data, dc_out_change_cb_t cb, const char *module_id)
|
|
||||||
{
|
|
||||||
return dc_in_register_impl(saddr, desc, link_saddr, p_data, cb, module_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -43,13 +43,6 @@ int dc_get_out_signal_info(const char *saddr, char *desc, int desc_len,
|
||||||
return dc_query_info(&g_dc_out, saddr, desc, desc_len, data_type, p_data);
|
return dc_query_info(&g_dc_out, saddr, desc, desc_len, data_type, p_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief 查询 in 信号信息 */
|
|
||||||
int dc_get_in_signal_info(const char *saddr, char *desc, int desc_len,
|
|
||||||
uint8_t *data_type, void **p_data)
|
|
||||||
{
|
|
||||||
return dc_query_info(&g_dc_in, saddr, desc, desc_len, data_type, p_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief 查询 AO 信号信息(含参数元数据和控型) */
|
/** @brief 查询 AO 信号信息(含参数元数据和控型) */
|
||||||
int dc_get_ao_signal_info(const char *saddr, char *desc, int desc_len,
|
int dc_get_ao_signal_info(const char *saddr, char *desc, int desc_len,
|
||||||
uint8_t *data_type, dc_param_meta_t *p_meta, uint8_t *ctrl_type,
|
uint8_t *data_type, dc_param_meta_t *p_meta, uint8_t *ctrl_type,
|
||||||
|
|
@ -220,10 +213,6 @@ int dc_get_signal_count(const char *type_str)
|
||||||
{
|
{
|
||||||
pmap = &g_dc_out;
|
pmap = &g_dc_out;
|
||||||
}
|
}
|
||||||
else if (0 == strcmp(type_str, "in"))
|
|
||||||
{
|
|
||||||
pmap = &g_dc_in;
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(type_str, "yk"))
|
else if (0 == strcmp(type_str, "yk"))
|
||||||
{
|
{
|
||||||
pmap = &g_dc_yk;
|
pmap = &g_dc_yk;
|
||||||
|
|
@ -263,10 +252,6 @@ int dc_get_signal_info_by_id(const char *type_str, uint32_t id,
|
||||||
{
|
{
|
||||||
pmap = &g_dc_out;
|
pmap = &g_dc_out;
|
||||||
}
|
}
|
||||||
else if (0 == strcmp(type_str, "in"))
|
|
||||||
{
|
|
||||||
pmap = &g_dc_in;
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(type_str, "yk"))
|
else if (0 == strcmp(type_str, "yk"))
|
||||||
{
|
{
|
||||||
pmap = &g_dc_yk;
|
pmap = &g_dc_yk;
|
||||||
|
|
|
||||||
|
|
@ -99,11 +99,6 @@ static void cmd_dc_func(int argc, char *argv[])
|
||||||
printf("out signals:\n");
|
printf("out signals:\n");
|
||||||
dc_show_signals(g_dc_out);
|
dc_show_signals(g_dc_out);
|
||||||
}
|
}
|
||||||
else if (0 == strcmp(argv[1], "in"))
|
|
||||||
{
|
|
||||||
printf("in signals:\n");
|
|
||||||
dc_show_signals(g_dc_in);
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(argv[1], "yk"))
|
else if (0 == strcmp(argv[1], "yk"))
|
||||||
{
|
{
|
||||||
printf("yk signals:\n");
|
printf("yk signals:\n");
|
||||||
|
|
@ -123,8 +118,6 @@ static void cmd_dc_func(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
printf("out signals:\n");
|
printf("out signals:\n");
|
||||||
dc_show_signals(g_dc_out);
|
dc_show_signals(g_dc_out);
|
||||||
printf("in signals:\n");
|
|
||||||
dc_show_signals(g_dc_in);
|
|
||||||
printf("yk signals:\n");
|
printf("yk signals:\n");
|
||||||
dc_show_signals(g_dc_yk);
|
dc_show_signals(g_dc_yk);
|
||||||
printf("ao signals:\n");
|
printf("ao signals:\n");
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
* - Kahn 拓扑排序 (保证节点按依赖顺序执行, 检测环路)
|
* - Kahn 拓扑排序 (保证节点按依赖顺序执行, 检测环路)
|
||||||
* - 非阻塞定时器 (clock_gettime CLOCK_MONOTONIC)
|
* - 非阻塞定时器 (clock_gettime CLOCK_MONOTONIC)
|
||||||
* - mtime 文件变化检测 (stat, 仅在 XML 更新时重新解析)
|
* - mtime 文件变化检测 (stat, 仅在 XML 更新时重新解析)
|
||||||
* - 与 self_ptl 遥信联动 (dc_signal_in 链接到 self_ptl 配置的遥信信号)
|
* - 与 self_ptl 遥信联动 (dc_signal_out_link_with_callback 链接到 self_ptl 配置的遥信信号)
|
||||||
* - 经 datacenter 写入 out 信号 (dc_set_out_signal_val)
|
* - 经 datacenter 写入 out 信号 (dc_set_out_signal_val)
|
||||||
*
|
*
|
||||||
* 线程模型: X-Macro 框架 app_plc 线程, EV_TIMER3(1s) 触发 PLC_Logic()
|
* 线程模型: X-Macro 框架 app_plc 线程, EV_TIMER3(1s) 触发 PLC_Logic()
|
||||||
|
|
@ -1788,20 +1788,16 @@ int app_plc_init1(void *arg)
|
||||||
int app_plc_init2(void *arg)
|
int app_plc_init2(void *arg)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
ret |= dc_signal_in("plc.run_cnt_in", "plc.run_cnt_in", "plc.run_cnt", (void **)&gp_run_cnt_in, "plc");
|
ret |= dc_signal_out_link_with_callback("plc.run_cnt", (void **)&gp_run_cnt_in, NULL, "plc");
|
||||||
|
|
||||||
for (uint32_t i = 0; i < g_plc_cfg.size(); i++)
|
for (uint32_t i = 0; i < g_plc_cfg.size(); i++)
|
||||||
{
|
{
|
||||||
stru_plc_cfg *p = &g_plc_cfg[i];
|
stru_plc_cfg *p = &g_plc_cfg[i];
|
||||||
char saddr[64];
|
ret |= dc_signal_out_link_with_callback(p->base.saddr.c_str(), (void **)&p->p_data, NULL, "plc");
|
||||||
char desc[64];
|
|
||||||
snprintf(saddr, sizeof(saddr), "plc.st.in.%d", i);
|
|
||||||
snprintf(desc, sizeof(desc), "plc链接遥信%d", i);
|
|
||||||
ret |= dc_signal_in(saddr, desc, p->base.saddr.c_str(), (void **)&p->p_data, "plc");
|
|
||||||
}
|
}
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
LOG_E("app_plc_init2 dc_signal_in failed");
|
LOG_E("app_plc_init2 dc_signal_out_link_with_callback failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
* 功能:
|
* 功能:
|
||||||
* - HTTP 静态文件服务(packed_fs 内嵌前端)
|
* - HTTP 静态文件服务(packed_fs 内嵌前端)
|
||||||
* - WebSocket 信号实时推送(增量更新)
|
* - WebSocket 信号实时推送(增量更新)
|
||||||
* - 5 种信号类型增删改查(out/in/yk/ao/param)
|
* - 4 种信号类型增删改查(out/yk/ao/param)
|
||||||
* - 远程命令执行(捕获 stdout 回传)
|
* - 远程命令执行(捕获 stdout 回传)
|
||||||
* - 文件上传/下载
|
* - 文件上传/下载
|
||||||
* - 异步命令输出通道
|
* - 异步命令输出通道
|
||||||
|
|
@ -29,10 +29,9 @@ extern "C"
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
WS_SIG_OUT = 0,
|
WS_SIG_OUT = 0,
|
||||||
WS_SIG_IN,
|
WS_SIG_YK = 1,
|
||||||
WS_SIG_YK,
|
WS_SIG_AO = 2,
|
||||||
WS_SIG_AO,
|
WS_SIG_PARAM = 3,
|
||||||
WS_SIG_PARAM,
|
|
||||||
WS_SIG_MAX
|
WS_SIG_MAX
|
||||||
} enum_ws_sig_type;
|
} enum_ws_sig_type;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ typedef struct
|
||||||
static std::map<unsigned long, stru_ws_session> g_ws_sessions;
|
static std::map<unsigned long, stru_ws_session> g_ws_sessions;
|
||||||
static pthread_mutex_t g_ws_session_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t g_ws_session_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/* WebSocket 收发包日志开关(默认关闭,通过 web_log on/off 控制) */
|
||||||
|
static int g_ws_rx_log = 0;
|
||||||
|
|
||||||
/* ---- 前向声明 ---- */
|
/* ---- 前向声明 ---- */
|
||||||
static int ws_make_sig_json(stru_ws_session *s, cJSON *root, enum_ws_sig_type st, bool *has_change);
|
static int ws_make_sig_json(stru_ws_session *s, cJSON *root, enum_ws_sig_type st, bool *has_change);
|
||||||
static void ws_sig_add(stru_ws_session *s, enum_ws_sig_type st, const char *saddr);
|
static void ws_sig_add(stru_ws_session *s, enum_ws_sig_type st, const char *saddr);
|
||||||
|
|
@ -52,7 +55,7 @@ static int ws_sig_set(stru_ws_session *s, enum_ws_sig_type st, const char *sadd
|
||||||
/* ---- 函数表: 信号类型 → 名称 ---- */
|
/* ---- 函数表: 信号类型 → 名称 ---- */
|
||||||
static const char *g_ws_sig_names[WS_SIG_MAX] =
|
static const char *g_ws_sig_names[WS_SIG_MAX] =
|
||||||
{
|
{
|
||||||
"out", "in", "yk", "ao", "param"
|
"out", "yk", "ao", "param"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
|
|
@ -112,33 +115,6 @@ static void ws_sig_add_out(stru_ws_session *s, const char *saddr)
|
||||||
vec.push_back(sig);
|
vec.push_back(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ws_sig_add_in(stru_ws_session *s, const char *saddr)
|
|
||||||
{
|
|
||||||
std::vector<stru_ws_sig> &vec = s->signals[WS_SIG_IN];
|
|
||||||
void *p_data = NULL;
|
|
||||||
|
|
||||||
if (ws_sig_find_idx(vec, saddr) >= 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stru_ws_sig sig;
|
|
||||||
sig.saddr = saddr;
|
|
||||||
|
|
||||||
char desc[128] = {0};
|
|
||||||
|
|
||||||
if (0 != dc_get_in_signal_info(saddr, desc, sizeof(desc), &sig.data_type, &p_data))
|
|
||||||
{
|
|
||||||
LOG_E("dc_get_in_signal_info failed: %s", saddr);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sig.desc = desc;
|
|
||||||
sig.vec_p_data.push_back(p_data);
|
|
||||||
vec.push_back(sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ws_sig_add_yk(stru_ws_session *s, const char *saddr)
|
static void ws_sig_add_yk(stru_ws_session *s, const char *saddr)
|
||||||
{
|
{
|
||||||
std::vector<stru_ws_sig> &vec = s->signals[WS_SIG_YK];
|
std::vector<stru_ws_sig> &vec = s->signals[WS_SIG_YK];
|
||||||
|
|
@ -231,7 +207,6 @@ static void ws_sig_add(stru_ws_session *s, enum_ws_sig_type st, const char *sadd
|
||||||
switch (st)
|
switch (st)
|
||||||
{
|
{
|
||||||
case WS_SIG_OUT: ws_sig_add_out(s, saddr); break;
|
case WS_SIG_OUT: ws_sig_add_out(s, saddr); break;
|
||||||
case WS_SIG_IN: ws_sig_add_in(s, saddr); break;
|
|
||||||
case WS_SIG_YK: ws_sig_add_yk(s, saddr); break;
|
case WS_SIG_YK: ws_sig_add_yk(s, saddr); break;
|
||||||
case WS_SIG_AO: ws_sig_add_ao(s, saddr); break;
|
case WS_SIG_AO: ws_sig_add_ao(s, saddr); break;
|
||||||
case WS_SIG_PARAM: ws_sig_add_param(s, saddr); break;
|
case WS_SIG_PARAM: ws_sig_add_param(s, saddr); break;
|
||||||
|
|
@ -274,12 +249,6 @@ static int ws_sig_set(stru_ws_session *s, enum_ws_sig_type st, const char *saddr
|
||||||
case WS_SIG_OUT:
|
case WS_SIG_OUT:
|
||||||
return dc_set_out_signal_val(saddr, data, MODULE_WEB_SERVER);
|
return dc_set_out_signal_val(saddr, data, MODULE_WEB_SERVER);
|
||||||
|
|
||||||
case WS_SIG_IN:
|
|
||||||
/* in 信号只读 */
|
|
||||||
LOG_E("set in signal not supported: %s", saddr);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case WS_SIG_YK:
|
case WS_SIG_YK:
|
||||||
{
|
{
|
||||||
dc_ctrl_t ctrl;
|
dc_ctrl_t ctrl;
|
||||||
|
|
@ -483,6 +452,18 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buf[256] = {0};
|
||||||
|
int copy_len = (int)rx_len < 255 ? (int)rx_len : 255;
|
||||||
|
memcpy(buf, p_rx, (size_t)copy_len);
|
||||||
|
buf[copy_len] = '\0';
|
||||||
|
|
||||||
|
if (g_ws_rx_log)
|
||||||
|
{
|
||||||
|
LOG_I("WS recv %uB: %s", rx_len, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cJSON *root = cJSON_Parse(p_rx);
|
cJSON *root = cJSON_Parse(p_rx);
|
||||||
|
|
||||||
if (!root)
|
if (!root)
|
||||||
|
|
@ -529,13 +510,12 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 构建信号元数据 JSON */
|
/* 构建信号元数据 JSON */
|
||||||
const char *dc_types[5];
|
const char *dc_types[4];
|
||||||
int dc_type_count = 0;
|
int dc_type_count = 0;
|
||||||
|
|
||||||
if (0 == strcmp(sub, "all") || 0 == strncmp(sub, "all ", 4))
|
if (0 == strcmp(sub, "all") || 0 == strncmp(sub, "all ", 4))
|
||||||
{
|
{
|
||||||
dc_types[dc_type_count++] = "out";
|
dc_types[dc_type_count++] = "out";
|
||||||
dc_types[dc_type_count++] = "in";
|
|
||||||
dc_types[dc_type_count++] = "yk";
|
dc_types[dc_type_count++] = "yk";
|
||||||
dc_types[dc_type_count++] = "ao";
|
dc_types[dc_type_count++] = "ao";
|
||||||
dc_types[dc_type_count++] = "param";
|
dc_types[dc_type_count++] = "param";
|
||||||
|
|
@ -544,10 +524,6 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
{
|
{
|
||||||
dc_types[dc_type_count++] = "out";
|
dc_types[dc_type_count++] = "out";
|
||||||
}
|
}
|
||||||
else if (0 == strcmp(sub, "in") || 0 == strncmp(sub, "in ", 3))
|
|
||||||
{
|
|
||||||
dc_types[dc_type_count++] = "in";
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(sub, "yk") || 0 == strncmp(sub, "yk ", 3))
|
else if (0 == strcmp(sub, "yk") || 0 == strncmp(sub, "yk ", 3))
|
||||||
{
|
{
|
||||||
dc_types[dc_type_count++] = "yk";
|
dc_types[dc_type_count++] = "yk";
|
||||||
|
|
@ -564,7 +540,6 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
{
|
{
|
||||||
/* 默认返回全部 */
|
/* 默认返回全部 */
|
||||||
dc_types[dc_type_count++] = "out";
|
dc_types[dc_type_count++] = "out";
|
||||||
dc_types[dc_type_count++] = "in";
|
|
||||||
dc_types[dc_type_count++] = "yk";
|
dc_types[dc_type_count++] = "yk";
|
||||||
dc_types[dc_type_count++] = "ao";
|
dc_types[dc_type_count++] = "ao";
|
||||||
dc_types[dc_type_count++] = "param";
|
dc_types[dc_type_count++] = "param";
|
||||||
|
|
@ -614,7 +589,7 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
|
|
||||||
if (dc_tx)
|
if (dc_tx)
|
||||||
{
|
{
|
||||||
ws_send_binary(c->id, dc_tx, strlen(dc_tx));
|
ws_send_one(c->id, dc_tx, strlen(dc_tx));
|
||||||
free(dc_tx);
|
free(dc_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -682,7 +657,7 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
|
|
||||||
if (0 == func_proc_self_dir(proc_dir, sizeof(proc_dir)))
|
if (0 == func_proc_self_dir(proc_dir, sizeof(proc_dir)))
|
||||||
{
|
{
|
||||||
snprintf(resolved, sizeof(resolved), "%s%s", proc_dir, jpath->valuestring);
|
snprintf(resolved, sizeof(resolved), "%s/%s", proc_dir, jpath->valuestring);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -753,7 +728,7 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
|
|
||||||
if (0 == func_proc_self_dir(proc_dir, sizeof(proc_dir)))
|
if (0 == func_proc_self_dir(proc_dir, sizeof(proc_dir)))
|
||||||
{
|
{
|
||||||
snprintf(resolved, sizeof(resolved), "%s%s", proc_dir, jpath->valuestring);
|
snprintf(resolved, sizeof(resolved), "%s/%s", proc_dir, jpath->valuestring);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -838,6 +813,7 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
|
|
||||||
if (0 == strcmp(curd, "add"))
|
if (0 == strcmp(curd, "add"))
|
||||||
{
|
{
|
||||||
|
if (g_ws_rx_log) LOG_I("WS add %s %s", g_ws_sig_names[st], saddr);
|
||||||
ws_sig_add(&sess, st, saddr);
|
ws_sig_add(&sess, st, saddr);
|
||||||
|
|
||||||
/* 立即推送当前状态 */
|
/* 立即推送当前状态 */
|
||||||
|
|
@ -858,6 +834,7 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
}
|
}
|
||||||
else if (0 == strcmp(curd, "del"))
|
else if (0 == strcmp(curd, "del"))
|
||||||
{
|
{
|
||||||
|
if (g_ws_rx_log) LOG_I("WS del %s %s", g_ws_sig_names[st], saddr);
|
||||||
ws_sig_del(&sess, st, saddr);
|
ws_sig_del(&sess, st, saddr);
|
||||||
|
|
||||||
cJSON *push = cJSON_CreateObject();
|
cJSON *push = cJSON_CreateObject();
|
||||||
|
|
@ -877,6 +854,7 @@ void ws_recv(struct mg_connection *c, const char *p_rx, uint16_t rx_len)
|
||||||
}
|
}
|
||||||
else if (0 == strcmp(curd, "set"))
|
else if (0 == strcmp(curd, "set"))
|
||||||
{
|
{
|
||||||
|
if (g_ws_rx_log) LOG_I("WS set %s %s = %s (zone=%u)", g_ws_sig_names[st], saddr, sig_data, zone);
|
||||||
ws_sig_set(&sess, st, saddr, zone, sig_data);
|
ws_sig_set(&sess, st, saddr, zone, sig_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -897,3 +875,50 @@ void ws_session_destroy(struct mg_connection *c)
|
||||||
g_ws_sessions.erase(c->id);
|
g_ws_sessions.erase(c->id);
|
||||||
pthread_mutex_unlock(&g_ws_session_mutex);
|
pthread_mutex_unlock(&g_ws_session_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================================
|
||||||
|
* web_log 命令 — 控制 WebSocket 收发包日志
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
/** @brief web_log 命令补全 */
|
||||||
|
LOCAL void cmd_web_log_complete(const char *buf, char ***completions, int *ncomp)
|
||||||
|
{
|
||||||
|
static const char *subs[] = {"on", "off", "status"};
|
||||||
|
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs) / sizeof(subs[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief web_log 命令处理 */
|
||||||
|
LOCAL void cmd_web_log(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *usage =
|
||||||
|
"web_log on 打开 WS 收发包日志\n"
|
||||||
|
"web_log off 关闭 WS 收发包日志\n"
|
||||||
|
"web_log status 查看当前状态\n";
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("%s", usage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == strcmp(argv[1], "on"))
|
||||||
|
{
|
||||||
|
g_ws_rx_log = 1;
|
||||||
|
printf("WS log: ON\n");
|
||||||
|
}
|
||||||
|
else if (0 == strcmp(argv[1], "off"))
|
||||||
|
{
|
||||||
|
g_ws_rx_log = 0;
|
||||||
|
printf("WS log: OFF\n");
|
||||||
|
}
|
||||||
|
else if (0 == strcmp(argv[1], "status"))
|
||||||
|
{
|
||||||
|
printf("WS log: %s\n", g_ws_rx_log ? "ON" : "OFF");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("未知子命令: %s\n%s", argv[1], usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CMD_REGISTER_C("web_log", cmd_web_log, "WebSocket 收发包日志开关", cmd_web_log_complete);
|
||||||
|
|
|
||||||
|
|
@ -230,44 +230,6 @@ static void test_out_signal(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 测试 3:in 信号注册
|
|
||||||
*/
|
|
||||||
static void test_in_signal(void)
|
|
||||||
{
|
|
||||||
TEST("dc_signal_in()");
|
|
||||||
{
|
|
||||||
void *p = NULL;
|
|
||||||
int r = dc_signal_in("RPC1:YC:1:in", "test in", "RPC1:YC:1",
|
|
||||||
&p, "protocol");
|
|
||||||
|
|
||||||
if (DC_OK != r || !p)
|
|
||||||
{
|
|
||||||
FAIL("in register failed");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST("dc_signal_in() bad link");
|
|
||||||
{
|
|
||||||
void *p = NULL;
|
|
||||||
int r = dc_signal_in("RPC1:YC:99:in", "bad", "RPC1:YC:99",
|
|
||||||
&p, "protocol");
|
|
||||||
|
|
||||||
if (DC_ERR_NOTFOUND != r)
|
|
||||||
{
|
|
||||||
FAIL("bad link should return NOTFOUND");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OK();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 测试 4:yk 信号 + 同步控制
|
* @brief 测试 4:yk 信号 + 同步控制
|
||||||
*/
|
*/
|
||||||
|
|
@ -862,7 +824,6 @@ int main(void)
|
||||||
|
|
||||||
/* 信号注册 */
|
/* 信号注册 */
|
||||||
test_out_signal();
|
test_out_signal();
|
||||||
test_in_signal();
|
|
||||||
test_yk_signal();
|
test_yk_signal();
|
||||||
test_ao_signal();
|
test_ao_signal();
|
||||||
test_param_signal();
|
test_param_signal();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue