增加类型检查,且允许混合上传

This commit is contained in:
Yu Sun
2022-07-11 23:58:53 +08:00
parent 70d1e43c76
commit 5fdfc04349
4 changed files with 244 additions and 117 deletions

View File

@@ -24,10 +24,37 @@ $worker -> onWorkerStart = function(Worker $worker) {
$worker -> onMessage = function(TcpConnection $connection, Request $request) { $worker -> onMessage = function(TcpConnection $connection, Request $request) {
global $options, $dbconn; global $options, $dbconn;
// 仅供Axios使用 // 先预处理POST内容
if ($request->header('content-type') === 'application/json') { if ($request->header('content-type') === 'application/json') {
$post = $request -> post(); $post = $request -> post();
if (isset($post['action']) and str_contains($post['action'], 'node')) { } else {
$body = $request -> rawBody();
if ($body === "") {
$response = new Response(200, [
'Content-Type' => 'application/json;charset=utf-8',
], "空请求!");
$connection -> send($response);
} else {
$post = json_decode($request -> rawBody());
if (json_last_error() !== JSON_ERROR_NONE) {
$response = new Response(200, [
'Content-Type' => 'application/json;charset=utf-8',
], json_encode(array(
'action' => '错得太离谱以至于我也不知道这是什么动作',
'errcode' => 4001,
'errmsg' => 'POST的内容不是JSON也并非可按照JSON解析的字符串或者检查一下你的JSON是不是有注释'
)));
$connection -> send($response);
}
}
}
if (is_array($post)) {
if (count($post) !== 0) {
// Axios发送的POST是array
if (is_array($post) and isset($post['action'])) {
if (str_ends_with($post['action'], 'node')) {
// 用这种方式自动匹配调用和action相对应的方法
$action = $post['action']; $action = $post['action'];
unset($post['action']); unset($post['action']);
$enode_configure = new ENodeConfigure($dbconn, post: $post); $enode_configure = new ENodeConfigure($dbconn, post: $post);
@@ -49,18 +76,31 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
))); )));
} }
} }
} else { }
$post = json_decode($request -> rawBody()); }
if (json_last_error() !== JSON_ERROR_NONE) } else if (isset($post -> action)) {
dump('fuck');
$connection -> send(json_encode(array(
'action' => '错得太离谱以至于我也不知道这是什么动作',
'errcode' => 4001,
'errmsg' => 'POST的内容不是JSON也并非可按照JSON解析的字符串'
)));
dump($post);
if ($post -> action === 'set_node_data') { if ($post -> action === 'set_node_data') {
$data_capture = new EDataCapture($dbconn, post: $post); $data_capture = new EDataCapture($dbconn, post: $post);
if ($data_capture -> check_res === 'WRONG_WORKING_SUBCLASS') {
$response = new Response(200, [
'Content-Type' => 'application/json;charset=utf-8',
], json_encode(array(
'action' => 'result_set_node_data',
'errcode' => 4002,
'errmsg' => '未登记过的工序单元!'
)));
$connection -> send($response);
}
if ($data_capture -> check_res === 'MISMATCH_TYPE') {
$response = new Response(200, [
'Content-Type' => 'application/json;charset=utf-8',
], json_encode(array(
'action' => 'result_set_node_data',
'errcode' => 4002,
'errmsg' => '节点编码和数值类型不匹配!'
)));
$connection -> send($response);
}
$res = $data_capture -> set_node_data(); $res = $data_capture -> set_node_data();
if ($res === true) { if ($res === true) {
$connection -> send(json_encode(array( $connection -> send(json_encode(array(
@@ -76,16 +116,31 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
))); )));
} }
} else { } else {
$connection -> send(json_encode(array( // 有action但是不知道是什么鬼动作
$response = new Response(200, [
'Content-Type' => 'application/json;charset=utf-8',
], json_encode(array(
'action' => $post -> action, 'action' => $post -> action,
'errcode' => 4002, 'errcode' => 4002,
'errmsg' => '请检查传入的字段值!' 'errmsg' => '同朕check check佢'
))); )));
$connection -> send($response);
} }
} else {
// action都无
$response = new Response(200, [
'Content-Type' => 'application/json;charset=utf-8',
], json_encode(array(
'action' => '缺少action字段',
'errcode' => 4001,
'errmsg' => '你请求紧乜撚动作吖?'
)));
$connection -> send($response);
} }
$get = $request -> get(); $get = $request -> get();
if (isset($get['query']) and $get['query'] == 'nodes') { if (isset($get['query'])) {
if ($get['query'] == 'nodes') {
$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))
@@ -98,11 +153,9 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
'code' => 0, 'code' => 0,
'data' => $nodes 'data' => $nodes
))); )));
} } else if ($get['query'] == 'working_subclasses') {
if (isset($get['query']) and $get['query'] == 'working_subclasses') {
$enode_configure = new ENodeConfigure($dbconn, get: $get); $enode_configure = new ENodeConfigure($dbconn, get: $get);
$working_subclasses = $enode_configure -> get_working_subclasses(); $working_subclasses = $enode_configure -> get_working_subclasses($dbconn);
if (is_null($working_subclasses)) if (is_null($working_subclasses))
$connection -> send(json_encode(array( $connection -> send(json_encode(array(
'code' => 1, 'code' => 1,
@@ -113,9 +166,7 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
'code' => 0, 'code' => 0,
'data' => $working_subclasses 'data' => $working_subclasses
))); )));
} } else if ($get['query'] == 'codes') {
if (isset($get['query']) and $get['query'] == 'codes') {
$enode_configure = new ENodeConfigure($dbconn, get: $get); $enode_configure = new ENodeConfigure($dbconn, get: $get);
$codes = $enode_configure -> get_codes_by_working_subclasses(); $codes = $enode_configure -> get_codes_by_working_subclasses();
if (is_null($codes)) if (is_null($codes))
@@ -128,9 +179,7 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
'code' => 0, 'code' => 0,
'data' => $codes 'data' => $codes
))); )));
} } else if ($get['query'] == 'node_data') {
if (isset($get['query']) and $get['query'] == 'node_data') {
$data_capture = new EDataCapture($dbconn, get: $get); $data_capture = new EDataCapture($dbconn, get: $get);
$data = $data_capture -> get_node_data(); $data = $data_capture -> get_node_data();
if (is_null($data)) if (is_null($data))
@@ -143,6 +192,12 @@ $worker -> onMessage = function(TcpConnection $connection, Request $request) {
'code' => 0, 'code' => 0,
'data' => $data 'data' => $data
))); )));
} else {
$connection -> send(json_encode(array(
'code' => 1,
'msg' => '你请求紧乜撚嘢啊?'
)));
}
} }
}; };

