160 lines
4.9 KiB
PHP
160 lines
4.9 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands\Linkos;
|
||
|
||
use App\Enums\DeviceStatus;
|
||
use App\Enums\DeviceType;
|
||
use App\Iot\Linkos\FarmClient;
|
||
use App\Models\Device;
|
||
use App\Models\WormPhoto;
|
||
use App\Models\WormReport;
|
||
use Illuminate\Console\Command;
|
||
use Illuminate\Support\Facades\Storage;
|
||
use Throwable;
|
||
|
||
class WormReportCommand extends Command
|
||
{
|
||
/**
|
||
* The name and signature of the console command.
|
||
*
|
||
* @var string
|
||
*/
|
||
protected $signature = 'linkos:worm-report';
|
||
|
||
/**
|
||
* The console command description.
|
||
*
|
||
* @var string
|
||
*/
|
||
protected $description = 'linkos 虫情设备数据同步';
|
||
|
||
/**
|
||
* Execute the console command.
|
||
*/
|
||
public function handle()
|
||
{
|
||
$this->info('------------------------------------------');
|
||
$this->info(now());
|
||
try {
|
||
$this->sync();
|
||
} catch (Throwable $e) {
|
||
report($e);
|
||
}
|
||
$this->info('------------------------------------------');
|
||
}
|
||
|
||
protected function sync(): void
|
||
{
|
||
// 接口接口限制,每分钟最多访问6次,因此每次访问后需休眠10秒
|
||
$client = new FarmClient('xunwang', 'qwer1234');
|
||
|
||
$now = now();
|
||
|
||
/** @var \Illuminate\Database\Eloquent\Collection */
|
||
$devices = Device::supplierBy('device-supplier-linkos')
|
||
->where('type', DeviceType::Worm)
|
||
->whereIn('status', [DeviceStatus::Online, DeviceStatus::Offline])
|
||
->get();
|
||
|
||
if ($devices->isEmpty()) {
|
||
$this->warn('没有找到虫情设备');
|
||
return;
|
||
}
|
||
|
||
$this->info('==================================');
|
||
$this->info('尝试更新设备状态...');
|
||
$realTimeData = $client->realTimeData($devices->pluck('sn')->all());
|
||
|
||
foreach ($realTimeData as $item) {
|
||
foreach ($devices as $device) {
|
||
if ($item['deviceAddr'] != $device->sn) {
|
||
continue;
|
||
}
|
||
// 更新设备状态
|
||
$device->update([
|
||
'status' => $item['status'] === 'online' ? DeviceStatus::Online : DeviceStatus::Offline,
|
||
]);
|
||
}
|
||
}
|
||
$this->info("设备状态更新完成");
|
||
|
||
$this->info('==================================');
|
||
|
||
$this->info('尝试同步虫情区域统计...');
|
||
for ($i=2; $i > 0; $i--) {
|
||
$reportedAt = $now->copy()->subDays($i);
|
||
|
||
$statistics = collect(
|
||
$client->wormStatistics(
|
||
'E05F10DAIB6F4I4977IB95FI82554A48DE7C',
|
||
$reportedAt->copy()->startOfDay(),
|
||
$reportedAt->copy()->endOfDay(),
|
||
)
|
||
)->mapWithKeys(fn ($item) => [$item['deviceAddr'] => $item['wornData']]);
|
||
|
||
foreach ($devices as $device) {
|
||
$data = $statistics[$device->sn] ?? [];
|
||
|
||
WormReport::updateOrCreate([
|
||
'device_id' => $device->id,
|
||
'reported_at' => $reportedAt->toDateString(),
|
||
], [
|
||
'agricultural_base_id' => $device->agricultural_base_id,
|
||
'worm_num' => collect($data)->sum('num'),
|
||
'data' => $data,
|
||
]);
|
||
}
|
||
}
|
||
$this->info("同步虫情区域统计完成");
|
||
|
||
$this->info('==================================');
|
||
|
||
// 接口请求次数
|
||
$requests = 4;
|
||
|
||
// 同步最近7天的分析报表记录
|
||
$this->info('尝试同步分析报表记录...');
|
||
foreach ($devices->pluck('sn') as $sn) {
|
||
$data = $client->wormAnalyseData($sn, $now->copy()->subDays(7), $now, 1, 100);
|
||
|
||
foreach ($data['rows'] as $item) {
|
||
foreach ($devices as $device) {
|
||
if ($item['deviceAddr'] != $device->sn) {
|
||
continue;
|
||
}
|
||
|
||
$url = $item['analyseCoordUrl'] ?: $item['imagesUrl'];
|
||
|
||
// 下载图片
|
||
$name = md5($url);
|
||
if ($ext = pathinfo($url, PATHINFO_EXTENSION)) {
|
||
$name .= ".{$ext}";
|
||
}
|
||
|
||
$path = "worm-photos/{$device->id}/{$name}";
|
||
|
||
$disk = Storage::disk('public');
|
||
if (! $disk->exists($path)) {
|
||
$disk->put($path, file_get_contents($url));
|
||
}
|
||
|
||
WormPhoto::updateOrCreate([
|
||
'device_id' => $device->id,
|
||
'uploaded_at' => $item['createTime'],
|
||
], [
|
||
'url' => $path,
|
||
]);
|
||
}
|
||
}
|
||
|
||
$requests++;
|
||
// 接口请求频率: 每分钟6次
|
||
if ($requests == 6) {
|
||
$requests = 0;
|
||
sleep(61);
|
||
}
|
||
}
|
||
$this->info("同步分析报表记录完成");
|
||
}
|
||
}
|