diff --git a/app/Admin/Controllers/AirLogController.php b/app/Admin/Controllers/AirLogController.php new file mode 100644 index 0000000..c60b267 --- /dev/null +++ b/app/Admin/Controllers/AirLogController.php @@ -0,0 +1,12 @@ +input('region_id', 0); + $config = null; + $device = null; + if($regionId){ + $region = Region::find($regionId); + if($region){ + $monitorMode = $region->monitorModes()->where('type', MonitorMode::TYPE_AIR)->first(); + $device = $monitorMode->devices()->first(); + $config = $device?->extends ?? null; + } + } return amisMake()->Grid()->columns([ amisMake()->Wrapper()->sm(6)->body([ amisMake()->Panel()->title('智能开关设置') ->labelWidth(100) ->body([ - \amisMake()->Form()->title('')->mode('horizontal')->body([ + \amisMake()->Form()->title('')->mode('horizontal') + ->api([ + 'method'=>'post', + 'url'=>admin_url('save-region-config').'/'.$regionId.'?type='.MonitorMode::TYPE_AIR, + 'data'=>[ + 'open_is_enable' => '${open_is_enable}', + 'open_config' => '${open_config}', + 'close_is_enable' => '${close_is_enable}', + 'close_config' => '${close_config}', + ] + ]) + ->data($config ? $config : []) + ->body([ amisMake()->FieldSetControl()->title('智能开启')->body([ \amisMake()->SwitchControl()->name('open_is_enable')->label('开关'), - \amisMake()->ConditionBuilderControl()->label('条件')->fields([ + \amisMake()->ConditionBuilderControl()->name('open_config')->label('条件')->fields([ [ - 'label' => '温度', 'type'=>'number','step'=>'0.01','name'=>'q', + 'label' => '温度', 'type'=>'number','step'=>'0.01','name'=>'box_temperature', 'operators'=> [ - 'equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'between', 'not_between', + 'less', 'less_or_equal', 'greater', 'greater_or_equal' // 'is_empty', 'is_not_empty' ] ], [ - 'label' => '湿度', 'type'=>'number','step'=>'0.01','name'=>'x', + 'label' => '湿度', 'type'=>'number','step'=>'0.01','name'=>'box_humidity', 'operators'=> [ - 'equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'between', 'not_between', + 'less', 'less_or_equal', 'greater', 'greater_or_equal' // 'is_empty', 'is_not_empty' ] ], @@ -302,18 +325,18 @@ class DeviceController extends AdminController ]), amisMake()->FieldSetControl()->title('智能关闭')->body([ \amisMake()->SwitchControl()->name('close_is_enable')->label('开关'), - \amisMake()->ConditionBuilderControl()->label('条件')->fields([ + \amisMake()->ConditionBuilderControl()->name('close_config')->label('条件')->fields([ [ - 'label' => '温度', 'type'=>'number','step'=>'0.01','name'=>'q', + 'label' => '温度', 'type'=>'number','step'=>'0.01','name'=>'box_temperature', 'operators'=> [ - 'equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'between', 'not_between', + 'less', 'less_or_equal', 'greater', 'greater_or_equal', // 'is_empty', 'is_not_empty' ] ], [ - 'label' => '湿度', 'type'=>'number','step'=>'0.01','name'=>'x', + 'label' => '湿度', 'type'=>'number','step'=>'0.01','name'=>'box_humidity', 'operators'=> [ - 'equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'between', 'not_between', + 'less', 'less_or_equal', 'greater', 'greater_or_equal' // 'is_empty', 'is_not_empty' ] ], @@ -325,21 +348,19 @@ class DeviceController extends AdminController amisMake()->Wrapper()->sm(6)->body([ amisMake()->Panel()->title('开关记录') ->body([ - \amisMake()->Table()->title('') - ->data([ - 'items' => [ - [ - 'name'=> '温度>10℃', - 'name1'=> '关闭', - 'time1'=> '2023-03-21 10:00:00', - ] - ] - ]) - ->columns([ - amisMake()->TableColumn()->name('name')->label('触发条件'), - amisMake()->TableColumn()->name('name1')->label('状态'), - amisMake()->TableColumn()->name('time1')->label('执行时间'), - ]) + \amisMake()->CRUDTable() + ->api(admin_url('air-logs').'?_action=getData&device_id='.($device?->id ?? 0)) + ->title('') + ->columns([ + amisMake()->TableColumn()->name('content')->label('触发条件'), + amisMake()->TableColumn()->name('type')->type('mapping')->map([ + "0"=>"未知", + "1"=>"开启", + "2"=>"关闭", + "*"=> '其他:${type}' + ])->label('动作'), + amisMake()->TableColumn()->name('created_at')->type('datetime')->label('执行时间'), + ]) ]) ]), ]); @@ -401,7 +422,7 @@ class DeviceController extends AdminController \amisMake()->Form()->title('')->mode('horizontal') ->api([ 'method'=>'post', - 'url'=>admin_url('save-region-config').'/'.$regionId, + 'url'=>admin_url('save-region-config').'/'.$regionId.'?type='.MonitorMode::TYPE_ATOMIZING, 'data'=>[ 'is_enable' => '${is_enable}', 'config' => '${config}' @@ -453,9 +474,10 @@ class DeviceController extends AdminController if($id){ $region = Region::find($id); if($region){ - $monitorMode = $region->monitorModes()->where('type', MonitorMode::TYPE_ATOMIZING)->first(); + $type = $request->input('type', 0); + $monitorMode = $region->monitorModes()->where('type', $type)->first(); $config = $request->input() ?? null; - + unset($config['type']); $res = $monitorMode->devices()->update([ 'extends' => $config, ]); diff --git a/app/Admin/Controllers/HomeController.php b/app/Admin/Controllers/HomeController.php index 4b0a059..c68c5ba 100644 --- a/app/Admin/Controllers/HomeController.php +++ b/app/Admin/Controllers/HomeController.php @@ -2,6 +2,8 @@ namespace App\Admin\Controllers; +use App\Models\Device; +use App\Models\MeteorologicalReport; use Illuminate\Http\JsonResponse; use Slowlyo\OwlAdmin\Renderers\Card; use Slowlyo\OwlAdmin\Renderers\Flex; @@ -21,6 +23,7 @@ class HomeController extends AdminController public function index(): JsonResponse|JsonResource { + (new \App\Services\Admin\DeviceService())->meteorologicalControAir(Device::find(3), MeteorologicalReport::find(217), now()); $page = $this->basePage()->css($this->css())->body([ Grid::make()->columns([ $this->frameworkInfo()->md(8), diff --git a/app/Admin/routes.php b/app/Admin/routes.php index a148d18..3daa5f5 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -103,4 +103,6 @@ Route::group([ //喷雾自动开启/关闭日志 $router->resource('atomizing-logs', \App\Admin\Controllers\AtomizingLogController::class)->only(['index']); + //通风自动开启/关闭日志 + $router->resource('air-logs', \App\Admin\Controllers\AirLogController::class)->only(['index']); }); diff --git a/app/Filters/Admin/AirLogFilter.php b/app/Filters/Admin/AirLogFilter.php new file mode 100644 index 0000000..6a49de9 --- /dev/null +++ b/app/Filters/Admin/AirLogFilter.php @@ -0,0 +1,16 @@ +where('device_id', $deviceId); + } +} diff --git a/app/Models/AirLog.php b/app/Models/AirLog.php new file mode 100644 index 0000000..20a5915 --- /dev/null +++ b/app/Models/AirLog.php @@ -0,0 +1,14 @@ +wasChanged('box_temperature') || $log->wasChanged('box_humidity')){//如果温度或者湿度发生变化; + + } + //获取当前设备关联监测点IDs; + $monitorIds = MonitorDevice::where('device_id', $device->id)->pluck('monitor_id')->toArray(); + $regionIds = RegionMonitor::where('monitor_id', $monitorIds)->pluck('region_id')->toArray(); + + $regions = Region::whereIn('id', $regionIds)->whereHas('monitorModes', function($q){ + return $q->where('type', MonitorMode::TYPE_AIR); + })->get(); + + //遍历地点,是否有通风设备; + foreach($regions as $region){ + $monitorModes = $region->monitorModes()->where('type', MonitorMode::TYPE_AIR)->get(); + foreach($monitorModes as $monitor){ + $_device = $monitor->devices()->first(); + $config = $_device?->extends ?? []; + + $fieldNameMap = MonitorMode::fieldMap(Device::TYPE_METEOROLOGICAL); + $fieldUnitMap = MonitorMode::fieldUnitMap(Device::TYPE_METEOROLOGICAL); + + $airState = $this->getAirStatus($device); + + //开启了自动开启配置 + if($config && $config['open_is_enable'] ){ + $rule = $config['open_config']; + $res = $this->verifyRule($rule, $log); + + if($res['status'] && !$this->getAirStatus($device)){//如果判定成功,且设备当前是关闭状态 + $msg = ''; + $column = $res['keys'][0]; + if(strpos($column, ',')){//看是否是并联条件 + $_columns = explode(',',$column); + foreach($_columns as $cc){ + $msg.= $fieldNameMap[$cc].'达到'.$log->$cc.$fieldUnitMap[$cc].'值,且'; + } + + $msg = mb_substr($msg, 0, -2); + }else{ + $msg = $fieldNameMap[$column].'达到'.$log->$column.$fieldUnitMap[$column].'值'; + } + $this->openAir($device, $msg); + } + } + if($config && $config['close_is_enable'] ){ + $rule = $config['close_config']; + $res = $this->verifyRule($rule, $log); + + if($res['status'] && !$this->getAirStatus($device)){//如果判定成功,且设备当前是关闭状态 + $msg = ''; + $column = $res['keys'][0]; + if(strpos($column, ',')){//看是否是并联条件 + $_columns = explode(',',$column); + foreach($_columns as $cc){ + $msg.= $fieldNameMap[$cc].'达到'.$log->$cc.$fieldUnitMap[$cc].'值,且'; + } + + $msg = mb_substr($msg, 0, -2); + }else{ + $msg = $fieldNameMap[$column].'达到'.$log->$column.$fieldUnitMap[$column].'值'; + } + $this->closeAir($device, $msg); + } + } + } + } + + //开关控制; + } + public 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']){ + $res['status'] = true; + $res['keys'] = array_merge($res['keys'], $cRes['keys']); + return $res; + } + } + } + break; + case 'and': + if(isset($rule['children'])){ + $_keys = []; + foreach($rule['children'] as $child){ + $cRes = $this->verifyRule($child, $log); + if($cRes){ + $_keys = array_merge($_keys, $cRes['keys']); + continue; + }else{ + $res['status'] = false; + return $res; + } + } + $res['status'] = true; + $res['keys'][] = implode(',', $_keys); + } + break; + } + }else{//单条件 + $key = $rule['left']['field'] ?? ''; + $value = $log->$key ?? null; + switch($rule['op']){ + case 'less': + break; + if($value < $rule['right']){ + $res['status'] = true; + $res['keys'][] = $key; + } + case 'less_or_equal': + if($value <= $rule['right']){ + $res['status'] = true; + $res['keys'][] = $key; + } + break; + case 'greater': + if($value > $rule['right']){ + $res['status'] = true; + $res['keys'][] = $key; + } + break; + case 'greater_or_equal': + if($value >= $rule['right']){ + $res['status'] = true; + $res['keys'][] = $key; + } + break; + } + } + return $res; + } + + /** + * 获取通风设备当前状态 + */ + public function getAirStatus(Device $device) + { + dd(app(HttpClient::class)->getDeviceStatus($device->sn, ["switch_state"])); + return false; + } + + /** + * 开启通风设备 + */ + public function openAir(Device $device, string $msg) + { + if($device->type != Device::TYPE_AIR){ + return ; + } + //记录触发日志 + AirLog::create([ + 'device_id' => $device->id, + 'type' => 1, + 'content' => $msg, + ]); + //编号,-todo + // $httpClient = app(HttpClient::class); + // dd($httpClient->deviceDataDownlink($device->sn, 'switch_control', ['switch_state' => 0])); + return ; + } + + /** + * 关闭通风设备 + */ + public function closeAir(Device $device, string $msg) + { + if($device->type != Device::TYPE_AIR){ + return ; + } + AirLog::create([ + 'device_id' => $device->id, + 'type' => 2, + 'content' => $msg, + ]); + dd('关闭通风'); + //编号, + // $httpClient = app(HttpClient::class); + // dd($httpClient->deviceDataDownlink($device->sn, 'switch_control', ['switch_state' => 1])); + return ; + } } diff --git a/app/Services/DeviceLogService.php b/app/Services/DeviceLogService.php index 478f7cd..876eb92 100644 --- a/app/Services/DeviceLogService.php +++ b/app/Services/DeviceLogService.php @@ -295,7 +295,8 @@ class DeviceLogService } $meteorologicalReport->fill($attributes)->save(); - + + (new \App\Services\Admin\DeviceService())->meteorologicalControAir($device, $meteorologicalReport, $time); (new DeviceWarningService())->judgeLog($device, $meteorologicalReport, $time); } diff --git a/app/Services/DeviceWarningService.php b/app/Services/DeviceWarningService.php index 1f962dc..454f8b6 100644 --- a/app/Services/DeviceWarningService.php +++ b/app/Services/DeviceWarningService.php @@ -9,12 +9,13 @@ use App\Models\{Device,MonitorMode,WarningNotice,SoilReport,MeteorologicalReport 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://水质监测 + case MeteorologicalReport::class://气象监测 $slug .= Device::TYPE_METEOROLOGICAL; break; case WaterQualityReport::class://水质监测 diff --git a/database/migrations/2023_07_24_101436_create_air_logs_table.php b/database/migrations/2023_07_24_101436_create_air_logs_table.php new file mode 100644 index 0000000..4b2406f --- /dev/null +++ b/database/migrations/2023_07_24_101436_create_air_logs_table.php @@ -0,0 +1,34 @@ +id(); + $table->unsignedBigInteger('device_id'); + $table->unsignedTinyInteger('type')->default(0)->comment('0未知;1开启,2关闭'); + $table->string('content'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('air_logs'); + } +};