View File

@@ -18,18 +18,17 @@
**请求** **请求**
> 需保证每次传入数据的**工序单元working subclass和数值类型type** 一致 > 上位机程序中请单次传入尽量多的数据使得性能最大化
>
> 在此基础上尽量单次传入尽量多数据使得性能最大化。
> >
> 但仍需兼顾传输速率和超时时间。 > 但仍需兼顾传输速率和超时时间。
>
> 无需指定数值类型,服务端会自动根据已添加的节点信息检查,若不符则会报错。
```json ```json
{ {
"action": "set_node_data", "action": "set_node_data",
"param": { "param": {
"working_subclass": <string>, "working_subclass": <string>,
"type": "string" | "int" | "float" | "bool",
"data": [ "data": [
{ {
"code": <string>, "code": <string>,
@@ -56,17 +55,37 @@
```json ```json
{ {
"action": "result_set_data", "action": "result_set_node_data",
"errcode": 0, "errcode": 0,
"errmsg": "" "errmsg": ""
} }
``` ```
操作失败: 操作失败**工序单元尚未登记**
```json ```json
{ {
"action": "result_set_data", "action": "result_set_node_data",
"errcode": 4002,
"errmsg": "未登记过的工序单元!"
}
```
操作失败(**数值类型错误**
```json
{
"action": "result_set_node_data",
"errcode": 4002,
"errmsg": "节点编码和数值类型不匹配!"
}
```
操作失败(不明原因):
```json
{
"action": "result_set_node_data",
"errcode": 4002, "errcode": 4002,
"errmsg": "ROLLBACKed: Bad data received (structure and/or values)" "errmsg": "ROLLBACKed: Bad data received (structure and/or values)"
} }
@@ -115,7 +134,7 @@ yarn serve
客户端连接: 客户端连接:
```bash ```bash
sudo apt install postgresql-client # sudo apt install postgresql-client
# 登入 # 登入
psql -h localhost -U postgres psql -h localhost -U postgres
# 显示数据库列表 # 显示数据库列表

View File

@@ -2,32 +2,85 @@
namespace EdgeManager\EDataCapture; namespace EdgeManager\EDataCapture;
class EDataCapture { class EDataCapture {
// 我不主张在构造函数内实现类型检查,因为在请求过于密集、记录较多时会严重影响性能
// 请使用SCADA系统的开发人员自觉遵守文档内规范
function __construct( function __construct(
protected $dbconn, protected $dbconn,
protected $post = NULL, protected $post = NULL,
protected $get = NULL protected $get = NULL,
) {} public $check_res = NULL,
protected $working_subclass = NULL,
protected $code_type = [],
protected $data = []
) {
if (!is_null($this -> post)) {
if (!in_array(
$this -> post -> param -> working_subclass,
ENodeConfigure::get_working_subclasses($this -> dbconn)
)) {
$this -> check_res = 'WRONG_WORKING_SUBCLASS';
return;
} else {
$this -> working_subclass = $this -> post -> param -> working_subclass;
}
$res = pg_fetch_all(pg_query($this -> dbconn,
"SELECT code, type
FROM hf_mes_scada_data_capture_node_configure"
));
$code_type = &$this -> code_type;
array_walk($res, function(&$v, $k) use (&$code_type) {
$code_type[$v['code']] = $v['type'];
});
foreach ($this -> post -> param -> data as $row) {
$check_func = 'is_' . $code_type[$row -> code];
if (!$check_func($row -> value)) {
$this -> check_res = 'MISMATCH_TYPE';
return;
} else {
$this -> data[$row -> code][] = [
'value' => $row -> value,
'device_code' => $row -> device_code ?? NULL,
'batch' => $row -> batch ?? NULL
];
}
}
unset($row);
}
}
function set_node_data() { function set_node_data() {
foreach (array_chunk($this -> post -> param -> data, 6710885, true) as $chunk) { pg_query($this -> dbconn, "BEGIN");
foreach ($this -> data as $code => $value) {
foreach (array_chunk($value, 6710885, true) as $chunk) {
$sql_head = sprintf( $sql_head = sprintf(
"INSERT INTO hf_mes_scada_data_capture_node_data_%s (code, v_%s, device_code, batch) "INSERT INTO hf_mes_scada_data_capture_node_data_%s (code, v_%s, device_code, batch)
VALUES", VALUES",
$this -> post -> param -> working_subclass, $this -> working_subclass,
$this -> post -> param -> type $this -> code_type[$code]
); );
foreach ($chunk as $row) { foreach ($chunk as $row) {
$sql_values[] = sprintf( $sql_values[] = sprintf(
"('%s', %s, %s, %s)", "('%s', '%s', %s, %s)",
$row -> code, $code,
$row -> value, $row['value'],
$row -> device_code ?? 'DEFAULT', $row['device_code'] ?? 'DEFAULT',
$row -> batch ?? 'DEFAULT' $row['batch'] ?? 'DEFAULT'
); );
} }
return pg_query($this -> dbconn, $sql_head . implode(',', $sql_values)); $res[] = pg_query($this -> dbconn, $sql_head . implode(',', $sql_values));
unset($row, $sql_values);
}
unset($chunk);
}
unset($code, $value);
if (in_array(false, $res)) {
pg_query($this -> dbconn, "ROLLBACK");
return false;
} else {
pg_query($this -> dbconn, "COMMIT");
return true;
} }
} }

View File

@@ -106,8 +106,8 @@ class ENodeConfigure {
return pg_fetch_all($res); return pg_fetch_all($res);
} }
function get_working_subclasses() { static function get_working_subclasses($dbconn) {
$res = pg_query($this -> dbconn, "SELECT DISTINCT ON (working_subclass) working_subclass FROM hf_mes_scada_data_capture_node_configure"); $res = pg_query($dbconn, "SELECT DISTINCT ON (working_subclass) working_subclass FROM hf_mes_scada_data_capture_node_configure");
return pg_fetch_all_columns($res, 0); return pg_fetch_all_columns($res, 0);
} }