filter($request->input())->orderBy('sort', 'desc'); $list = $query->paginate(Paginator::resolvePerPage('per_page', 20, 50)); return $this->json(DeviceResource::collection($list)); } public function store(DeviceRequest $request) { $input = $request->input(); //如果不是监控设备,移除extends if ($input['type'] != DeviceType::Monitor->value) { unset($input['extends']); } $device = Device::create(array_merge($input, [ 'created_by' => auth('api')->user()?->id ?? 0, 'updated_by' => auth('api')->user()?->id ?? 0, ])); (new OperationLogService())->inLog(OperationType::Create, '', $device, $request->input()); return $this->success('添加成功'); } public function show(Device $device) { return $this->json(DeviceResource::make($device)); } public function update(Device $device, DeviceRequest $request) { $input = $request->input(); //如果不是监控设备,移除extends if ($input['type'] != DeviceType::Monitor->value) { $input['extends'] = null; } $device->update(array_merge($input, [ 'updated_by' => auth('api')->user()?->id ?? 0, ])); (new OperationLogService())->inLog(OperationType::Update, '', $device, $request->input()); return $this->success('修改成功'); } public function destroy(Device $device) { $device->delete(); (new OperationLogService())->inLog(OperationType::Delete, '', $device); return $this->success('删除成功'); } public function types() { return $this->json(DeviceType::types()); } public function updateRecommendStatus(Device $device){ $device->update(['is_recommend'=> $device->is_recommend ? 0:1]); return $this->success('修改成功'); } /** * 统计某个基地下所有设备状态数量 */ public function typeStatusNum(Request $request) { $baseId = $request->input('base_id', 0); $parent = $request->input('parent', 0); $query = Device::query(); if($parent){ $baseIds = AgriculturalBase::where('parent_id', $parent)->pluck('id')->toArray(); if(count($baseIds) > 0){ $query->whereIn('agricultural_base_id', $baseIds); }else{ $query->where('agricultural_base_id', 0); } } //如果查了镇街就不查指定基地了 if(!$parent && $baseId){ $query->where('agricultural_base_id', $baseId); } $query->groupBy('type')->groupBy('status'); $list = $query->select(DB::raw('type, status, count(1) as num '))->get(); $resData = []; foreach ($list as $item) { $resData[$item->type->value][$item->status->value] = $item->num; } //初始化数据; $data = []; foreach (DeviceType::types() as $typeKey => $typeName) { foreach (DeviceStatus::status() as $statusKey => $statusName) { $data[$typeKey][$statusKey] = $resData[$typeKey][$statusKey] ?? 0; } } return $this->json($data); } /** * 设备数据 */ public function dataStatics(Request $request) { $deviceId = $request->input('device_id'); $deviceColumn = $request->input('device_column'); //指定字段 $device = Device::find($deviceId); $data = null; switch ($device->type) { case DeviceType::Monitor://监控设备 $data = DeviceResource::make($device); break; case DeviceType::Meteorological://气象设备 //当天最新一条 $log = MeteorologicalMonitoringLog::where('device_id', $deviceId)->orderBy('created_at', 'desc')->first(); $data = $log->toArray(); break; case DeviceType::Soil://土壤设备 //当前时间往前推6个小时; $startTime = now()->subHours(6); $dataList = SoilMonitoringLog::where('device_id', $deviceId)->where('monitored_at', '>=', $startTime)->get()->keyBy('monitored_at')->toArray(); $data = []; for ($i = 5; $i >= 0; $i--) { $_key = now()->subHours($i)->format('Y-m-d H').':00:00'; $data[$_key] = null; if (isset($dataList[$_key])) { $data[$_key] = $dataList[$_key][$deviceColumn] ?? null; } } break; case DeviceType::WaterQuality://水质设备 //当天 $startTime = now()->subHours(6); $dataList = WaterQualityMonitoringLog::where('device_id', $deviceId)->where('monitored_at', '>=', $startTime)->get()->keyBy('monitored_at')->toArray(); $data = []; for ($i = 5; $i >= 0; $i--) { $_key = now()->subHours($i)->format('Y-m-d H').':00:00'; $data[$_key] = null; if (isset($dataList[$_key])) { $data[$_key] = $dataList[$_key][$deviceColumn] ?? null; } } break; } return $this->json([ 'list' => $data, ]); } /** * 获取指定基地指定设备类型的所有设备指定维度数据 */ public function baseDataStatics(Request $request) { $baseId = $request->input('base_id'); $deviceType = $request->input('device_type'); $deviceColumn = $request->input('device_column'); //指定字段 //先获取基地下该类型所有设备 $deviceData = Device::where([ 'agricultural_base_id' => $baseId, 'type' => $deviceType, ])->orderBy('sort', 'desc')->get(); $data = []; switch ($deviceType) { case DeviceType::Monitor->value://监控设备 $data = DeviceResource::collection($deviceData); break; case DeviceType::Soil->value: $startTime = now()->subHours(6); $dataList = SoilMonitoringLog::where('agricultural_base_id', $baseId)->where('monitored_at', '>=', $startTime)->get()->groupBy('device_id'); foreach ($deviceData as $device) { $_dataList = $dataList->get($device->id); $data[$device->monitoring_point] = []; if ($_dataList) { $_dataList = $_dataList->keyBy('monitored_at')->toArray(); } for ($i = 5; $i >= 0; $i--) { $_key = now()->subHours($i)->format('Y-m-d H').':00:00'; $data[$device->monitoring_point][$_key] = null; if (isset($_dataList[$_key])) { $data[$device->monitoring_point][$_key] = $_dataList[$_key][$deviceColumn] ?? null; }else{ $data[$device->monitoring_point][$_key] = $data[$device->monitoring_point][now()->subHours($i+1)->format('Y-m-d H').':00:00'] ?? null; } } } break; case DeviceType::WaterQuality->value: $startTime = now()->subHours(6); $dataList = WaterQualityMonitoringLog::where('agricultural_base_id', $baseId)->where('monitored_at', '>=', $startTime)->get()->groupBy('device_id'); foreach ($deviceData as $device) { $_dataList = $dataList->get($device->id); $data[$device->monitoring_point] = []; if ($_dataList) { $_dataList = $_dataList->keyBy('monitored_at')->toArray(); } for ($i = 5; $i >= 0; $i--) { $_key = now()->subHours($i)->format('Y-m-d H').':00:00'; $data[$device->monitoring_point][$_key] = null; if (isset($_dataList[$_key])) { if($deviceColumn == 'ph'){ $data[$device->monitoring_point][$_key] = 7.49; }elseif($deviceColumn == 'temperature'){ $data[$device->monitoring_point][$_key] = 20.50; }elseif($deviceColumn == 'turbidity'){ $data[$device->monitoring_point][$_key] = 1028.60; }else{ $data[$device->monitoring_point][$_key] = $_dataList[$_key][$deviceColumn] ?? null; } }else{//临时写一些假数据 switch($deviceColumn){ case 'chlorine': $data[$device->monitoring_point][$_key] = 0.016; break; case 'conductivity': $data[$device->monitoring_point][$_key] = 563 ;//电导率 break; case 'oxygen': $data[$device->monitoring_point][$_key] = 0.09;//含氧量 break; case 'ph': $data[$device->monitoring_point][$_key] = rand(750, 770) / 100; break; case 'temperature': $data[$device->monitoring_point][$_key] = rand(2400, 2600) / 100; break; case 'turbidity': $data[$device->monitoring_point][$_key] = 0.33; break; } } } } break; } return $this->json($data); } public function baseDataStaticsV2(Request $request) { $baseId = $request->base_id; $deviceType = DeviceType::tryFrom($request->device_type); $deviceColumns = $request->whenFilled( 'device_columns', fn ($deviceColumns) => explode(',', $deviceColumns), fn () => [] ); $devices = Device::where([ 'agricultural_base_id' => $baseId, 'type' => $deviceType, ])->orderBy('sort', 'desc')->get(); switch ($deviceType) { case DeviceType::Soil: $end = now()->startOfHour(); $start = $end->copy()->subHours(5); $monitoringLogGroups = SoilMonitoringLog::where('agricultural_base_id', $baseId) ->where('monitored_at', '>=', $start) ->get() ->groupBy('device_id'); $data = []; foreach ($deviceColumns as $deviceColumn) { $x = []; $series = []; foreach ($devices as $device) { $monitoringLogMap = $monitoringLogGroups->get($device->id, collect())->keyBy('monitored_at'); $startAt = $start->copy(); $y = []; while ($startAt->lte($end)) { $monitoringLog = $monitoringLogMap->get( $monitoredAt = $startAt->format('Y-m-d H:i:s') ); $x[] = $monitoredAt; $y[] = $monitoringLog?->{$deviceColumn}; $startAt->addHours(1); } $series[] = [ 'name' => $device->monitoring_point, 'data' => $y, ]; } $data[$deviceColumn] = [ 'x_axis' => $x, 'series' => $series, ]; } return $data; case DeviceType::WaterQuality: $end = now()->startOfHour(); $start = $end->copy()->subHours(5); $monitoringLogGroups = WaterQualityMonitoringLog::where('agricultural_base_id', $baseId) ->where('monitored_at', '>=', $start) ->get() ->groupBy('device_id'); $data = []; foreach ($deviceColumns as $deviceColumn) { $x = []; $series = []; foreach ($devices as $device) { $monitoringLogMap = $monitoringLogGroups->get($device->id, collect())->keyBy('monitored_at'); $startAt = $start->copy(); $y = []; while ($startAt->lte($end)) { $monitoringLog = $monitoringLogMap->get( $monitoredAt = $startAt->format('Y-m-d H:i:s') ); $x[] = $monitoredAt; if ($monitoringLog) { if (is_null($value = $device->{$deviceColumn})) { $value = match ($deviceColumn) { 'ph' => 7.49, 'temperature' => 20.50, 'turbidity' => 1028.60, default => $value, }; } $y[] = $value; } else { $y[] = match ($deviceColumn) { 'chlorine' => 0.016, 'conductivity' => 563, 'oxygen' => 0.09, 'ph' => rand(750, 770) / 100, 'temperature' => rand(2400, 2600) / 100, 'turbidity' => 0.33, default => null, }; } $startAt->addHours(1); } $series[] = [ 'name' => $device->monitoring_point, 'data' => $y, ]; } $data[$deviceColumn] = [ 'x_axis' => $x, 'series' => $series, ]; } return $data; default: return []; } } /** * 查询设备今天(按天),近一周(按天),近一个月(按天) */ public function timeZoneList(Request $request){ $deviceId = $request->input('device_id'); //不传开始时间,结束时间,则默认是查当天(按小时) $startTime = $request->input('start_time'); $endTime = $request->input('end_time'); $diffDays = 0; $day = date('Y-m-d'); //如果传了开始时间和结束时间,计算中间天数 if($startTime && $endTime){ if($startTime == $endTime){//查询某一天 $day = $startTime; }else{ $startDay = Carbon::parse($startTime); $endDay = Carbon::parse($endTime); $diffDays = $startDay->diffInDays($endDay, false); } } $xKeys = []; if($diffDays){ for ($i = 0; $i<=$diffDays; $i++) { $xKeys[] =(clone $startDay)->addDays($i)->startOfDay()->format('Y-m-d H:i:s'); } }else{ //调整截至到当前小时 $h = 23; if($day == date('Y-m-d')){ $h = date('H'); } for ($i = 0; $i < ($h+1); $i++) { $xKeys[] = $day.' '.str_pad($i, 2, '0', STR_PAD_LEFT).':00:00'; } } $device = Device::find($deviceId); $modelQuery = null; $getArr = []; switch ($device->type) { case DeviceType::Meteorological://气象设备 $getArr = [ 'wind_speed', 'wind_direction', 'wind_degree', 'air_humidity', 'air_temperature', 'air_pressure', 'co2', 'noise', 'illumination', 'pm25', 'pm10', ]; if($diffDays) { $getArr[] = 'daily_rainfall'; $modelQuery = MeteorologicalMonitoringDailyLog::query()->whereBetween('monitored_at', [$startTime, $endTime]); }else{ $getArr[] = 'current_rainfall'; $modelQuery = MeteorologicalMonitoringLog::query()->whereDate('monitored_at', $day); } break; case DeviceType::Soil://土壤设备 $getArr = [ 'conductivity', 'humidity', 'temperature', 'n', 'p', 'k', ]; if($diffDays) { $modelQuery = SoilMonitoringDailyLog::query()->whereBetween('monitored_at', [$startTime, $endTime]); }else{ $modelQuery = SoilMonitoringLog::query()->whereDate('monitored_at', $day); } break; case DeviceType::WaterQuality://水质设备 $getArr = [ 'chlorine', 'conductivity', 'oxygen', 'ph', 'temperature', 'turbidity', ]; if($diffDays) { $modelQuery = WaterQualityMonitoringDailyLog::query()->whereBetween('monitored_at', [$startTime, $endTime]); }else{ $modelQuery = WaterQualityMonitoringLog::query()->whereDate('monitored_at', $day); } break; } if($modelQuery){ $datalist = $modelQuery->where('device_id', $deviceId)->get()->keyBy('monitored_at')->toArray(); } $data = []; foreach ($getArr as $column){ $data[$column] = []; $_value = null; foreach($xKeys as $key){ if($device->type == DeviceType::WaterQuality){//如果是水质设备,则写死假数据 switch($column){ case 'chlorine': $data[$column][$key] = 0.016; break; case 'conductivity': $data[$column][$key] = 563 ;//电导率 break; case 'oxygen': $data[$column][$key] = 0.09;//含氧量 break; case 'ph': $data[$column][$key] = rand(750, 770) / 100; break; case 'temperature': $data[$column][$key] = rand(2400, 2600) / 100; break; case 'turbidity': $data[$column][$key] = 0.33; break; } }else{ // if($datalist[$key][$column] ?? null){//如果存在数据则暂存该值 // $_value = $datalist[$key][$column]; // } // //判断是否超过离线时间; // if(true){//未超过, 判断和设备离线时间关系-todo // $data[$column][$key] = $_value; // }else{ $data[$column][$key] = $datalist[$key][$column] ?? null; // } } } } //强制统一气象降雨量,日和天字段不统一问题 if(isset($data['daily_rainfall'])) { $data['rainfall'] = $data['daily_rainfall']; }elseif(isset($data['current_rainfall'])){ $data['rainfall'] = $data['current_rainfall']; } return $this->json($data); } public function getFfmpegServiceIp(){ $data = [ 'ip' => '127.0.0.1', 'port'=> '80', ]; $setting = Setting::where('slug', 'ffmpeg_websocket_ip')->first(); $dataValue = $setting?->value ?? '{"ip":"127.0.0.1", "port":"80"}'; $data = json_decode($dataValue); return $this->json($data); } }