argument('factory'); $sleep = (int) value(fn ($sleep) => is_numeric($sleep) ? $sleep : 300, $this->option('sleep')); while (true) { /** @var \Illuminate\Database\Eloquent\Collection */ $devices = Device::with(['factory'])->poweredBy($factory)->get(); foreach ($devices as $device) { switch ($device->factory?->key) { case 'link-os': $this->createReportToLinkosDevice($device); break; } } sleep($sleep); }; } protected function createReportToLinkosDevice(Device $device): void { switch ($device->type) { case Device::TYPE_SOIL: $this->createReportToLinkosSoilDevice($device); break; case Device::TYPE_METEOROLOGICAL: $this->createReportToLinkosMeteorologicalDevice($device); break; case Device::TYPE_WATER_QUALITY: $this->createReportToLinkosWaterQualityDevice($device); break; } } protected function createReportToLinkosSoilDevice(Device $device): void { $lastSoilReport = SoilReport::where('device_id', $device->id) ->latest('reported_at') ->first(); $lastReportedAt = $lastSoilReport?->reported_at ?: $device->logs()->oldest('reported_at')->value('reported_at'); if ($lastReportedAt === null) { return; } $latestReportedAt = $device->logs()->latest('reported_at')->value('reported_at'); if ($latestReportedAt === null) { return; } /** @var \Carbon\Carbon */ $startAt = $lastReportedAt->copy()->startOfHour(); /** @var \Carbon\Carbon */ $endAt = $latestReportedAt->copy()->startOfHour(); do { /** @var \Illuminate\Database\Eloquent\Collection */ $logs = $device->logs() ->whereBetween('reported_at', [$startAt, $startAt->copy()->endOfHour()]) ->oldest('reported_at') ->get(); if ($logs->isNotEmpty()) { $soilReport = SoilReport::firstOrCreate( [ 'device_id' => $device->id, 'reported_at' => $startAt, ], Arr::except($lastSoilReport?->setHidden([])?->attributesToArray() ?: [], ['reported_at']) ); /** @var \App\Models\DeviceLog */ foreach ($logs as $log) { foreach ([ 'conductivity' => 'conductivity', 'soil_humidity' => 'humidity', 'soil_temperature' => 'temperature', 'nitrogen_content' => 'n', 'potassium_content' => 'k', 'phosphorus_content' => 'p', ] as $key => $attribute) { if (! is_array($log->data) || ! array_key_exists($key, $log->data)) { continue; } $soilReport->{$attribute} = $log->data[$key]; } $lastSoilReport = tap($soilReport)->save(); } } $startAt->addHour(); } while ($endAt->gte($startAt)); } protected function createReportToLinkosMeteorologicalDevice(Device $device): void { $lastMeteorologicalReport = MeteorologicalReport::where('device_id', $device->id) ->latest('reported_at') ->first(); $lastReportedAt = $lastMeteorologicalReport?->reported_at ?: $device->logs()->oldest('reported_at')->value('reported_at'); if ($lastReportedAt === null) { return; } $latestReportedAt = $device->logs()->latest('reported_at')->value('reported_at'); if ($latestReportedAt === null) { return; } /** @var \Carbon\Carbon */ $startAt = $lastReportedAt->copy()->startOfHour(); /** @var \Carbon\Carbon */ $endAt = $latestReportedAt->copy()->startOfHour(); do { /** @var \Illuminate\Database\Eloquent\Collection */ $logs = $device->logs() ->whereBetween('reported_at', [$startAt, $startAt->copy()->endOfHour()]) ->oldest('reported_at') ->get(); if ($logs->isNotEmpty()) { $meteorologicalReport = MeteorologicalReport::firstOrCreate( [ 'device_id' => $device->id, 'reported_at' => $startAt, ], Arr::except($lastMeteorologicalReport?->setHidden([])?->attributesToArray() ?: [], ['reported_at']) ); /** @var \App\Models\DeviceLog */ foreach ($logs as $log) { foreach ([ 'current_rainfall' => 'today_rainfall', 'day_rainfall' => 'yesterday_rainfall', 'accumulate_rainfall' => 'accumulate_rainfall', 'moment_rainfall' => 'moment_rainfall', 'pm10_concentration' => 'pm10', 'pm25_concentration' => 'pm25', 'box_illumination' => 'box_illumination', 'box_pressure' => 'box_pressure', 'box_carbon' => 'box_co2', 'box_temperature' => 'box_temperature', 'box_humidity' => 'box_humidity', 'box_noise' => 'box_noise', 'wind_degree' => 'wind_degree', 'wind_direction' => 'wind_direction', 'wind_power' => 'wind_power', 'wind_speed' => 'wind_speed', ] as $key => $attribute) { if (! is_array($log->data) || ! array_key_exists($key, $log->data)) { continue; } $meteorologicalReport->{$attribute} = $log->data[$key]; } $lastMeteorologicalReport = tap($meteorologicalReport)->save(); } } $startAt->addHour(); } while ($endAt->gte($startAt)); } protected function createReportToLinkosWaterQualityDevice(Device $device): void { $lastWaterQualityReport = WaterQualityReport::where('device_id', $device->id) ->latest('reported_at') ->first(); $lastReportedAt = $lastWaterQualityReport?->reported_at ?: $device->logs()->oldest('reported_at')->value('reported_at'); if ($lastReportedAt === null) { return; } $latestReportedAt = $device->logs()->latest('reported_at')->value('reported_at'); if ($latestReportedAt === null) { return; } /** @var \Carbon\Carbon */ $startAt = $lastReportedAt->copy()->startOfHour(); /** @var \Carbon\Carbon */ $endAt = $latestReportedAt->copy()->startOfHour(); do { /** @var \Illuminate\Database\Eloquent\Collection */ $logs = $device->logs() ->whereBetween('reported_at', [$startAt, $startAt->copy()->endOfHour()]) ->oldest('reported_at') ->get(); if ($logs->isNotEmpty()) { $waterQualityReport = WaterQualityReport::firstOrCreate( [ 'device_id' => $device->id, 'reported_at' => $startAt, ], Arr::except($lastWaterQualityReport?->setHidden([])?->attributesToArray() ?: [], ['reported_at']) ); /** @var \App\Models\DeviceLog */ foreach ($logs as $log) { foreach ([ 'chlorine' => 'chlorine', 'conductivity' => 'conductivity', 'oxygen' => 'oxygen', 'ph' => 'ph', 'temp' => 'temperature', 'turbidity' => 'turbidity', ] as $key => $attribute) { if (! is_array($log->data) || ! array_key_exists($key, $log->data)) { continue; } $waterQualityReport->{$attribute} = $log->data[$key]; } $lastWaterQualityReport = tap($waterQualityReport)->save(); } } $startAt->addHour(); } while ($endAt->gte($startAt)); } }