dev
Jing Li 2023-08-12 17:31:07 +08:00
parent 943099a5d3
commit f491a1bf84
8 changed files with 231 additions and 6 deletions

View File

@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands\BiAng;
use App\Enums\DeviceStatus;
use App\Enums\DeviceType;
use App\Models\Device;
use App\Models\WormStatisticsReport;
use App\Services\BiAngDeviceService;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
class WormStatisticsSyncCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'biang:worm-statistics-sync';
/**
* The console command description.
*
* @var string
*/
protected $description = '虫情设备统计数据同步';
/**
* Execute the console command.
*/
public function handle()
{
$this->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('==================================');
}
}
}

View File

@ -22,6 +22,10 @@ class Kernel extends ConsoleKernel
$schedule->command(Commands\WaterQualityMonitoringLogFixCommand::class)
->hourly()
->runInBackground();
$schedule->command(Commands\BiAng\WormStatisticsSyncCommand::class)
->hourly()
->runInBackground();
}
/**

View File

@ -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);
}
}

View File

@ -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;

View File

@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class WormStatisticsReport extends Model
{
use HasFactory;
protected $casts = [
'data' => 'json',
'reported_at' => 'date',
];
protected $fillable = [
'device_id', 'agricultural_base_id', 'worm_num', 'data', 'reported_at',
];
}

View File

@ -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'] ?? '');
}
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('worm_statistics_reports', function (Blueprint $table) {
$table->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');
}
};

View File

@ -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']);