1
0
Fork 0
internet-everythings-agricu.../app/Services/DeviceWarningService.php

162 lines
6.1 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
use App\Models\{Device,MonitorMode,WarningNotice,SoilReport,MeteorologicalReport,WaterQualityReport};
class DeviceWarningService
{
public function judgeLog(Device $device, Model $log, Carbon $reportedAt){
//设备预警
$slug = 'mode_warning_';
switch ($log::class) {
case SoilReport::class://土壤监测
$slug .= Device::TYPE_SOIL;
break;
case MeteorologicalReport::class://气象监测
$slug .= Device::TYPE_METEOROLOGICAL;
break;
case WaterQualityReport::class://水质监测
$slug .= Device::TYPE_SOIL;
break;
}
$rule = settings()->get($slug);
if($rule){
foreach($rule as $lv => $rule){
$res = $this->verifyRule($rule, $log);
if($res && $res['status']){
$this->inLog($device, $reportedAt, $log, $lv, $res['keys']);
}
}
}
return ;
}
private function verifyRule($rule, $log){
$res = [
'status' => false,
'keys' => []
];
if(isset($rule['conjunction'])){//多条件
switch($rule['conjunction']){
case 'or':
if(isset($rule['children'])){
foreach($rule['children'] as $child){
$cRes = $this->verifyRule($child, $log);
if($cRes && $cRes['status']){
if($log->wasChanged($cRes['keys'])){
$res['status'] = true;
$res['keys'] = array_merge($res['keys'], $cRes['keys']);
}elseif(WarningNotice::where([
'loggable_type' => $log::class,
'loggable_id' => $log->id,
])->count() == 0){
$res['status'] = true;
$res['keys'] = array_merge($res['keys'], $cRes['keys']);
}
}
}
}
break;
case 'and':
if(isset($rule['children'])){
$_keys = [];
foreach($rule['children'] as $child){
$cRes = $this->verifyRule($child, $log);
if($cRes && $cRes['status']){
$_keys = array_merge($_keys, $cRes['keys']);
continue;
}else{
break;
}
}
if($log->wasChanged($_keys)){
$res['status'] = true;
$res['keys'][] = implode(',', $_keys);
}elseif(WarningNotice::where([
'loggable_type' => $log::class,
'loggable_id' => $log->id,
])->count() == 0){
$res['status'] = true;
$res['keys'][] = implode(',', $_keys);
}
}
break;
}
}else{//单条件
$key = $rule['left']['field'] ?? '';
$value = $log->$key ?? null;
$min = $rule['right']['0'] ?? null;
$max = $rule['right']['1'] ?? null;
if($min !== null && $max === null){//设置了最小值,未设置最大值
if($value >= $min ){
$res['status'] = true;
$res['keys'][] = $key;
}
}elseif($min === null && $max !== null){//设置最大值,未设置最小值
if($value <= $max ){
$res['status'] = true;
$res['keys'][] = $key;
}
}elseif($min !== null && $max !== null){//最大值,最小值都有设置
if($value >= $min && $value <= $max){
$res['status'] = true;
$res['keys'][] = $key;
}
}
}
return $res;
}
private function inLog(Device $device, Carbon $reportedAt, Model $log, $lv, $columns){
if(!is_array($columns)){
$columns = array($columns);
}
switch($device->type){
case Device::TYPE_METEOROLOGICAL:
$fieldNameMap = MonitorMode::fieldMap(Device::TYPE_METEOROLOGICAL);
$fieldUnitMap = MonitorMode::fieldUnitMap(Device::TYPE_METEOROLOGICAL);
break;
case Device::TYPE_SOIL:
$fieldNameMap = MonitorMode::fieldMap(Device::TYPE_SOIL);
$fieldUnitMap = MonitorMode::fieldUnitMap(Device::TYPE_SOIL);
break;
}
$notices = array();
foreach($columns as $column){
$msg = '';
if(strpos($column, ',')){//看是否是并联条件
$_columns = explode(',',$column);
foreach($_columns as $cc){
$msg.= $fieldNameMap[$cc].'达到'.($log->$cc ?? 0).$fieldUnitMap[$cc].'值,且';
}
$msg = mb_substr($msg, 0, -2);
}else{
$msg = $fieldNameMap[$column].'达到'.($log->$column ?? 0).$fieldUnitMap[$column].'值';
}
$notices[] = [
'device_id' => $device->id,
'lv' => $lv,
'content' => '【'.$device->name.'】【'.WarningNotice::lvMap()[$lv].'】'.$msg,
'reported_at' => $reportedAt,
'created_at' => now(),
'updated_at' => now(),
'loggable_type' => $log::class,
'loggable_id' => $log->id,
];
}
count($notices) > 0 && WarningNotice::insert($notices);
}
}