From de53ecbb16705ed4e4659472280fb74a2cf787b1 Mon Sep 17 00:00:00 2001 From: vine_liutk <961510893@qq.com> Date: Tue, 11 Jul 2023 18:35:01 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=96=B7=E9=9B=BE?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Admin/Controllers/DeviceController.php | 88 +++++++++++++++++-- .../Controllers/MonitorModeController.php | 2 +- app/Admin/routes.php | 2 + app/Console/Commands/MqttPenwuPlan.php | 37 ++++++++ app/Models/Region.php | 2 +- app/Services/MqttService.php | 59 +++++++++++++ 6 files changed, 179 insertions(+), 11 deletions(-) create mode 100644 app/Console/Commands/MqttPenwuPlan.php create mode 100644 app/Services/MqttService.php diff --git a/app/Admin/Controllers/DeviceController.php b/app/Admin/Controllers/DeviceController.php index bdb9745..8abac77 100644 --- a/app/Admin/Controllers/DeviceController.php +++ b/app/Admin/Controllers/DeviceController.php @@ -13,6 +13,7 @@ use App\Models\MeteorologicalReport; use App\Models\MonitorMode; use App\Models\Region; use Illuminate\Http\Request; +use App\Services\MqttService; class DeviceController extends AdminController { @@ -279,7 +280,6 @@ class DeviceController extends AdminController amisMake()->Wrapper()->sm(6)->body([ amisMake()->Panel()->title('智能开关设置') ->labelWidth(100) - ->className('Panel--success') ->body([ \amisMake()->Form()->title('')->mode('horizontal')->body([ amisMake()->FieldSetControl()->title('智能开启')->body([ @@ -325,7 +325,6 @@ class DeviceController extends AdminController ]), amisMake()->Wrapper()->sm(6)->body([ amisMake()->Panel()->title('开关记录') - ->className('Panel--success') ->body([ \amisMake()->Table()->title('') ->data([ @@ -348,23 +347,79 @@ class DeviceController extends AdminController } /** - * 喷灌 + * 喷雾 */ public function atomizingDetail(){ + $regionId = request()->input('region_id', 0); + $config = null; + $statusStr = '未知'; + if($regionId){ + $region = Region::find($regionId); + if($region){ + $monitorMode = $region->monitorModes()->where('type', MonitorMode::TYPE_ATOMIZING)->first(); + $config = $monitorMode?->pivot->config ?? null; + + if($monitorMode){ + //判断设备状态是否离线; + $device = $monitorMode->devices()->first(); + if($device->state == Device::STATE_ONLINE){ + $res = (new MqttService())->getStatus(); + if($res['error']){ + switch($res['error']){ + case 1: + $statusStr = '急停'; + break; + case 2: + $statusStr = '低水位报警'; + break; + } + }else{ + if($res['is_running']){ + if($res['yv1']){ + $statusStr = '区域A运行中,喷雾量:'.$res['speed1'].'%'; + }elseif(['yv2']){ + $statusStr = '区域B运行中,喷雾量:'.$res['speed2'].'%'; + } + }else{ + $statusStr = '未运行'; + } + } + }else{ + $statusStr = Device::stateMap()[$device->state]; + } + } + } + } + return amisMake()->Grid()->columns([ amisMake()->Wrapper()->sm(6)->body([ amisMake()->Panel()->title('智能喷灌设置') ->subFormMode('horizontal') ->labelWidth(80) - ->className('Panel--success') ->body([ - \amisMake()->Form()->title('')->mode('horizontal')->body([ - amisMake()->FieldSetControl()->title('定时喷灌')->body([ + \amisMake()->Form()->title('')->mode('horizontal') + ->api([ + 'method'=>'post', + 'url'=>admin_url('save-region-config').'/'.$regionId, + 'data'=>[ + 'is_enable' => '${is_enable}', + 'config' => '${config}' + ] + ]) + ->data($config ? json_decode($config) : []) + ->body([ + amisMake()->FieldSetControl()->title('当前状态')->body([ + amisMake()->TextControl('status', '状态')->value($statusStr), + ])->static(), + amisMake()->FieldSetControl()->className('mt-10')->title('定时喷灌')->body([ \amisMake()->SwitchControl()->name('is_enable')->label('开关'), \amisMake()->ArrayControl()->name('config')->label('定时')->items([ amisMake()->ComboControl()->items([ - \amisMake()->InputTimeRange(), - \amisMake()->TextControl()->name('input')->label('喷灌量')->labelWidth(30), + amisMake()->SelectControl('value')->options([ + 'a'=>'区域A','b'=>'区域B' + ]), + \amisMake()->InputTimeRange()->name('time_zone'), + Components::make()->decimalControl('input', '喷雾量%')->value(70)->percision(0)->step(1)->max(100) ]), ]), ]), @@ -373,7 +428,6 @@ class DeviceController extends AdminController ]), amisMake()->Wrapper()->sm(6)->body([ amisMake()->Panel()->title('开关记录') - ->className('Panel--success') ->body([ \amisMake()->Table()->title('') ->data([ @@ -394,4 +448,20 @@ class DeviceController extends AdminController ]), ]); } + + public function saveRegionConfig($id, Request $request) + { + if($id){ + $region = Region::find($id); + if($region){ + $monitorMode = $region->monitorModes()->where('type', MonitorMode::TYPE_ATOMIZING)->first(); + $config = $request->input() ?? null; + $res = $region->monitorModes()->updateExistingPivot($monitorMode->id, [ + 'config' => $config, + ]); + } + } + + return $this->autoResponse($res, __('admin.save')); + } } diff --git a/app/Admin/Controllers/MonitorModeController.php b/app/Admin/Controllers/MonitorModeController.php index dc7e648..4a16d94 100644 --- a/app/Admin/Controllers/MonitorModeController.php +++ b/app/Admin/Controllers/MonitorModeController.php @@ -168,7 +168,7 @@ class MonitorModeController extends AdminController amisMake()->PickerControl('picker_devices', '喷雾设备')->visibleOn('data.type == '.MonitorMode::TYPE_ATOMIZING) ->valueField('id') ->labelField('name') - ->multiple(true) + ->multiple(false)//喷雾设备只能选择一个 ->size('lg') ->source([ 'method' => 'get', diff --git a/app/Admin/routes.php b/app/Admin/routes.php index ceb4338..d320bf8 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -91,6 +91,8 @@ Route::group([ $router->post('custom-region-atomizing', '\App\Admin\Controllers\DeviceController@atomizingDetail'); + $router->post('save-region-config/{id}', '\App\Admin\Controllers\DeviceController@saveRegionConfig'); + //种植记录 $router->resource('crop-plants', \App\Admin\Controllers\CropPlantController::class)->only(['index','store', 'edit', 'update', 'destroy']); $router->resource('crop-harvestes', \App\Admin\Controllers\CropHarvestController::class)->only(['index','store', 'edit', 'update', 'destroy']); diff --git a/app/Console/Commands/MqttPenwuPlan.php b/app/Console/Commands/MqttPenwuPlan.php new file mode 100644 index 0000000..886462d --- /dev/null +++ b/app/Console/Commands/MqttPenwuPlan.php @@ -0,0 +1,37 @@ +belongsToMany(MonitorMode::class, RegionMonitor::class, 'region_id', 'monitor_id')->withTimestamps(); + return $this->belongsToMany(MonitorMode::class, RegionMonitor::class, 'region_id', 'monitor_id')->withTimestamps()->withPivot('config'); } // 种植记录 diff --git a/app/Services/MqttService.php b/app/Services/MqttService.php new file mode 100644 index 0000000..c517c6d --- /dev/null +++ b/app/Services/MqttService.php @@ -0,0 +1,59 @@ + 'application/json;charset=UTF-8', + ])->get('http://36.133.205.221:92/status'); + return $res->json(); + } + + public function mqttDo($parms) + { + $res = Http::withHeaders([ + 'Content-Type' => 'application/json;charset=UTF-8', + ])->post('http://36.133.205.221:92/mqtt', $parms); + return $res->json(); + } + + /** + * 开启哪个区域,多大量 + */ + public function open($quyu, $liang) + { + $parms = [ + 'speed1' => 0, + 'speed2' => 0, + 'yv1' => 0, + 'yv2' => 0, + ]; + switch($quyu){ + case 'a': + $parms['speed1'] = $liang; + $parms['yv1'] = 1; + break; + case 'b': + $parms['speed2'] = $liang; + $parms['yv2'] = 1; + break; + } + return $this->mqttDo($parms); + } + + public function close(){ + $parms = [ + 'speed1' => 0, + 'speed2' => 0, + 'yv1' => 0, + 'yv2' => 0, + ]; + return $this->mqttDo($parms); + } +} \ No newline at end of file From ff775ec9d59293df43d867f019ee02a1ad6046ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 17 Jul 2023 12:00:06 +0800 Subject: [PATCH 2/8] Fix --- app/Services/DeviceLogService.php | 87 +++++++------------------------ 1 file changed, 19 insertions(+), 68 deletions(-) diff --git a/app/Services/DeviceLogService.php b/app/Services/DeviceLogService.php index 478f7cd..a345dd9 100644 --- a/app/Services/DeviceLogService.php +++ b/app/Services/DeviceLogService.php @@ -56,74 +56,25 @@ class DeviceLogService continue; } - if ($device->isTypeSoil()) { - // 如果包含气象设备监测字段,则跳过 - if (Arr::hasAny($item['data'], [ - 'day_rainfall', - 'accumulate_rainfall', - 'potassium_content', - 'moment_rainfall', - 'pm10_concentration', - 'pm25_concentration', - 'box_noise', - 'box_carbon', - 'box_humidity', - 'box_pressure', - 'box_temperature', - 'box_illumination', - 'wind_power', - 'wind_speed', - 'wind_degree', - 'wind_direction', - ])) { - continue; - } - } elseif ($device->isTypeMeteorological()) { - // 如果包含土壤设备监测字段,则跳过 - if (Arr::hasAny($item['data'], [ - 'nitrogen_content', - 'phosphorus_content', - 'potassium_content', - 'conductivity', - 'soil_humidity', - 'soil_temperature', - ])) { - continue; - } - } - - if ( - $device->isTypeSoil() && Arr::hasAny($item['data'], [ - - ]) - ) { - - } elseif ( - $device->isTypeMeteorological() && - Arr::hasAny( - $item['data'], - [ - 'nitrogen_content', - 'phosphorus_content', - 'potassium_content', - 'conductivity', - 'soil_humidity', - 'soil_temperature', - ] - ) - ) { - continue; - } - - $isSoilMonitoring = Arr::hasAny($item['data'], [ - 'soil_humidity', - 'soil_temperature', - 'nitrogen_content', - 'potassium_content', - 'phosphorus_content', - ]); - - if (($device->isTypeSoil() && ! $isSoilMonitoring) || (! $device->isTypeSoil() && $isSoilMonitoring)) { + // 如果多合一气象监测器包含土壤监控时,需过滤掉气象监控的数据 + if ($device->isTypeSoil() && Arr::hasAny($item['data'], [ + 'current_rainfall', + 'day_rainfall', + 'accumulate_rainfall', + 'moment_rainfall', + 'pm10_concentration', + 'pm25_concentration', + 'box_illumination', + 'box_pressure', + 'box_carbon', + 'box_temperature', + 'box_humidity', + 'box_noise', + 'wind_degree', + 'wind_direction', + 'wind_power', + 'wind_speed', + ])) { continue; } From 1414cfae3de00176888a076cdcd1a59f8fb08953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 17 Jul 2023 12:53:17 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=B8=8B=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/DeviceLogSyncCommand.php | 1 - app/Iot/Linkos/HttpClient.php | 37 +++++++++++++++---- app/Services/DeviceLogService.php | 2 +- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/Console/Commands/DeviceLogSyncCommand.php b/app/Console/Commands/DeviceLogSyncCommand.php index 8a900ea..28020b0 100644 --- a/app/Console/Commands/DeviceLogSyncCommand.php +++ b/app/Console/Commands/DeviceLogSyncCommand.php @@ -5,7 +5,6 @@ namespace App\Console\Commands; use App\Models\Device; use App\Services\DeviceLogService; use Illuminate\Console\Command; -use Illuminate\Support\Carbon; use Throwable; class DeviceLogSyncCommand extends Command diff --git a/app/Iot/Linkos/HttpClient.php b/app/Iot/Linkos/HttpClient.php index 1b01273..0d3a725 100644 --- a/app/Iot/Linkos/HttpClient.php +++ b/app/Iot/Linkos/HttpClient.php @@ -26,7 +26,7 @@ class HttpClient * @param int $perPage * @return array */ - public function getDeviceFlowList(string $deviceId, Carbon $start, Carbon $end, int $page = 1, int $perPage = 50): array + public function deviceFlowList(string $deviceId, Carbon $start, Carbon $end, int $page = 1, int $perPage = 50): array { $result = $this->post('/api/deviceFlow/v1/list', [ 'device_id' => $deviceId, @@ -38,9 +38,36 @@ class HttpClient ], ]); + if (data_get($result, 'success') !== true) { + throw new RuntimeException(data_get($result, 'msg', '出错啦!')); + } + return $result['data']; } + /** + * 设备数据下行 + * + * @param string $deviceId + * @param string $service + * @param array $data + * @param boolean $confirm + * @param boolean $clear + * @param boolean $schedule + * @return array + */ + public function deviceDataDownlink(string $deviceId, string $service, array $data = [], bool $confirm = true, bool $clear = true, bool $schedule = false): array + { + return $this->post('/api/down', [ + 'device_id' => $deviceId, + 'service_id' => $service, + 'parameter' => $data, + 'clear' => (int) $clear, + 'schedule' => (int) $schedule, + 'confirm' => (int) $confirm, + ]); + } + /** * @param string $url * @param array $data @@ -77,13 +104,7 @@ class HttpClient 'Signature' => $this->sign(compact('nonce', 'timestamp')), ])->baseUrl(self::ENDPOINT_URL)->send($method, $url, $options); - $result = $response->throw()->json(); - - if (data_get($result, 'success') !== true) { - throw new RuntimeException(data_get($result, 'msg', '出错啦!')); - } - - return $result; + return $response->throw()->json(); } /** diff --git a/app/Services/DeviceLogService.php b/app/Services/DeviceLogService.php index a345dd9..f5dfe3a 100644 --- a/app/Services/DeviceLogService.php +++ b/app/Services/DeviceLogService.php @@ -41,7 +41,7 @@ class DeviceLogService $perPage = 50; do { - $data = $httpClient->getDeviceFlowList( + $data = $httpClient->deviceFlowList( $device->sn, $start, $end, $page, $perPage ); From aec3b6a338797482cfd21e124f263e7067f5fabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 17 Jul 2023 13:35:40 +0800 Subject: [PATCH 4/8] Update --- app/Http/Controllers/Callback/LinkosCallbackController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Callback/LinkosCallbackController.php b/app/Http/Controllers/Callback/LinkosCallbackController.php index 1ccabcf..d3d2938 100644 --- a/app/Http/Controllers/Callback/LinkosCallbackController.php +++ b/app/Http/Controllers/Callback/LinkosCallbackController.php @@ -10,7 +10,7 @@ class LinkosCallbackController extends Controller { public function __invoke(Request $request) { - logger()->info('linkos callback parameters -------->', $request->input()); + logger()->debug('linkos callback parameters -------->', $request->input()); if ($request->filled('notify_type')) { switch ($request->notify_type) { From 132c36e9eff65b419df8b2a705322f1db92de717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 17 Jul 2023 13:50:17 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E9=80=9A=E9=A3=8E=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=83=A8=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/DeviceLogSyncCommand.php | 6 ++++++ app/Models/Device.php | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/app/Console/Commands/DeviceLogSyncCommand.php b/app/Console/Commands/DeviceLogSyncCommand.php index 28020b0..02bc61c 100644 --- a/app/Console/Commands/DeviceLogSyncCommand.php +++ b/app/Console/Commands/DeviceLogSyncCommand.php @@ -63,7 +63,13 @@ class DeviceLogSyncCommand extends Command /** @var \Illuminate\Database\Eloquent\Collection */ $devices = Device::with(['factory'])->poweredBy($factory)->get(); + /** @var \App\Models\Device */ foreach ($devices as $device) { + // 忽略通风设备 + if ($device->isTypeAir()) { + continue; + } + $this->info('=========================================='); $this->info('设备编号: ' . $device->sn); $this->info('设备名称: ' . $device->name); diff --git a/app/Models/Device.php b/app/Models/Device.php index 0afe60b..4ed8252 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -87,4 +87,9 @@ class Device extends Model { return $this->type === static::TYPE_METEOROLOGICAL; } + + public function isTypeAir(): bool + { + return $this->type === static::TYPE_AIR; + } } From f11d16251de89234276da6abd69f98f1036d887c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Mon, 24 Jul 2023 14:13:20 +0800 Subject: [PATCH 6/8] Update --- app/Services/DeviceLogService.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/Services/DeviceLogService.php b/app/Services/DeviceLogService.php index f5dfe3a..e3c35d2 100644 --- a/app/Services/DeviceLogService.php +++ b/app/Services/DeviceLogService.php @@ -448,6 +448,10 @@ class DeviceLogService switch ($key) { case 'wind_samples': $attributes['wind_degree'] = value(function (array $windSamples) { + if (empty($windSamples)) { + return null; + } + $x = 0; $y = 0; @@ -477,6 +481,10 @@ class DeviceLogService }, $item); $attributes['wind_direction'] = value(function ($windDegree) { + if (is_null($windDegree)) { + return null; + } + if ($windDegree >= 22.5 && $windDegree < 67.5) { return MeteorologicalDailyReport::WIND_DIRECTION_NORTHEAST; } elseif ($windDegree >= 67.5 && $windDegree < 112.5) { From 151f7877e4f62d00404567d6953071c8ccd2a6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Thu, 27 Jul 2023 15:47:40 +0800 Subject: [PATCH 7/8] Update --- app/Iot/Linkos/HttpClient.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/Iot/Linkos/HttpClient.php b/app/Iot/Linkos/HttpClient.php index 0d3a725..758fed8 100644 --- a/app/Iot/Linkos/HttpClient.php +++ b/app/Iot/Linkos/HttpClient.php @@ -68,6 +68,13 @@ class HttpClient ]); } + public function get(string $url, array $query = []): array + { + return $this->request('GET', $url, [ + 'query' => $query, + ]); + } + /** * @param string $url * @param array $data From 8da20ed9adb496fc3346159a132bce94941ef630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Thu, 27 Jul 2023 15:52:32 +0800 Subject: [PATCH 8/8] Update --- app/Iot/Linkos/HttpClient.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/Iot/Linkos/HttpClient.php b/app/Iot/Linkos/HttpClient.php index 758fed8..7900a4e 100644 --- a/app/Iot/Linkos/HttpClient.php +++ b/app/Iot/Linkos/HttpClient.php @@ -68,6 +68,23 @@ class HttpClient ]); } + /** + * 获取设备最新属性数据 + */ + public function getDeviceStatus(string $deviceId, array $props): array + { + $result = $this->get('/api/deviceStatus/v1/getDeviceStatus', [ + 'deviceCode' => $deviceId, + 'prop' => implode(",", $props), + ]); + + if (data_get($result, 'success') !== true) { + throw new RuntimeException(data_get($result, 'msg', '出错啦!')); + } + + return $result['data']; + } + public function get(string $url, array $query = []): array { return $this->request('GET', $url, [