415 lines
16 KiB
PHP
415 lines
16 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use App\Enums\DeviceStatus;
|
||
use App\Enums\DeviceType;
|
||
use App\Helpers\Paginator;
|
||
use App\Http\Requestes\DeviceRequest;
|
||
use App\Http\Resources\DeviceResource;
|
||
use App\Models\Device;
|
||
use App\Models\MeteorologicalMonitoringLog;
|
||
use App\Models\MeteorologicalMonitoringDailyLog;
|
||
use App\Models\SoilMonitoringLog;
|
||
use App\Models\SoilMonitoringDailyLog;
|
||
use App\Models\WaterQualityMonitoringLog;
|
||
use App\Models\WaterQualityMonitoringDailyLog;
|
||
use App\Models\AgriculturalBase;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Carbon\Carbon;
|
||
use App\Services\OperationLogService;
|
||
use App\Enums\OperationType;
|
||
use Peidikeji\Setting\Models\Setting;
|
||
|
||
class DeviceController extends Controller
|
||
{
|
||
public function index(Request $request)
|
||
{
|
||
$query = Device::with('base')->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;
|
||
}
|
||
}
|
||
}
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
return $this->json($data);
|
||
}
|
||
|
||
/**
|
||
* 查询设备今天(按天),近一周(按天),近一个月(按天)
|
||
*/
|
||
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;
|
||
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(1400, 1600) / 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);
|
||
}
|
||
}
|