// +---------------------------------------------------------------------- declare(strict_types=1); namespace addon\iot\controller\api; use think\facade\Db; use addon\iot\service\DeviceService; use addon\iot\service\ShareService; use addon\iot\service\OtaService; /** * App 端 OTA 域 API(需框架会员 JWT 登录) * 路由前缀:/iot/api/ota/...(OTA 域;旧 /iot/api/client/* 兼容别名迁移期保留) * * 覆盖:固件查询与升级指令下发。 */ class Ota extends ClientBase { /** * 我的设备可用的固件 * GET /iot/api/ota/otaList?uuid=xxx(不传 uuid 返回全部设备) * 返回:{ device, ota|null },App 端比对影子里的 version 判断是否有新版本 */ public function otaList() { $uid = $this->memberId(); if ($uid <= 0) { return $this->result->apiError('未登录'); } $uuid = trim((string) $this->request->get('uuid', '')); // OTA 列表只用设备行(model 等),不需要位置配置:false 省掉 2 条 SQL 与响应体积 $devices = DeviceService::visibleDevices($uid, false); if ($uuid !== '') { $devices = array_values(array_filter($devices, fn($d) => $d['uuid'] === $uuid)); } $cache = []; $list = []; foreach ($devices as $d) { $model = (string) $d['model']; if ($model === '') { $list[] = ['device' => $d, 'ota' => null]; continue; } if (!isset($cache[$model])) { $cache[$model] = Db::name('iot_ota') ->where('model', $model)->where('status', 1) ->order('id', 'desc')->find(); } $list[] = ['device' => $d, 'ota' => $cache[$model] ?: null]; } return $this->result->apiSuccess(['list' => $list, 'total' => count($list)]); } /** * 我的设备 OTA 升级 * POST /iot/api/ota/publishOta * param: ota_id, uuid */ public function publishOta() { $uid = $this->memberId(); if ($uid <= 0) { return $this->result->apiError('未登录'); } $otaId = (int) $this->request->post('ota_id', 0); $uuid = trim((string) $this->request->post('uuid', '')); if (!$otaId) { return $this->result->apiError('固件不能为空'); } if ($uuid === '') { return $this->result->apiError('设备uuid不能为空'); } $dev = DeviceService::findByUuid($uuid); if (!$dev) { return $this->result->apiError('设备不存在'); } if (!ShareService::canAccess($uuid, $uid, ShareService::PERM_CTRL)) { return $this->result->apiError('无权控制该设备'); } try { $n = OtaService::publish($otaId, [$uuid]); } catch (\Throwable $e) { return $this->result->apiError($e->getMessage()); } return $this->result->apiSuccess(['affected' => $n, 'uuid' => $uuid]); } }