完成除数据查询前端功能的EDataCapture开发

This commit is contained in:
Yu Sun
2022-07-09 14:30:23 +08:00
parent e018f19f09
commit be6c61b9d3
7 changed files with 176 additions and 71 deletions

View File

@@ -11,7 +11,7 @@ $options = getopt('h::', ['server_name:', 'user:', 'password:', 'help::']);
init_db($options['server_name'], $options['user'], $options['password']);
$worker = new Worker('http://0.0.0.0:1818');
$worker = new Worker('http://0.0.0.0:8888');
$worker -> name = 'CaptureWorker';
$worker -> onWorkerStart = function(Worker $worker) {
@@ -30,9 +30,40 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
unset($post['action']);
$enode_configure = new ENodeConfigure($dbconn, $post = $post);
$res = $enode_configure -> $action();
if ($res)
$connection -> send(json_encode(array ('code' => 0,
'msg' => 'Set threshold success')));
if ($res === true)
$connection -> send(json_encode(array(
'code' => 0,
'msg' => 'Success'
)));
else if ($res === "REPLICATED")
$connection -> send(json_encode(array(
'code' => 1,
'msg' => '节点编码不可重复!'
)));
else if ($res === false) {
$connection -> send(json_encode(array(
'code' => 1,
'msg' => '服务器内部逻辑错误,请联系开发者!'
)));
}
} else if (isset($post['action']) and str_contains($post['action'], 'data')) {
$action = $post['action'];
unset($post['action']);
$data_capture = new EDataCapture($dbconn, $post = $post);
$res = $data_capture -> $action();
if ($res === true) {
$connection -> send(json_encode(array(
'action' => 'result_set_data',
'errcode' => 0,
'errmsg' => ''
)));
} else {
$connection -> send(json_encode(array(
'action' => 'result_set_data',
'errcode' => 4002,
'errmsg' => 'ROLLBACKed: Bad data received (structure and/or values)'
)));
}
}
$get = $request -> get();
@@ -40,9 +71,15 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
$enode_configure = new ENodeConfigure($dbconn, $get = $get);
$nodes = $enode_configure -> get_nodes();
if (is_null($nodes))
$connection -> send(json_encode(array('code' => 1, 'msg' => 'no node data')));
$connection -> send(json_encode(array(
'code' => 1,
'msg' => 'no node data'
)));
else
$connection -> send(json_encode(array('code' => 0, 'data' => $nodes)));
$connection -> send(json_encode(array(
'code' => 0,
'data' => $nodes
)));
}
};

View File

@@ -2,7 +2,31 @@
namespace EdgeManager\EDataCapture;
class EDataCapture {
// 我不主张在构造函数内实现类型检查,因为在请求过于密集、记录较多时会严重影响性能
// 请使用SCADA系统的开发人员自觉遵守文档内规范
function __construct(
protected $dbconn,
protected $post = NULL,
protected $get = NULL
) {}
private function set_data() {
foreach (array_chunk($this -> post -> param, 6507524, true) as $chunk) {
$sql_cmd[] = [sprintf(
"INSERT INTO hf_mes_scada_data_capture_node_data_%s",
$chunk[0] -> working_subclass
)];
foreach ($chunk as $row) {
$sql_cmd[] = sprintf(
"(code, v_%s, device_code, batch) VALUES('%s', %s, %s, %s)",
$row -> type,
$row -> code,
$row -> value,
$row -> device_code ?? NULL,
$row -> batch ?? NULL
);
}
return pg_query($this -> dbconn, implode(' ', $sql_cmd));
}
}
}
}

View File

