完成除数据查询前端功能的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']); 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 -> name = 'CaptureWorker';
$worker -> onWorkerStart = function(Worker $worker) { $worker -> onWorkerStart = function(Worker $worker) {
@@ -30,9 +30,40 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
unset($post['action']); unset($post['action']);
$enode_configure = new ENodeConfigure($dbconn, $post = $post); $enode_configure = new ENodeConfigure($dbconn, $post = $post);
$res = $enode_configure -> $action(); $res = $enode_configure -> $action();
if ($res) if ($res === true)
$connection -> send(json_encode(array ('code' => 0, $connection -> send(json_encode(array(
'msg' => 'Set threshold success'))); '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(); $get = $request -> get();
@@ -40,9 +71,15 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
$enode_configure = new ENodeConfigure($dbconn, $get = $get); $enode_configure = new ENodeConfigure($dbconn, $get = $get);
$nodes = $enode_configure -> get_nodes(); $nodes = $enode_configure -> get_nodes();
if (is_null($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 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; namespace EdgeManager\EDataCapture;
class EDataCapture { class EDataCapture {
private function set_data() { // 我不主张在构造函数内实现类型检查,因为在请求过于密集、记录较多时会严重影响性能
// 请使用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() { 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"); pg_query($this -> dbconn, "BEGIN");
$res1 = pg_query($this -> dbconn, sprintf( $res[] = pg_query($this -> dbconn, sprintf(
"CREATE TABLE IF NOT EXISTS %s( "CREATE TABLE IF NOT EXISTS %s (
id serial8, id serial8,
code text references hf_mes_scada_data_capture_node_configure(code), code text references hf_mes_scada_data_capture_node_configure(code),
v_string text, v_string text,
@@ -22,30 +31,65 @@ class ENodeConfigure {
v_bool bool, v_bool bool,
device_code text, device_code text,
batch text, batch text,
create_date timestamp capture_time timestamp NOT NULL DEFAULT NOW()
)", $table_name )", $table_name
)); ));
$res2 = pg_insert( $res[] = pg_insert(
$this -> dbconn, $this -> dbconn,
'hf_mes_scada_data_capture_node_configure', 'hf_mes_scada_data_capture_node_configure',
$this -> post $this -> post
); );
// 检查一下,如果超表已经有了就不要尝试重复创建了
if ($res1 and $res2) $table_exists = pg_query(sprintf(
pg_query($this -> dbconn, "COMMIT"); "SELECT *
else FROM timescaledb_information.hypertables
pg_query($this -> dbconn, "ROLLBACK"); WHERE hypertable_name = '%s'
", $table_name
pg_query($this -> dbconn, sprintf("SELECT create_hypertable('%s','create_date')", $table_name)); ));
pg_query($this -> dbconn, sprintf( if (!in_array($table_name, pg_fetch_all_columns($table_exists, 1))) {
"CREATE INDEX ON %s (v_string, v_int, v_float, v_bool, create_date DESC) $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 WHERE COALESCE(v_string, v_int::text, v_float::text, v_bool::text) IS NOT NULL
", $table_name ", $table_name
)); ));
} }
function remove_node() { 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() { function update_node() {

View File

@@ -2,20 +2,21 @@
function init_db($server_name, $user, $password) { function init_db($server_name, $user, $password) {
$dbconn = pg_connect(sprintf("host=%s user=%s password=%s", $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"); $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_query("CREATE DATABASE scada");
pg_close($dbconn); pg_close($dbconn);
$dbconn = pg_connect(sprintf("host=%s dbname=scada user=%s password=%s", $server_name, $user, $password)); $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 ( pg_query("CREATE TABLE IF NOT EXISTS hf_mes_scada_data_capture_node_configure (
id serial2, id serial2,
code text primary key, code text primary key NOT NULL,
name text, name text NOT NULL,
type text, type text NOT NULL,
flow_code text, flow_code text,
process_code text, working_subclass text NOT NULL,
workstation text, workstation text,
create_date timestamp, create_date timestamp NOT NULL DEFAULT NOW(),
note text note text
)"); )");
pg_close($dbconn); 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 }) => ({ export default ({ service, request, serviceForMock, requestForMock, mock, faker, tools }) => ({
/** /**
* @description 方法名称 * @description 方法名称
* @param {Object} data 请求携带的信息 * @param {Object} data 请求携带的信息
*/ */
ADD_NODE (data) {
return request({
url: '',
method: 'post',
data
})
},
UPDATE_NODE (data) { ADD_NODE: (data) => handlePost(request, data),
return request({ UPDATE_NODE: (data) => handlePost(request, data),
url: '', REMOVE_NODE: (data) => handlePost(request, data),
method: 'post',
data
})
},
QUERY_NODE () { QUERY_NODE () {
return request({ url: '?query=nodes' }) return request({ url: '?query=nodes' })

View File

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

View File

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