lcly-data-admin/app/Console/Commands/LinkosDeviceLogSyncCommand.php

198 lines
5.2 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Exceptions\BizException;
use App\Models\LinkosDeviceLog;
use App\Services\LinkosService;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
class LinkosDeviceLogSyncCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'linkos:device-log-sync {device}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'LinkOS 设备流水同步';
/**
* @var \App\Services\LinkosService
*/
protected $linkosService;
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$now = now();
$device = $this->argument('device');
// 最近同步时间
$lastDate = $this->getLastDate($device);
do {
if ($lastDate === null) {
$lastDate = Carbon::parse('2022-06-01');
} else {
$lastDate->addDay();
}
$start = $lastDate->copy()->startOfDay();
if ($start->gt($now)) {
throw new BizException('开始时间大约当前时间');
}
$end = $lastDate->copy()->endOfDay();
if ($end->gt($now)) {
$end = $now;
}
$this->info('----------------------------------');
$this->info('设备编号: '.$device);
$this->info('开始时间: '.$start->toDateTimeString());
$this->info('结束时间: '.$end->toDateTimeString());
$this->info('开始同步');
$this->info('...');
$this->synchronize($device, $start, $end);
$this->info('Done!');
$this->info('----------------------------------');
if ($now->isSameDay($lastDate)) {
break;
}
$this->setLastDate($device, $lastDate);
} while (true);
return Command::SUCCESS;
}
/**
* 同步设备历史数据
*
* @param string $device
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @return void
*/
protected function synchronize(string $device, Carbon $start, Carbon $end)
{
// 分页页码
$page = 0;
// 每页条数
$size = 50;
// 开始时间戳
$startTime = $start->unix() * 1000;
// 结束时间戳
$endTime = $end->unix() * 1000;
LinkosDeviceLog::where('device_id', $device)->whereBetween('reported_at', [$start, $end])->delete();
do {
$result = retry(5, function () use ($device, $page, $size, $startTime, $endTime) {
return $this->linkosService()->post('/deviceFlow/v1/list', [
'device_id' => $device,
'start_time' => $startTime,
'end_time' => $endTime,
'pageable' => [
'page' => $page,
'size' => $size,
],
]);
}, 100);
$data = collect($result['data']['content']);
$count = $data->count();
if ($count === 0) {
break;
}
$time = now();
LinkosDeviceLog::insert(
$data->map(function ($item) use ($time) {
return [
'device_id' => $item['device_id'],
'device_unit' => $item['device_unit'],
'device_category' => $item['device_category'],
'data' => ! empty($item['data']) ? json_encode($item['data']) : '{}',
'reported_at' => $item['createTime'],
'created_at' => $time->toDateTimeString(),
'updated_at' => $time->toDateTimeString(),
];
})->toArray()
);
unset($result, $data);
$page++;
} while ($count === $size);
}
/**
* @return \App\Services\LinkosService
*/
protected function linkosService(): LinkosService
{
if ($this->linkosService === null) {
$this->linkosService = app(LinkosService::class);
}
return $this->linkosService;
}
/**
* 获取设备最后同步日期
*
* @param string $device
* @return \Carbon\Carbon|null
*/
protected function getLastDate(string $device): ?Carbon
{
if (is_null($date = Cache::get($this->generateKey($device)))) {
return null;
}
return Carbon::parse($date);
}
/**
* 设置设备最后同步日期
*
* @param string $device
* @param \Carbon\Carbon $date
* @return void
*/
protected function setLastDate(string $device, Carbon $date): void
{
Cache::put($this->generateKey($device), $date->toDateString(), 86400);
}
/**
* @param string $device
* @return string
*/
protected function generateKey(string $device): string
{
return 'linkos_device_log:'.$device.'_last_sync_date';
}
}