@@ -9,11 +9,20 @@ class ENodeConfigure {
) {}
function add_node() {
$table_name = "hf_mes_scada_data_capture_node_data_" . $this -> post['process_code'];
$exists = pg_query(sprintf(
"SELECT EXISTS(
SELECT 1 FROM hf_mes_scada_data_capture_node_configure WHERE code='%s'
)", $this -> post['code']
));
if (pg_fetch_assoc($exists)['exists'] == 't') {
return "REPLICATED";
}
$table_name = "hf_mes_scada_data_capture_node_data_" . $this -> post['working_subclass'];
pg_query($this -> dbconn, "BEGIN");
$res1 = pg_query($this -> dbconn, sprintf(
"CREATE TABLE IF NOT EXISTS %s(
$res[] = pg_query($this -> dbconn, sprintf(
"CREATE TABLE IF NOT EXISTS %s (
id serial8,
code text references hf_mes_scada_data_capture_node_configure(code),
v_string text,
@@ -22,35 +31,70 @@ class ENodeConfigure {
v_bool bool,
device_code text,
batch text,
create_date timestamp
capture_time timestamp NOT NULL DEFAULT NOW()
)", $table_name
));
$res2 = pg_insert(
$res[] = pg_insert(
$this -> dbconn,
'hf_mes_scada_data_capture_node_configure',
$this -> post
);
if ($res1 and $res2)
pg_query($this -> dbconn, "COMMIT");
else
pg_query($this -> dbconn, "ROLLBACK");
pg_query($this -> dbconn, sprintf("SELECT create_hypertable('%s','create_date')", $table_name));
pg_query($this -> dbconn, sprintf(
"CREATE INDEX ON %s (v_string, v_int, v_float, v_bool, create_date DESC)
WHERE COALESCE(v_string, v_int::text, v_float::text, v_bool::text) IS NOT NULL
// 检查一下,如果超表已经有了就不要尝试重复创建了
$table_exists = pg_query(sprintf(
"SELECT *
FROM timescaledb_information.hypertables
WHERE hypertable_name = '%s'
", $table_name
));
if (!in_array($table_name, pg_fetch_all_columns($table_exists, 1))) {
$res[] = pg_query($this -> dbconn, sprintf("SELECT create_hypertable('%s', 'capture_time')", $table_name));
$res[] = pg_query($this -> dbconn, sprintf(
"CREATE INDEX ON %s (v_string, v_int, v_float, v_bool, capture_time DESC)
WHERE COALESCE(v_string, v_int::text, v_float::text, v_bool::text) IS NOT NULL
", $table_name
));
}
if (in_array(false, $res)) {
pg_query($this -> dbconn, "ROLLBACK");
return false;
} else {
pg_query($this -> dbconn, "COMMIT");
return true;
}
}
function remove_node() {
pg_query($this -> dbconn, "BEGIN");
$res[] = pg_delete(
$this -> dbconn,
'hf_mes_scada_data_capture_node_configure',
$this -> post,
);
$exists = pg_query(sprintf(
"SELECT EXISTS(
SELECT 1 FROM hf_mes_scada_data_capture_node_configure WHERE code='%s'
)", $this -> post['working_subclass']
));
if (pg_fetch_assoc($exists)['exists'] == 'f') {
$res[] = pg_query(sprintf(
"DROP TABLE hf_mes_scada_data_capture_node_data_%s",
$this -> post['working_subclass']
));
}
if (in_array(false, $res)) {
pg_query($this -> dbconn, "ROLLBACK");
return false;
} else {
pg_query($this -> dbconn, "COMMIT");
return true;
}
}
function update_node() {
return pg_update(
$this -> dbconn,
$this -> dbconn,
'hf_mes_scada_data_capture_node_configure',
$this -> post,
['code' => $this -> post['code']]
@@ -61,4 +105,4 @@ class ENodeConfigure {
$res = pg_query($this -> dbconn, "SELECT * FROM hf_mes_scada_data_capture_node_configure");
return pg_fetch_all($res);
}
}
}

View File

@@ -2,20 +2,21 @@
function init_db($server_name, $user, $password) {
$dbconn = pg_connect(sprintf("host=%s user=%s password=%s", $server_name, $user, $password));
$res = pg_query("select datname from pg_database");
if (find_key_value(pg_fetch_assoc($res), 'datname', 'scada'))
if (!in_array('scada', pg_fetch_all_columns($res, 0)))
pg_query("CREATE DATABASE scada");
pg_close($dbconn);
$dbconn = pg_connect(sprintf("host=%s dbname=scada user=%s password=%s", $server_name, $user, $password));
pg_query("CREATE TABLE IF NOT EXISTS hf_mes_scada_data_capture_node_configure (
id serial2,
code text primary key,
name text,
type text,
code text primary key NOT NULL,
name text NOT NULL,
type text NOT NULL,
flow_code text,
process_code text,
working_subclass text NOT NULL,
workstation text,
create_date timestamp,
create_date timestamp NOT NULL DEFAULT NOW(),
note text
)");
pg_close($dbconn);

View File

@@ -1,23 +1,18 @@
const handlePost = (request, data) => (request({
url: '',
method: 'post',
data
}))
export default ({ service, request, serviceForMock, requestForMock, mock, faker, tools }) => ({
/**
* @description 方法名称
* @param {Object} data 请求携带的信息
*/
ADD_NODE (data) {
return request({
url: '',
method: 'post',
data
})
},
UPDATE_NODE (data) {
return request({
url: '',
method: 'post',
data
})
},
ADD_NODE: (data) => handlePost(request, data),
UPDATE_NODE: (data) => handlePost(request, data),
REMOVE_NODE: (data) => handlePost(request, data),
QUERY_NODE () {
return request({ url: '?query=nodes' })

View File

@@ -21,7 +21,7 @@
</template>
<script>
import { assign, each, pickBy, startsWith } from 'lodash'
import { assign, each, pick, pickBy, startsWith } from 'lodash'
export default {
data () {
@@ -48,8 +48,8 @@ export default {
key: 'flow_code'
},
{
title: '工序编码',
key: 'process_code'
title: '工序单元',
key: 'working_subclass'
},
{
title: '工作站',
@@ -57,7 +57,7 @@ export default {
},
{
title: '创建时间',
key: 'create_time'
key: 'create_date'
},
{
title: '备注',
@@ -127,8 +127,8 @@ export default {
flow_code: {
title: '流程'
},
process_code: {
title: '工序编码'
working_subclass: {
title: '工序单元'
},
workstation: {
title: '工作站'
@@ -160,7 +160,7 @@ export default {
code: [{ required: true, type: 'string', message: '节点编码必须填写', trigger: 'blur' }],
name: [{ required: true, type: 'string', message: '节点名称必须填写', trigger: 'blur' }],
type: [{ required: true, message: '必须指定节点类型', trigger: 'blur' }],
process_code: [{ required: true, type: 'string', message: '工序编码必须填写', trigger: 'blur' }]
working_subclass: [{ required: true, type: 'string', message: '工序单元必须填写', trigger: 'blur' }]
}
}
},
@@ -184,38 +184,42 @@ export default {
mode: 'add'
})
},
async handleRowAdd (row) {
async handleRowAdd (row, done) {
this.formOptions.saveLoading = true
await this.$api.ADD_NODE(assign(row, { action: 'add_node' }))
this.$message({
message: '添加成功',
type: 'success'
})
try {
await this.$api.ADD_NODE(assign(row, { action: 'add_node' }))
this.$message({
message: '添加成功',
type: 'success'
})
} catch (e) {
console.log(e)
}
this.getNodes()
done()
this.formOptions.saveLoading = false
},
async handleRowEdit ({ index, row }) {
async handleRowEdit ({ index, row }, done) {
this.formOptions.saveLoading = true
await this.$api.UPDATE_NODE(assign(pickBy(row, (v, k) => (!startsWith(k, 'show'))), { action: 'update_node' }))
this.$message({
message: '编辑成功',
type: 'success'
})
done()
this.formOptions.saveLoading = false
},
handleRowRemove ({ index, row }, done) {
setTimeout(() => {
console.log(index)
console.log(row)
this.$message({
message: '删除成功',
type: 'success'
})
done()
}, 300)
async handleRowRemove ({ index, row }, done) {
await this.$api.REMOVE_NODE(assign(pick(row, ['code', 'working_subclass']), { action: 'remove_node' }))
this.$message({
message: '删除成功',
type: 'success'
})
done()
},
handleDialogCancel (done) {
this.$message({
message: '取消保存',
message: '用户放弃改动',
type: 'warning'
})
done()

View File

@@ -28,7 +28,7 @@ module.exports = {
publicPath, // 和 publicPath 保持一致
proxy: {
'/api': {
target: 'http://127.0.0.1:1818',
target: 'http://127.0.0.1:8888',
ws: true,
changeOrigin: true,
pathRewrite: {