From f491a1bf84c53fe8653e98a0fdd461e0908bc0c4 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Sat, 12 Aug 2023 17:31:07 +0800 Subject: [PATCH] Update --- .../BiAng/WormStatisticsSyncCommand.php | 92 +++++++++++++++++++ app/Console/Kernel.php | 4 + app/Http/Controllers/DeviceController.php | 31 ++++++- app/Iot/BiAng/HttpClient.php | 2 +- app/Models/WormStatisticsReport.php | 20 ++++ app/Services/BiAngDeviceService.php | 51 +++++++++- ...8_create_worm_statistics_reports_table.php | 36 ++++++++ routes/api.php | 1 + 8 files changed, 231 insertions(+), 6 deletions(-) create mode 100644 app/Console/Commands/BiAng/WormStatisticsSyncCommand.php create mode 100644 app/Models/WormStatisticsReport.php create mode 100644 database/migrations/2023_08_012_155228_create_worm_statistics_reports_table.php diff --git a/app/Console/Commands/BiAng/WormStatisticsSyncCommand.php b/app/Console/Commands/BiAng/WormStatisticsSyncCommand.php new file mode 100644 index 0000000..2c8b945 --- /dev/null +++ b/app/Console/Commands/BiAng/WormStatisticsSyncCommand.php @@ -0,0 +1,92 @@ +sync(); + } + + protected function sync(): void + { + /** @var \Illuminate\Database\Eloquent\Collection */ + $devices = Device::with(['project']) + ->supplierBy('device-supplier-biang') + ->where('type', DeviceType::Worm) + ->whereIn('status', [DeviceStatus::Online, DeviceStatus::Offline]) + ->get(); + + if ($devices->isEmpty()) { + $this->warn('没有找到虫情设备'); + return; + } + + $today = today(); + + foreach ($devices as $device) { + $this->info('=================================='); + + $latestReportedAt = WormStatisticsReport::Where('device_id', $device->id)->latest('reported_at')->value('reported_at'); + + $start = $latestReportedAt ? $latestReportedAt->copy() : $today->copy()->subDays(179); + + $days = $start->diffInDays($today, false); + + if ($days > 179) { + $end = $start->copy()->addDays(179); + } else { + if ($days < 2) { + $start = $today->copy()->subDays(2); + } + $end = $today->copy(); + } + $this->info('设备编号: '.$device->sn); + $this->info('开始日期: '.$start->toDateString()); + $this->info('结束日期: '.$end->toDateString()); + + $statistics = (new BiAngDeviceService())->getWormStatistics($device, $start, $end); + + foreach (data_get($statistics, 'data.records', []) as $item) { + $data = collect(Arr::except($item, '日期'))->map(fn ($v, $k) => ['name' => $k, 'num' => $v]); + + WormStatisticsReport::updateOrCreate([ + 'device_id' => $device->id, + 'reported_at' => $item['日期'], + ], [ + 'agricultural_base_id' => $device->agricultural_base_id, + 'worm_num' => $data->sum('num'), + 'data' => $data->values(), + ]); + } + + $this->info('=================================='); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 8e3a6c0..5050984 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -22,6 +22,10 @@ class Kernel extends ConsoleKernel $schedule->command(Commands\WaterQualityMonitoringLogFixCommand::class) ->hourly() ->runInBackground(); + + $schedule->command(Commands\BiAng\WormStatisticsSyncCommand::class) + ->hourly() + ->runInBackground(); } /** diff --git a/app/Http/Controllers/DeviceController.php b/app/Http/Controllers/DeviceController.php index da72241..b0f01e3 100644 --- a/app/Http/Controllers/DeviceController.php +++ b/app/Http/Controllers/DeviceController.php @@ -16,9 +16,10 @@ use App\Models\SoilMonitoringDailyLog; use App\Models\SoilMonitoringLog; use App\Models\WaterQualityMonitoringDailyLog; use App\Models\WaterQualityMonitoringLog; +use App\Services\BiAngDeviceService; use App\Services\OperationLogService; -use Carbon\Carbon; use Illuminate\Http\Request; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Peidikeji\Setting\Models\Setting; @@ -572,4 +573,32 @@ class DeviceController extends Controller return $this->json($data); } + + /** + * 虫情图片 + */ + public function wormPhotos($id, Request $request, BiAngDeviceService $biAngDeviceService) + { + $request->validate([ + 'start_time' => ['bail', 'required', 'date_format:Y-m-d'], + 'end_time' => ['bail', 'required', 'date_format:Y-m-d'], + ]); + + $device = Device::findOrFail($id); + + $data = []; + + switch ($device->supplier_key) { + case 'device-supplier-biang': + $result = $biAngDeviceService->getWormPhotos( + $device, + Carbon::parse($request->input('start_time')), + Carbon::parse($request->input('end_time')), + ); + $data = $result['imgUrl']; + break; + } + + return $this->json($data); + } } diff --git a/app/Iot/BiAng/HttpClient.php b/app/Iot/BiAng/HttpClient.php index 7d68809..e91bdb3 100644 --- a/app/Iot/BiAng/HttpClient.php +++ b/app/Iot/BiAng/HttpClient.php @@ -3,7 +3,7 @@ namespace App\Iot\BiAng; use App\Exceptions\BiAngException; -use Illuminate\Support\Carbon; +use Carbon\Carbon; use Illuminate\Support\Facades\Http; use Illuminate\Support\Str; use RuntimeException; diff --git a/app/Models/WormStatisticsReport.php b/app/Models/WormStatisticsReport.php new file mode 100644 index 0000000..a2b3e81 --- /dev/null +++ b/app/Models/WormStatisticsReport.php @@ -0,0 +1,20 @@ + 'json', + 'reported_at' => 'date', + ]; + + protected $fillable = [ + 'device_id', 'agricultural_base_id', 'worm_num', 'data', 'reported_at', + ]; +} diff --git a/app/Services/BiAngDeviceService.php b/app/Services/BiAngDeviceService.php index d619307..ef44425 100644 --- a/app/Services/BiAngDeviceService.php +++ b/app/Services/BiAngDeviceService.php @@ -4,7 +4,8 @@ namespace App\Services; use App\Enums\DeviceStatus; use App\Enums\DeviceType; -use App\Iot\BiAng\HttpClient as BiAngHttpClient; +use App\Exceptions\BizException; +use App\Iot\BiAng\HttpClient; use App\Models\Device; use App\Models\DeviceLog; use App\Models\InsecticidalLampDailyReport; @@ -19,13 +20,41 @@ use Illuminate\Support\Facades\DB; class BiAngDeviceService { + /** + * 虫情设备/昆虫性诱设备 - 查询某个时间段内的图片 + */ + public function getWormPhotos(Device $device, Carbon $start, Carbon $end): array + { + try { + $httpClient = $this->buildHttpClient($device); + } catch (BizException $e) { + return []; + } + + return $httpClient->getWormPhotos($device->sn, $start, $end); + } + + /** + * 虫情设备 - (识别款)图片虫数识别统计 + */ + public function getWormStatistics(Device $device, Carbon $start, Carbon $end): array + { + try { + $httpClient = $this->buildHttpClient($device); + } catch (BizException $e) { + return []; + } + + return $httpClient->getWormStatistics($device->sn, $start, $end); + } + public function sync(Device $device, Carbon $syncTime): void { - $config = json_decode($device->project?->value, true); - if (! isset($config['username'], $config['password'])) { + try { + $httpClient = $this->buildHttpClient($device); + } catch (BizException $e) { return; } - $httpClient = new BiAngHttpClient($config['username'], $config['password']); switch ($device->type) { case DeviceType::Soil: @@ -535,4 +564,18 @@ class BiAngDeviceService $insecticidalLampDailyReport->fill($attributes)->save(); } + + /** + * 创建 HTTP 客户端 + */ + public function buildHttpClient(Device $device): HttpClient + { + $config = json_decode($device->project?->value, true); + + if (! is_array($config)) { + throw new BizException('账户信息未找到'); + } + + return new HttpClient($config['username'] ?? '', $config['password'] ?? ''); + } } diff --git a/database/migrations/2023_08_012_155228_create_worm_statistics_reports_table.php b/database/migrations/2023_08_012_155228_create_worm_statistics_reports_table.php new file mode 100644 index 0000000..f01d306 --- /dev/null +++ b/database/migrations/2023_08_012_155228_create_worm_statistics_reports_table.php @@ -0,0 +1,36 @@ +id(); + $table->unsignedBigInteger('device_id'); + $table->unsignedBigInteger('agricultural_base_id')->comment('农业基地ID'); + $table->unsignedInteger('worm_num')->comment('虫子数量'); + $table->json('data')->nullable(); + $table->date('reported_at')->comment('报告日期'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('worm_statistics_reports'); + } +}; diff --git a/routes/api.php b/routes/api.php index e211420..3c31971 100644 --- a/routes/api.php +++ b/routes/api.php @@ -54,6 +54,7 @@ Route::group(['middleware' => 'auth:sanctum'], function () { Route::apiResource('crop-flows', CropFlowController::class)->names('crops_flow'); //设备管理 Route::apiResource('devices', DeviceController::class)->names('device'); + Route::get('devices/{device}/worm-photos', [DeviceController::class, 'wormPhotos']); Route::put('devices-update-recommend/{device}', [DeviceController::class, 'updateRecommendStatus']); Route::get('devices-num', [DeviceController::class, 'typeStatusNum'])->name('device.type_status_num'); Route::get('monitoring-data', [DeviceController::class, 'timeZoneList']);