· 5 years ago · Aug 11, 2020, 01:04 PM
1<?php
2
3namespace App\Http\Controllers;
4
5use Illuminate\Http\Request;
6use Illuminate\Http\Response;
7use App\Libraries\PlugField;
8use App\Libraries\SessionFilter;
9use App\Models\Farm;
10use App\Models\FarmStation;
11use App\Models\Station;
12use Carbon\Carbon;
13use Illuminate\Support\Facades\Auth;
14use Illuminate\Support\Facades\File;
15use Illuminate\Support\Facades\Storage;
16use App\Models\Crop;
17use App\Models\StationInmet;
18use DateTime;
19use GuzzleHttp\Client;
20
21/**
22 * Controller responsável por gerenciar estações climáticas.
23 *
24 * @author Gabriel Ribeiro <gabriel.geodata@gmail.com>
25 * @since 30/01/2020
26 * @version 1.0.0
27 */
28class StationController extends Controller {
29
30 private $plugField;
31 private $path;
32 private $data;
33 private $root;
34
35 public function __construct() {
36
37 $this->root = storage_path().'/cache';
38 $this->path = $this->root . '/plug-field-data.json';
39
40 //Verifica se o diretório existe
41 if(!File::exists($this->root)) {
42 File::makeDirectory($this->root);
43 }
44
45 //Verifica se o arquivo existe
46 if(!File::exists($this->path)) {
47 File::put($this->path, '');
48 }
49
50 $this->data = json_decode(File::get($this->path));
51 $this->plugField = new PlugField();
52 }
53
54 // public function teste(){
55
56 // $startTime = microTime(true);
57
58 // $stationId = 35;
59
60 // $actualDate = '1593473987000';
61
62 // $firstDate = '1590795587000';
63
64 // $client = new Client();
65
66 // $response = $client->request('GET', 'https://plugfield.com.br/api/device/35', [
67 // 'headers' => [
68 // 'Content-Type' => 'application/json',
69 // 'access_token' => 'sf24aajl3a8qeo3vk9s1t82305238gdk'
70 // ]
71 // ]);
72
73 // if($response->getStatusCode() == 200){
74
75 // $data = [];
76 // $station = json_decode($response->getBody()->getContents());
77 // $name = [];
78
79 // foreach ($station->sensorList as $s){
80
81 // $url = 'https://plugfield.com.br/api/sensorData?sensor='.$s->id.
82 // '&device='.$station->id.'&time='.$firstDate.'&timeMax='.$actualDate;
83
84 // $response2 = $client->request('GET', $url, [
85 // 'headers' => [
86 // 'Content-Type' => 'application/json',
87 // 'access_token' => 'sf24aajl3a8qeo3vk9s1t82305238gdk'
88 // ]
89 // ]);
90
91 // $data[$s->name] = [];
92 // array_push($data[$s->name], json_decode($response2->getBody()->getContents()));
93
94 // }
95
96 // }
97 // else {
98 // dd('Não foi possivel');
99 // }
100
101 // dd($data, $station, 'atual', $actualDate, 'primeira', $firstDate, elapsedTime($startTime));
102 // }
103 /**
104 * Trata os parâmetros conforme o tipo da estação (Manual ou Automática)
105 *
106 * @param integer $cropId
107 * @return void
108 */
109 private function getInmetParams($type, $keyParam, $keyValue, $data) {
110
111 $keyArr = [
112 'temperature' => [
113 'min' => [ 'T' => 'TEM_MIN', 'M' => 'TEMP_MIN' ],
114 'last' => [ 'T' => 'TEM_INS', 'M' => 'TEMP_HORA' ],
115 'max' => [ 'T' => 'TEM_MAX', 'M' => 'TEMP_MAX' ],
116 ],
117 'humidity' => [
118 'min' => [ 'T' => 'UMD_MIN', 'M' => 'UMD_MIN' ],
119 'last' => [ 'T' => 'UMD_INS', 'M' => 'UMID_HORA' ],
120 'max' => [ 'T' => 'UMD_MAX', 'M' => 'UMD_MAX' ],
121 ],
122 'wind-speed' => [
123 'last' => [ 'T' => 'VEN_VEL', 'M' => 'VENT_VEL' ],
124 ],
125 'wind-direction' => [
126 'last' => ['T' => 'VEN_DIR', 'M' => 'VENT_DIR']
127 ],
128 'preassure' => [
129 'last' => ['T' => 'PRE_INS', 'M' => 'PRESS_EST']
130 ],
131 'gust-speed' => [
132 'last' => ['T' => 'VEN_RAJ']
133 ]
134 ];
135
136 if ($data && isset($keyArr[$keyParam]) && isset($keyArr[$keyParam][$keyValue]) && isset($keyArr[$keyParam][$keyValue][$type]) && isset($data[$keyArr[$keyParam][$keyValue][$type]])) {
137 return $data[$keyArr[$keyParam][$keyValue][$type]];
138 }
139
140 return null;
141 }
142
143 /**
144 * Verifica se fez chuva ... sol ou se não há valor para o determinado dia
145 *
146 * @param [type] $cropId
147 * @param [type] $month
148 * @return void
149 */
150 public function getInmetStationInfoByDate($cropId, $month){
151
152 $date = Carbon::createFromFormat('Y-m', $month);
153
154 $month = date_format($date,"Y-m-d");
155
156 if ($month && is_numeric($cropId)) {
157
158 $user = Auth::user();
159
160 $crop = Crop::findById($cropId, $user)->select('crops.*', 'f.lat', 'f.lng')->first();
161
162 if($crop) {
163
164 try {
165
166 $fs = FarmStation::findByFarmId($crop->farm_id, $user)->select('farm_stations.*')->first();
167
168 $inmetStation = StationInmet::findByCoordinates($crop->lat, $crop->lng)->first();
169
170 if ($inmetStation) {
171
172 $url = 'https://apitempo.inmet.gov.br/estacao/' . $date->startOfMonth()->format('Y-m-d') . '/'
173 . $date->endOfMonth()->format('Y-m-d') . '/' . $inmetStation->code;
174
175 $client = new Client([ 'timeout' => 10 ]);
176
177 $options = [
178 "headers" => [
179 "Accept" => "*/*"
180 ]
181 ];
182
183 $response = $client->request('GET', $url, $options);
184
185 if ($response->getStatusCode() == Response::HTTP_OK) {
186
187 $data = json_decode($response->getBody()->getContents(), true);
188
189 if ($data && count($data) > 0) {
190
191 $data = Collect($data);
192
193 //Obtém datas disponíveis no mês
194 $days = $data->pluck('DT_MEDICAO')->unique()->values();
195
196 $calendar = [
197 'gathered_rain' => $data->whereNotNull('CHUVA')->sum('CHUVA'),
198 'dates' => []
199 ];
200
201 //Define valores por data
202 foreach ($days as $date ) {
203
204 $hasTemp = false;
205
206 //Obtém dados da data em questão
207 $dateInfo = $data->where('DT_MEDICAO', $date);
208 $pluviometrySum = $dateInfo->whereNotNull('CHUVA')->sum('CHUVA');
209
210 //Verifica se existem medições de temperatura
211 foreach($dateInfo as $info) {
212
213 $temperatureArrKey = 'temperature';
214
215 $inmetStationType = $inmetStation->type;
216
217 $tempLast = $this->getInmetParams($inmetStationType, $temperatureArrKey, 'last', $info);
218 $tempMin = $this->getInmetParams($inmetStationType, $temperatureArrKey, 'min', $info);
219 $tempMax = $this->getInmetParams($inmetStationType, $temperatureArrKey, 'max', $info);
220
221 if (isset($tempLast) || isset($tempMin) || isset($tempMax)) {
222
223 $hasTemp = true;
224 break;
225 }
226
227 }
228
229 //Define estrutura de medições da data atual
230 $calendar['dates'][$date] = [
231 'status' => ($pluviometrySum > 2) ? 'rain' : 'sun',
232 'has_data'=> $hasTemp,
233 'pluviometry' => number_format($pluviometrySum, 2)
234 ];
235
236 }
237
238 return $calendar;
239
240 }
241
242 } else {
243 return response('Não foi possível encontrar os dados climáticos', Response::HTTP_NOT_FOUND);
244 }
245 }
246 return response('O provedor de dados climáticos não respondeu', Response::HTTP_NOT_FOUND);
247
248 } catch (\Exception $e) {
249
250 return response('Houve um erro interno, tente novamente mais tarde.', Response::HTTP_INTERNAL_SERVER_ERROR);
251
252 }
253
254 return response('Estação não encontrada', Response::HTTP_NOT_FOUND);
255 }
256
257 return response('A safra informada não foi encontrada', Response::HTTP_NOT_FOUND);
258 }
259
260 return response('Safra inválida', Response::HTTP_BAD_REQUEST);
261
262 }
263
264 /*
265 * Pesquisa por estações públicas mais próximas
266 *
267 * @param [type] $coords
268 */
269 private function getStation($crop) {
270
271 $user = Auth::user();
272 $fs = FarmStation::findByFarmId($crop->farm_id, $user)
273 ->select('farm_stations.*')
274 ->first();
275
276 //Verifica se existe ao menos uma estação na fazenda!
277 if($fs) {
278
279 return $fs->stations->first();
280 } else {
281
282 //Obtém estações públicas mais próximas
283 $coords = [
284 'lat' => $crop->lat,
285 'lng' => $crop->lng
286 ];
287
288 return Station::searchPublicStations($user, $coords)
289 ->first();
290 }
291
292 }
293
294 /**
295 * Obtém os dados da estação do INMET
296 *
297 * @param integer $cropId
298 * @return void
299 */
300 public function getInmetStationInfoByCrop(Request $request, $cropId) {
301
302
303 if ($request->date) {
304 $currentDate = Carbon::parse($request->date)->format('Y-m-d');
305 } else {
306 $currentDate = date('Y-m-d');
307 }
308
309 if (is_numeric($cropId)) {
310
311 $user = Auth::user();
312
313 $crop = Crop::findById($cropId, $user)
314 ->select('crops.*', 'f.lat', 'f.lng')
315 ->first();
316
317 if($crop) {
318
319 try {
320
321 $station = $this->getStation($crop);
322
323 //Verifica se foi encontrado alguma estação disponível
324 if($station) {
325
326 return $this->getMeasures($station->id);
327 }
328
329 $inmetStation = StationInmet::findByCoordinates($crop->lat, $crop->lng)->first();
330
331 if ($inmetStation) {
332
333 $station = [];
334
335 $station['station'] = [
336 'code' => $inmetStation->code,
337 'name' => ucwords(strtolower($inmetStation->name)),
338 'lat' => $inmetStation->lat,
339 'lng' => $inmetStation->lng,
340 ];
341
342 $station['updated_at'] = null;
343
344 $station['sensors'] = [];
345
346 $url = 'https://apitempo.inmet.gov.br/estacao/' . $currentDate . '/' . $currentDate . '/' . $inmetStation->code;
347
348 $client = new Client([ 'timeout' => 10 ]);
349
350 $options = [
351 "headers" => [
352 "Accept" => "*/*"
353 ]
354 ];
355
356 $response = $client->request('GET', $url, $options);
357
358 if ($response->getStatusCode() == Response::HTTP_OK) {
359
360 $data = json_decode($response->getBody()->getContents(), true);
361
362 if ($data && count($data) > 0) {
363
364 $measures = collect([]);
365
366 $tempMinMin = null;
367 $tempMaxMax = null;
368 $rain = null;
369
370 foreach ($data as $row) {
371
372 if ($row['DT_MEDICAO'] && $row['HR_MEDICAO']) {
373
374 $date = Carbon::createFromFormat('Y-m-dHi', $row['DT_MEDICAO'].$row['HR_MEDICAO']);
375
376 $temperatureArrKey = 'temperature';
377
378 $inmetStationType = $inmetStation->type;
379
380 $tempLast = $this->getInmetParams($inmetStationType, $temperatureArrKey, 'last', $row);
381 $tempMin = $this->getInmetParams($inmetStationType, $temperatureArrKey, 'min', $row);
382 $tempMax = $this->getInmetParams($inmetStationType, $temperatureArrKey, 'max', $row);
383
384 if ($tempMin && (!$tempMinMin || $tempMin < $tempMinMin)) {
385 $tempMinMin = $tempMin;
386 }
387
388 if ($tempMax && (!$tempMaxMax || $tempMax > $tempMaxMax)) {
389 $tempMaxMax = $tempMax;
390 }
391
392 if ($date < now() && $tempLast) {
393
394 $station['updated_at'] = $date->format('Y-m-d H:i:s');
395
396 $sensors = [];
397
398 $temperatureInfo = [
399 'key' => 'temperature',
400 "unit" => "°",
401 "values" => [
402 "min" => $this->getInmetParams($inmetStationType, $temperatureArrKey, 'min', $row),
403 "last" => $tempLast,
404 "max" => $this->getInmetParams($inmetStationType, $temperatureArrKey, 'max', $row),
405 ]
406 ];
407
408 $altitudeInfo = [
409 'key' => 'altitude',
410 "unit" => "m",
411 "values" => [
412 "last" => $inmetStation->altitude,
413 ]
414 ];
415
416 array_push($sensors, $altitudeInfo, $temperatureInfo);
417
418 $humidityArrKey = 'humidity';
419
420 $currentHumidty = $this->getInmetParams($inmetStationType, $humidityArrKey, 'last', $row);
421
422 if (isset($currentHumidty)) {
423
424 $humidtyInfo = [
425 'key' => 'humidity',
426 "unit" => "%",
427 "values" => [
428 "min" => $this->getInmetParams($inmetStationType, $humidityArrKey, 'min', $row),
429 "last" => $currentHumidty,
430 "max" => $this->getInmetParams($inmetStationType, $humidityArrKey, 'max', $row)
431 ]
432 ];
433
434 array_push($sensors, $humidtyInfo);
435 }
436 if (isset($row['CHUVA'])) {
437
438 $rain = $rain + number_format($row['CHUVA'],2);
439
440 $pluviometryInfo = [
441 'key' => 'pluviometry',
442 "unit" => "mm",
443 "values" => [
444 "last" => number_format($rain,2),
445 ]
446 ];
447 array_push($sensors, $pluviometryInfo);
448 }
449
450 $currentWindSpeed = $this->getInmetParams($inmetStationType, 'wind-speed', 'last', $row);
451
452 if ($currentWindSpeed) {
453
454 $windSpeedInfo = [
455 'key' => 'wind-speed',
456 "unit" => "Km/h",
457 "values" => [
458 "last" => $currentWindSpeed,
459 ]
460 ];
461
462 array_push($sensors, $windSpeedInfo);
463 }
464
465 $currentWindDir = $this->getInmetParams($inmetStationType, 'wind-direction', 'last', $row);
466
467 if ($currentWindDir) {
468
469 $windDirection = [
470 'key' => 'wind-direction',
471 "unit" => null,
472 "values" => [
473 "last" => $currentWindDir,
474 ],
475 'formattedValues' => [
476 'last' => formatCardinalPoint($currentWindDir)
477 ]
478 ];
479
480 array_push($sensors, $windDirection);
481 }
482
483 $currentGustSpeed = $this->getInmetParams($inmetStationType, 'gust-speed', 'last', $row);
484
485 if ($currentGustSpeed) {
486
487 $gustSpeedInfo = [
488 'key' => 'gust-speed',
489 "unit" => 'Km/h',
490 "values" => [
491 "last" => $currentGustSpeed,
492 ],
493 ];
494
495 array_push($sensors, $gustSpeedInfo);
496 }
497
498 $currentPreassure = $this->getInmetParams($inmetStationType, 'preassure', 'last', $row);
499
500 if ($currentPreassure) {
501
502 $preassureInfo = [
503 'key' => 'pressure',
504 "unit" => "hPa",
505 "values" => [
506 "last" => $currentPreassure,
507 ]
508 ];
509
510 array_push($sensors, $preassureInfo);
511 }
512
513 $station['sensors'] = $sensors;
514
515 $measures->push($station);
516 }
517 }
518 }
519 if ($measures->count()) {
520
521 $station = $measures->sortBy('updated_at')->last();
522
523 //Atualiza a temperatura mínima e máxima do dia
524 if (isset($tempMinMin) || isset($tempMaxMax)) {
525
526 foreach($station['sensors'] as $k => $sensor) {
527
528 if ($sensor['key'] == 'temperature') {
529
530 if (isset($tempMinMin)) {
531 $station['sensors'][$k]['values']['min'] = $tempMinMin;
532 }
533
534 if (isset($tempMaxMax)) {
535 $station['sensors'][$k]['values']['max'] = $tempMaxMax;
536 }
537 }
538
539 }
540 }
541
542 return $station;
543
544 }
545
546 return response('Não foi possível encontrar dados climáticos para as últimas 24 horas', Response::HTTP_NOT_FOUND);
547 }
548 }
549
550 return response('Não foi possível encontrar dados climáticos para as últimas 24 horas', Response::HTTP_NOT_FOUND);
551 }
552 } catch (\Exception $e) {
553
554 return response('Houve um erro interno, tente novamente mais tarde.', Response::HTTP_INTERNAL_SERVER_ERROR);
555 }
556
557 return response('Estação não encontrada', Response::HTTP_NOT_FOUND);
558 }
559
560 return response('A safra informada não foi encontrada', Response::HTTP_NOT_FOUND);
561 }
562
563 return response('Safra inválida', Response::HTTP_BAD_REQUEST);
564 }
565
566 /**
567 * Retorna lista de estações disponíveis para o usuário.
568 *
569 * @param Request $request
570 * @return void
571 */
572 public function index(Request $request) {
573
574 $request = SessionFilter::updateFilters($request);
575 list($limit, $column, $sort, $status) = $filters = filterSearch($request, 50);
576
577 $stations = FarmStation::search($request->search, Auth::user())
578 ->select('st.*', 'farm_stations.id as fs_id', 'f.name as farm_name', 'p.name as producer_name')
579 ->orderBy('farm_stations.id', 'desc')
580 ->paginate(10);
581
582 return view('stations.index', [ "stations" => $stations,"filters" => $filters ]);
583 }
584
585 /**
586 * Retorna a lista de estações para a api
587 *
588 * @return void
589 */
590 public function getStations(Request $request) {
591
592 try {
593 $stations = FarmStation::search(null, Auth::user())
594 ->select('st.*', 'farm_stations.id as fs_id', 'f.name as farm_name', 'p.name as producer_name')
595 ->get();
596
597 return $stations;
598 } catch(\Exception $e) {
599
600 return response('Houve um erro interno, tente novamente mais tarde!', Response::HTTP_INTERNAL_SERVER_ERROR);
601 }
602 }
603
604 /**
605 * Carrega view para a criação de uma nova Estação Climática
606 *
607 * @return void
608 */
609 public function create() {
610
611 $station = new Station();
612 $farms = Farm::search()->select('farms.*')->get();
613
614 return view('stations.create-edit', ['station' => $station, 'farms' => $farms]);
615 }
616
617 /**
618 * Insere uma nova Estação Climática
619 *
620 * @param Request $request
621 * @return void
622 */
623 public function insert(Request $request, $recursively = false) {
624
625 $this->validate($request, [
626 'farm_id' => 'required|numeric|min:1|max:2147483647',
627 'name' => 'required|string|',
628 'key' => 'required|string',
629 ]);
630
631 try {
632
633 $deviceList = $this->plugField->deviceAssociate($request->key);
634
635 //Salva estação inserida na base de dados
636 $this->save($deviceList, $request);
637
638 return redirect('stations')->withSuccess('Estação inserida com sucesso!');
639
640 } catch(\Exception $e) {
641
642 //Verifica se o token foi expirado
643 if($e->getCode() == Response::HTTP_UNAUTHORIZED) {
644
645 //Verifica se é uma chamada recursiva
646 if(!$recursively) {
647 $login = $this->plugField->login();
648
649 if($login) {
650
651 //Tenta inserir novamente a estação
652 return $this->insert($request, true);
653 }
654 }
655
656 return back()->withErrors('Houve um erro interno, tente novamente mais tarde!');
657 } else {
658
659 return back()->withErrors('Houve um erro interno, tente novamente mais tarde!');
660 }
661 }
662 }
663
664 /**
665 * Salva estação inserida na base de dados
666 *
667 * @param [type] $key
668 * @param [type] $deviceList
669 */
670 private function save($deviceList, $request) {
671
672 //Filtra a lista de estções pela chave de acesso e retorna a estação inserida.
673 $device = arrayUnwrapp(array_filter($deviceList, function($elm) use ($request) {
674
675 return $elm->accessCode == $request->key;
676 }));
677
678 //Verifica se estação já existe.
679 $station = Station::where('device_id', $device->id)->first();
680
681 if(!$station) {
682 $station = new Station();
683 $station->name = $request->name;
684 $station->device_id = $device->id;
685 $station->lat = $device->latitude;
686 $station->lng = $device->longitude;
687 $station->is_public = $request->is_public;
688 $station->save();
689 }
690
691 //Verifica se a estação já está atrelada a fazenda solicitada.
692 $farmStation = FarmStation::findByRelation($station->id, $request->farm_id)->first();
693
694 if(!$farmStation) {
695
696 $farmStation = new FarmStation();
697
698 $farmStation->station_id = $station->id;
699 $farmStation->farm_id = $request->farm_id;
700 $farmStation->save();
701
702 } else {
703 throw new \Exception('Não foi possível inserir. Estação já esta atrelada á esta fazenda!');
704 }
705
706 }
707
708 /**
709 * Atauliza informações da Estação
710 *
711 * @return void
712 */
713 public function edit(Request $request, $stationId) {
714
715 try {
716
717 if(!empty($stationId)) {
718 $station = FarmStation::findById($stationId, Auth::user())->select('st.*', 'farm_stations.farm_id')->first();
719
720 if($station) {
721
722 $device = $this->plugField->getDevice($station->device_id);
723 $deviceInfo = (object)['lat' => $device->latitude, 'lng' => $device->longitude];
724 $farms = Farm::search()->select('farms.*')->get();
725
726 return view('stations.create-edit', ['station' => $station, 'deviceInfo' => $deviceInfo, 'farms' => $farms]);
727 }
728 }
729
730 return redirect('stations')->withErrors('Nada foi encontrado!');
731
732 } catch(\Exception $e) {
733
734 return back()->withErrors($e->getMessage());
735 }
736 }
737
738 /**
739 * Atualiza um registro
740 *
741 * @return void
742 */
743 public function update(Request $request) {
744
745 $this->validate($request, [
746 'farm_id' => 'required|numeric|min:1|max:2147483647',
747 'name' => 'required|string|',
748 ]);
749
750 $station = Station::findById($request->station_id, Auth::user())->first();
751
752 if($station) {
753
754 //Verifica se a estação já está atrelada a fazenda solicitada.
755 $farmStation = FarmStation::findByRelation($station->id, $request->farm_id)->first();
756
757 if($farmStation) {
758
759 $station->name = $request->name;
760 $farmStation->farm_id = $request->farm_id;
761 $station->is_public = $request->is_public;
762
763 $station->save();
764
765 return redirect('stations')->withSuccess('Estação atualizada com sucesso!');
766 }
767
768 }
769
770 return redirect('stations')->withErrors('Nada foi encontrado!');
771 }
772
773 /**
774 * Remove uma associação.
775 *
776 * @return void
777 */
778 public function delete(Request $request) {
779
780 $this->validate($request, [
781 'id' => 'required|numeric'
782 ]);
783
784 $farmStations = FarmStation::findById($request->id, Auth::user())->select('farm_stations.*')->first();
785
786 if($farmStations) {
787
788 try {
789
790 $farmStations->stations()->delete();
791 $farmStations->delete();
792
793 return back()->withSuccess('Estação removida com sucesso!');
794 } catch(\Exception $e) {
795
796 return back()->withErrors('Houve um erro interno, tente novamente mais tarde!');
797 }
798 }
799
800 return redirect('farms')->withErrors('Nada foi encontrado!');
801 }
802
803 /**
804 * Retorna estações juntamente com seus valores atuais.
805 *
806 * @return void
807 */
808 public function getStationsDashboard(Request $request) {
809
810 $this->validate($request, [
811 'farm_id' => 'required|numeric'
812 ]);
813
814 $query = FarmStation::join('stations as st', 'st.id', 'farm_stations.station_id' )
815 ->where('farm_id', $request->farm_id);
816
817 if($request->station_id) {
818 $query->where('station_id', $request->station_id);
819 }
820
821 $stationsIds = $query->select('farm_stations.id', 'st.device_id')
822 ->pluck('device_id', 'farm_stations.id')->toArray();
823
824 $deviceList = $this->plugField->getDeviceList();
825
826 if(!empty($stationsIds)) {
827
828 $stations = array_filter($deviceList, function($elm) use($stationsIds) {
829
830 if(in_array($elm->id, $stationsIds)) {
831
832 $elm->fs_id = array_search($elm->id, $stationsIds);
833 }
834
835 return in_array($elm->id, $stationsIds) == true;
836 });
837
838 return $stations;
839 } else {
840 return null;
841 }
842 }
843
844 /**
845 * Retorna o dashboard de uma estação especificada pelo id.
846 *
847 * @param Request $request
848 */
849 public function getMeasures($stationId, $repeat = true) {
850
851 try {
852
853 // $station = FarmStation::findById($farmStationId, Auth::user())
854 // ->select('st.*', 'farm_stations.farm_id')
855 // ->first();
856
857 $station = Station::findById($stationId, Auth::user())
858 ->select('stations.*')
859 ->first();
860
861 $device = null;
862
863 if(!$this->checkLastUpdate()) {
864
865 $device = $this->plugField->getDevice($station->device_id);
866
867 } else {
868
869 $device = $this->getLocalDashboard($station->device_id);
870 }
871
872 if($device) {
873
874 $measure = [];
875
876 $measure['station'] = [
877 "code" => $device->serialNumber,
878 "name" => $device->name,
879 "lat" => $device->latitude,
880 "lng" => $device->longitude
881 ];
882
883 $updatedAt = Carbon::createFromFormat('d/m/Y H:i', $device->updateDateTime);
884
885 $measure['updated_at'] = $updatedAt->format('Y-m-d H:i:s');
886
887 $measure['sensors'] = [];
888
889 if (isset($device->altitude)) {
890
891 $altitudeInfo = [
892
893 "key" => "altitude",
894 "unit" => "m",
895 "values" => [
896 "last" => $device->altitude
897 ]
898 ];
899
900 array_push($measure['sensors'], $altitudeInfo);
901 }
902
903 if ($device->dashboard) {
904
905 if (isset($device->dashboard->temp)) {
906
907 $temperatureInfo = [
908 'key' => 'temperature',
909 'unit' => '°',
910 'values' => [
911 'last' => $device->dashboard->temp
912 ]
913 ];
914
915 if ($device->dashboard->tempMin) {
916
917 $temperatureInfo['values']['min'] = $device->dashboard->tempMin;
918 }
919
920 if($device->dashboard->tempMax) {
921
922 $temperatureInfo['values']['max'] = $device->dashboard->tempMax;
923 }
924
925 array_push($measure['sensors'], $temperatureInfo);
926 }
927
928 if (isset($device->dashboard->humi)) {
929
930 $humidtyInfo = [
931 'key' => 'humidity',
932 'unit' => '%',
933 'values' => [
934 'last' => $device->dashboard->humi
935 ]
936 ];
937
938 array_push($measure['sensors'], $humidtyInfo);
939 }
940
941 if (isset($device->dashboard->rain)) {
942
943 $pluviometryInfo = [
944 'key' => 'pluviometry',
945 'unit' => 'mm',
946 'values' => [
947 'last' => $device->dashboard->rain,
948 'day' => $device->dashboard->rainDay,
949 'month' => $device->dashboard->rainMonth,
950 'year' => $device->dashboard->rainYear
951 ]
952 ];
953
954 array_push($measure['sensors'], $pluviometryInfo);
955 }
956
957 if (isset($device->dashboard->wind)) {
958
959 $windSpeedInfo = [
960 'key' => 'wind-speed',
961 'unit' => 'Km/h',
962 'values' => [
963 'last' => $device->dashboard->wind,
964 ],
965 ];
966
967 array_push($measure['sensors'], $windSpeedInfo);
968 }
969
970 if (isset($device->dashboard->dire)) {
971
972 $windDirectionInfo = [
973 'key' => 'wind-direction',
974 'unit' => null,
975 'values' => [
976 'last' => $device->dashboard->dire,
977 ],
978 'formattedValues' => [
979 'last' => $device->dashboard->direString
980 ]
981 ];
982
983 array_push($measure['sensors'], $windDirectionInfo);
984 }
985
986 if (isset($device->dashboard->winb)) {
987
988 $gustSpeedInfo = [
989 'key' => 'gust-speed',
990 "unit" => 'Km/h',
991 "values" => [
992 "last" => $device->dashboard->winb,
993 ],
994 ];
995
996 array_push($measure['sensors'], $gustSpeedInfo);
997 }
998
999 if (isset($device->dashboard->prre)) {
1000
1001 $preassureInfo = [
1002 'key' => 'pressure',
1003 'unit' => 'hPa',
1004 'values' => [
1005 'last' => $device->dashboard->prre,
1006 ],
1007 ];
1008
1009 array_push($measure['sensors'], $preassureInfo);
1010 }
1011
1012 if (isset($device->dashboard->radi)) {
1013
1014 $solarRadiationInfo = [
1015 'key' => 'solar-radiation',
1016 'unit' => 'lux',
1017 'values' => [
1018 'last' => $device->dashboard->radi,
1019 ],
1020 ];
1021
1022 array_push($measure['sensors'], $solarRadiationInfo);
1023 }
1024
1025 if (isset($device->dashboard->uv)) {
1026
1027 $uvRadiationInfo = [
1028 'key' => 'uv',
1029 'unit' => null,
1030 'values' => [
1031 'last' => $device->dashboard->uv,
1032 ],
1033 ];
1034
1035 array_push($measure['sensors'], $uvRadiationInfo);
1036 }
1037
1038 if (isset($device->dashboard->duep)) {
1039
1040 $duepInfo = [
1041 'key' => 'dew-point',
1042 'unit' => '°',
1043 'values' => [
1044 'last' => $device->dashboard->duep,
1045 ],
1046 ];
1047
1048 array_push($measure['sensors'], $duepInfo);
1049 }
1050 }
1051
1052 return $measure;
1053
1054 } else {
1055
1056 return response('Houve um erro.', Response::HTTP_INTERNAL_SERVER_ERROR);
1057 }
1058
1059 } catch(\Exception $e) {
1060
1061 //Verifica se é uma chamada recursiva
1062 if($e->getCode() == Response::HTTP_UNAUTHORIZED && $repeat) {
1063
1064 $login = $this->plugField->login();
1065
1066 if($login) {
1067
1068 //Tenta buscar novamente o dashboard
1069 return $this->getMeasures($stationId, false);
1070 }
1071 }
1072
1073 return response($e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
1074 }
1075 }
1076
1077 /**
1078 * Retorna o dashboard de uma estação especificada pelo id, a partir das informações gravadas localmente.
1079 *
1080 * @param [type] $deviceId
1081 * @return void
1082 */
1083 private function getLocalDashboard($deviceId) {
1084
1085 $devices = collect($this->data->data);
1086
1087 return $devices->where('id', $deviceId)->first();
1088 }
1089
1090 /**
1091 * Checa a última atualização das informações e verifica se deve buscar novamente
1092 *
1093 * @return void
1094 */
1095 private function checkLastUpdate() {
1096
1097 if(isset($this->data)) {
1098
1099 $createdAt = Carbon::create($this->data->created_at);
1100 $diff = $createdAt->diffInMinutes(now());
1101
1102 if($diff < 5) {
1103 return true;
1104 }
1105 }
1106
1107 return false;
1108 }
1109
1110 /**
1111 * Retorna um json com os nomes e as métricas dos sensores.
1112 *
1113 * @return void
1114 */
1115 public function getMetrics() {
1116 return File::get(storage_path().'/cache/plug-field-metrics.json');
1117 }
1118}