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'; } }