SCTMES_V5/mes_in_sct/app/event/SetTrayProcessResultEvent.php

453 lines
18 KiB
PHP
Raw Normal View History

2025-06-14 18:55:09 +08:00
<?php
namespace app\event;
use libs\db\Db;
use libs\listener\Event;
use Exception;
class SetTrayProcessResultEvent extends Event
{
/**
* 计算温度补偿值并返回
* @param $data
* @return string[]
* @throws \Exception
*/
public function getTemperatureSupp($data)
{
list($param, $flow_id, $process_id) = [$data['param'], $data['flow_id'], $data['process_id']];
// 判断是否存在温度数组TEMPERATURE
if (isset($param['TEMPERATURE'])) {
// 查询是否配置了温度补偿数据
$sql = sprintf(
"SELECT result_param_code
FROM hf_mes_technology_process_temperature
WHERE process_id=%s GROUP BY result_param_code;",
$process_id
);
$ret = Db::query($sql);
if (!empty($ret)) {
// 保留充放电原始容量参数
foreach ($param as $k => $v) {
$string = $k;
$pattern = '/ENDC(\d)(\d)/';
$replacement = 'ORCA$1$2';
$replace_string = preg_replace($pattern, $replacement, $string);
if ($replace_string != NULL && $replace_string != $k) {
$param[$replace_string] = $v;
}
}
// 查找对应的温度补偿result_param
foreach ($param as $k => $v) {
foreach ($ret as $v1) {
// 查找配置的工步key等于结果参数的工步key
if ($v1['result_param_code'] == $k) {
// 判断工步数组与TEMPERATURE的长度是否一致
if (count($v) == count($param['TEMPERATURE'])) {
// 获取对应的工序key的温度补偿配置数据
$sql = sprintf(
"SELECT result_param_code,temperature,compensation_value
FROM hf_mes_technology_process_temperature
WHERE process_id=%s AND result_param_code='%s' ORDER BY temperature ASC;",
$process_id,
$k
);
$temp_ret = Db::query($sql);
for ($j = 0; $j < count($v); $j++) {
// 进行温度补偿修正
$value = floatval($v[$j]);
$temperature = floatval($param['TEMPERATURE'][$j]);
$closest = null;
foreach ($temp_ret as $item) {
if ($closest === null || abs($temperature - floatval($closest['temperature'])) > abs(floatval($item['temperature']) - $temperature)) {
$closest = $item;
}
}
$param[$k][$j] = $value * floatval($closest['compensation_value']);
}
}
}
}
}
}
}
return $param;
}
/**
* 验证pin_check数据
* @param $data
* @return bool
* @throws Exception
*/
public function verifyPinCheck($data)
{
list($param, $battery_ids) = [$data['param'], $data['battery_ids']];
if (!isset($param['pin_check'])) {
throw new Exception('上传的结果参数中不存在[pin_check]结果数据,请检查![pin_check]');
}
if (!is_array($param['pin_check'])) {
throw new Exception('上传的结果参数[pin_check]不是数组类型,请检查![pin_check]');
}
if (count($param['pin_check']) != count($battery_ids)) {
$count = count($battery_ids);
throw new Exception("上传的结果参数[pin_check]的数组长度与电池数量不相等,电池数量为:[{$count}],请检查![pin_check]");
}
if (!is_array($param['NG'])) {
throw new Exception('上传的结果参数中不存在[NG]结果数据,请检查![pin_check]');
}
if (!is_array($param['NG'])) {
throw new Exception('上传的结果参数[NG]不是数组类型,请检查![pin_check]');
}
if (count($param['NG']) != count($battery_ids)) {
$count = count($battery_ids);
throw new Exception("上传的结果参数[NG]的数组长度与电池数量不相等,电池数量为:[{$count}],请检查![pin_check]");
}
$pin_ckeck_arr = $param['pin_check'];
foreach ($pin_ckeck_arr as $index => $item) {
if (!is_int($item)) {
$index = $index + 1;
throw new Exception("上传的结果参数[pin_check]的数组位置[{$index}]的数值不是整数类型,类型要求例子:[0,1]");
}
if (!in_array($item, [0, 1])) {
$index = $index + 1;
throw new Exception("上传的结果参数[pin_check]的数组位置[{$index}]的数值不是整数0或者1类型要求例子:[0]或者[1]");
}
// 验证NG数据
if (!is_numeric($param['NG'][$index])) {
$index = $index + 1;
throw new Exception("上传的结果参数[NG]的数组位置[{$index}]的数值整型的字符串类型,类型要求例子:['0','1'],其中如果没有异常码,默认值为['0']");
}
// 验证pin_check等于1时对应的NG位置必须上传异常码
if ($item == 1) {
if (empty($param['NG'][$index])) {
throw new Exception("当[pin_check]结果参数数组位置[{$index}]的值为[1]时,对应上传的结果参数[NG]的数组位置[{$index}]必须上传通道异常码");
}
}
}
return true;
}
/**
* 写入pin_ckeck队列缓存数据
* @param $data
* @return bool
* @throws Exception
*/
public function setPincheckQueue($data)
{
list($param, $device_code, $batch, $subbatch, $tray, $lot) = [
$data['param'],
$data['device_code'],
$data['batch'],
$data['subbatch'],
$data['tray'],
$data['lot'],
];
// 判断是否存在pin_ckeck的数据
$pin_ckeck = $param['pin_check'];
// 判断pin_ckeck是否存在等于1数据
$filteredArray = array_filter($pin_ckeck, function ($value) {
return $value === 1;
});
if (!empty($filteredArray)) {
// 写入队列缓存数据(status=0为未处理数据)
$row = Db::insert('hf_mes_queue_pincheck', [
'device_code' => $device_code,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'param' => json_encode($param, JSON_UNESCAPED_UNICODE),
'status' => 0,
'create_time' => date('Y-m-d H:i:s')
]);
if ($row === NULL) {
throw new Exception('写入[pin_check]队列数据失败');
}
}
return true;
}
/**
* 写入曲线队列缓存数据
* @param $data
* @return bool
* @throws Exception
*/
public function setCurveQueue($data)
{
list($param, $device_code, $batch, $subbatch, $tray, $lot, $process_code, $battery_ids) = [
$data['param'],
$data['device_code'],
$data['batch'],
$data['subbatch'],
$data['tray'],
$data['lot'],
$data['process_code'],
$data['battery_ids']
];
$end_time = $param['end_time'];
$workingsubclass = $param['workingsubclass'];
try {
// 写入队列缓存数据(status=0为未处理数据)
$row = Db::insert('hf_mes_queue_curve', [
'device_code' => $device_code,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'param' => json_encode($param, JSON_UNESCAPED_UNICODE),
'status' => 0,
'end_time' => $end_time,
'create_time' => date(format: 'Y-m-d H:i:s')
]);
if ($row === NULL) {
throw new Exception('写入曲线队列数据失败!');
}
// 获取batch和电池ID
if (in_array($workingsubclass, ['IC', 'YC', 'PRESSURE_FORMATION', 'HC'])) {
$insert_curve_data = [];
$insert_curve_key = sprintf("INSERT INTO hf_mes_production_curve_data_path (batch,subbatch,workingsubclass,process_code,channel,battery_id,device_code,end_time,tray,lot,create_time,curve_path) VALUES ");
foreach ($battery_ids as $index => $val) {
// 跳过无效条码
if (in_array($val, ["0", 0, "", null], true)) {
continue;
}
$channel = $index + 1;
$insert_curve_data[] = sprintf(
"('%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
$batch,
$subbatch,
$workingsubclass,
$process_code,
$channel,
$val,
$device_code,
$end_time,
$tray,
$lot,
date("Y-m-d H:i:s"),
"/hf-data/" . $subbatch . '/' . $process_code . '/' . $device_code . '/' . $end_time
);
}
if (!empty($insert_curve_data)) {
//插入曲线表
$sql = $insert_curve_key . implode(',', $insert_curve_data);
$row = Db::query($sql);
if ($row === NULL) {
throw new Exception("电池曲线信息写入失败!");
}
} else {
throw new Exception("构造插入hf_mes_production_curve_data_path表数据库语句失败");
}
}
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
return true;
}
/**
* 直接写入分档信息
* @param $data
* @return bool
* @throws Exception
*/
public function setGradingQueue($data)
{
list($param, $batch, $subbatch, $tray, $lot, $process_code) = [
$data['param'],
$data['batch'],
$data['subbatch'],
$data['tray'],
$data['lot'],
$data['process_code']
];
try {
//直接更新bkv 表的分档信息
$sql = "SELECT
a.id AS id,
a.tray AS tray,
a.batch AS batch,
a.lot AS lot,
a.process_idx AS process_idx,
a.next_process_code AS next_process_code,
b.flow_id AS flow_id,
b2.setting AS setting,
json_agg(
json_build_object(
'param', d.code,
'name', d.name,
'note', d.remark,
'ng', d.remark,
'class', d.field_type,
'is_need', d.is_upload
)
) AS result_param
FROM hf_mes_production_tray_map a
INNER JOIN hf_mes_technology_process b ON a.next_process_code = b.code
INNER JOIN hf_mes_process_workingsubclass c ON b.workingsubclass_id = c.id
LEFT JOIN hf_mes_technology_process_result_param d ON d.process_id = b.id
LEFT JOIN hf_mes_technology_process b2 ON b2.code = (b.flow_id || '_SELECTION')
WHERE
a.active = 1
AND a.next_process_code != '-1'
AND a.next_process_code IS NOT NULL
AND a.tray = '$tray'
AND a.lot = '$lot'
AND a.subbatch = '$subbatch'
AND a.batch = '$batch'
GROUP BY
a.id, a.tray, a.batch, a.lot, a.process_idx, a.next_process_code,
b.flow_id, b2.setting;";
$ret = Db::query($sql);
if (count($ret) > 0) {
//进行分选和NG逻辑处理
for ($i = 0; $i < count($ret); $i++) {
//单个托盘处理
$process_code = $ret[$i]['next_process_code'];
$setting = json_decode($ret[$i]['setting']);
if (!isset($setting->process)) {
break;
}
$o = $setting->process;
$o_result_param = $setting->result_param;
foreach ($o as $item) {
// 将对象转为数组以获取 key 和 value
$arr = (array) $item;
foreach ($arr as $key => $val) {
// 替换 ' :' 为 '.'(注意:这里只是你可能用于 WHERE 子句的字段名或条件的一部分)
$val = str_replace(' :', '.', $val);
// 判断值非空
if (!empty($val)) {
$class = '';
// 查找匹配 param 的 ng 值
foreach ($o_result_param as $result_elem) {
if ($result_elem->param == $key) {
$class = $result_elem->ng;
break;
}
}
try {
if (!empty($class)) {
// SQL 条件安全性未验证,假设 $val 是类似 "some_field = 'some_value'" 的条件语句
$sql = "UPDATE \"hf_mes_tmp_bkv_{$subbatch}\"
SET classname = '{$key}',
class = '{$class}'
WHERE ({$val})
AND lot = '{$lot}'
AND tray = '{$tray}'
AND active = 1
AND (class IS NULL OR class = '' OR class = 'GOOD');";
$ret_bkv_update = Db::query($sql);
if ($ret_bkv_update === NULL) {
throw new Exception("更新分档数据失败!");
}
}
} catch (Exception $e) {
throw new Exception("更新分档数据失败!" . $e->getMessage());
}
}
}
}
}
}
return true;
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
/**
* 写入K值队列缓存数据
* @param $data
* @return bool
* @throws Exception
*/
public function setKQueue($data)
{
list($param, $batch, $subbatch, $tray, $lot, $flow_id) = [
$data['param'],
$data['batch'],
$data['subbatch'],
$data['tray'],
$data['lot'],
$data['flow_id']
];
// 写入队列缓存数据(status=0为未处理数据)
$row = Db::insert('hf_mes_queue_k', [
'flow_id' => $flow_id,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'param' => json_encode($param, JSON_UNESCAPED_UNICODE),
'status' => 0,
'create_time' => date('Y-m-d H:i:s')
]);
if ($row === NULL) {
throw new Exception('写入K值队列数据失败');
}
return true;
}
/**
* 写入容量预测队列缓存数据
* @param $data
* @return bool
* @throws Exception
*/
public function setKunQueue($data)
{
list($param, $batch, $subbatch, $tray, $lot, $workingsubclass) = [
$data['param'],
$data['batch'],
$data['subbatch'],
$data['tray'],
$data['lot'],
$data['workingsubclass']
];
// 写入队列缓存数据(status=0为未处理数据)
$row = Db::insert('hf_mes_queue_kun', [
'workingsubclass' => $workingsubclass,
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'param' => json_encode($param, JSON_UNESCAPED_UNICODE),
'status' => 0,
'create_time' => date('Y-m-d H:i:s')
]);
if ($row === NULL) {
throw new Exception('写入容量预测队列数据失败');
}
return true;
}
}