Yeelight /
miot-api
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * Created by PhpStorm. |
||
| 4 | * User: sheldon |
||
| 5 | * Date: 18-6-14 |
||
| 6 | * Time: 下午4:39. |
||
| 7 | */ |
||
| 8 | |||
| 9 | namespace MiotApi\Api; |
||
| 10 | |||
| 11 | use MiotApi\Contract\Instance\Instance; |
||
| 12 | use MiotApi\Exception\ApiErrorException; |
||
| 13 | |||
| 14 | /** |
||
| 15 | * 更方便的API调用. |
||
| 16 | * |
||
| 17 | * Class Api |
||
| 18 | */ |
||
| 19 | class Api extends BaseApi |
||
| 20 | { |
||
| 21 | /** |
||
| 22 | * 一次性获取到包含了 serialNumber (原did)的设备列表. |
||
| 23 | * |
||
| 24 | * @return array|mixed |
||
| 25 | */ |
||
| 26 | public function devicesList() |
||
| 27 | { |
||
| 28 | $devicesList = []; |
||
| 29 | $devices = $this->devices(); |
||
| 30 | |||
| 31 | if (isset($devices['devices'])) { |
||
| 32 | if (!empty($devices['devices'])) { |
||
| 33 | foreach ($devices['devices'] as $device) { |
||
| 34 | $dids[] = $device['did']; |
||
| 35 | $device['serialNumber'] = null; |
||
| 36 | $devicesList[$device['did']] = $device; |
||
| 37 | } |
||
| 38 | |||
| 39 | $deviceInformations = $this->deviceInformation($dids); |
||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||
| 40 | |||
| 41 | if (isset($deviceInformations['device-information'])) { |
||
| 42 | foreach ($deviceInformations['device-information'] as $deviceInformation) { |
||
| 43 | if (isset($devicesList[$deviceInformation['id']])) { |
||
| 44 | $devicesList[$deviceInformation['id']]['serialNumber'] = $deviceInformation['serialNumber']; |
||
| 45 | } |
||
| 46 | } |
||
| 47 | } |
||
| 48 | |||
| 49 | return array_values($devicesList); |
||
| 50 | } else { |
||
| 51 | // 没有设备的情况 |
||
| 52 | return []; |
||
| 53 | } |
||
| 54 | } else { |
||
| 55 | // 获取设备出错 |
||
| 56 | return $devices; |
||
| 57 | } |
||
| 58 | } |
||
| 59 | |||
| 60 | /** |
||
| 61 | * 按照名称获取属性. |
||
| 62 | * |
||
| 63 | * @param $did |
||
| 64 | * @param $type |
||
| 65 | * @param $data | $data = ['brightness', 'on'] |
||
|
0 ignored issues
–
show
|
|||
| 66 | * |
||
| 67 | * @throws ApiErrorException |
||
| 68 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 69 | * |
||
| 70 | * @return array|bool|mixed |
||
| 71 | */ |
||
| 72 | public function getPropertyGraceful($did, $type, $data) |
||
| 73 | { |
||
| 74 | $propertyData = [ |
||
| 75 | $did => [ |
||
| 76 | 'type' => $type, |
||
| 77 | 'data' => $data, |
||
| 78 | ], |
||
| 79 | ]; |
||
| 80 | |||
| 81 | return $this->getPropertiesGraceful($propertyData); |
||
| 82 | } |
||
| 83 | |||
| 84 | /** |
||
| 85 | * 按照名称获取多个设备属性. |
||
| 86 | * |
||
| 87 | * @param $data |
||
| 88 | * $data = ['AABBCD-did' => |
||
| 89 | * ['type' => 'urn:miot-spec-v2:device:light:0000A001:yeelink-color1:1', data => ['brightness', 'on']] |
||
| 90 | * ] |
||
| 91 | * |
||
| 92 | * @throws ApiErrorException |
||
| 93 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 94 | * |
||
| 95 | * @return array|bool|mixed |
||
| 96 | */ |
||
| 97 | public function getPropertiesGraceful($data) |
||
| 98 | { |
||
| 99 | if (!empty($data)) { |
||
| 100 | $properties = []; |
||
| 101 | $attributes = []; |
||
| 102 | $instances = []; |
||
| 103 | foreach ($data as $did => $datum) { |
||
| 104 | if (isset($datum['type'])) { |
||
| 105 | $instance = new Instance($datum['type']); |
||
| 106 | $propertiesNodes = $instance->getPropertiesNodes(); |
||
| 107 | $instances[$did] = $propertiesNodes; |
||
| 108 | |||
| 109 | if (!empty($datum['data'])) { |
||
| 110 | foreach ($datum['data'] as $name) { |
||
| 111 | list($sids, $pids) = $instance->getSidPidByName($name); |
||
| 112 | |||
| 113 | if (!$sids || !$pids) { |
||
| 114 | throw new ApiErrorException('Invalid property! did:'.$did.',name: '.$name); |
||
| 115 | } |
||
| 116 | |||
| 117 | foreach ($sids as $sindex => $sid) { |
||
| 118 | $property = $propertiesNodes[($sid.'.'.$pids[$sindex])]; |
||
| 119 | |||
| 120 | if (!$property->canRead()) { |
||
| 121 | throw new ApiErrorException( |
||
| 122 | 'The property does\'t has the read access! did:'.$did.',name: '.$name |
||
| 123 | ); |
||
| 124 | } |
||
| 125 | |||
| 126 | $properties[] = $did.'.'.$sid.'.'.$pids[$sindex]; |
||
| 127 | } |
||
| 128 | } |
||
| 129 | } else { |
||
| 130 | foreach ($propertiesNodes as $property) { |
||
| 131 | $name = $property->getUrn()->getName(); |
||
| 132 | list($sids, $pids) = $instance->getSidPidByName($name); |
||
| 133 | |||
| 134 | if (!$sids || !$pids) { |
||
| 135 | throw new ApiErrorException('Invalid property! did:'.$did.',name: '.$name); |
||
| 136 | } |
||
| 137 | |||
| 138 | foreach ($sids as $sindex => $sid) { |
||
| 139 | $property = $propertiesNodes[($sid.'.'.$pids[$sindex])]; |
||
| 140 | |||
| 141 | if ($property->canRead()) { |
||
| 142 | $properties[] = $did.'.'.$sid.'.'.$pids[$sindex]; |
||
| 143 | } |
||
| 144 | } |
||
| 145 | } |
||
| 146 | } |
||
| 147 | } else { |
||
| 148 | throw new ApiErrorException('Properties data and device type required'); |
||
| 149 | } |
||
| 150 | } |
||
| 151 | |||
| 152 | $response = $this->properties(array_unique($properties)); |
||
| 153 | if (isset($response['properties']) && !empty($response['properties'])) { |
||
| 154 | foreach ($response['properties'] as $res) { |
||
| 155 | $pidArr = explode('.', $res['pid']); |
||
| 156 | if (isset($res['value']) // 是否获取到了值 |
||
| 157 | && isset($res['status']) // 是否有返回状态 |
||
| 158 | && $res['status'] == 0 // 是否正常返回 |
||
| 159 | && isset($pidArr[0]) // did |
||
| 160 | && isset($pidArr[1]) // sid |
||
| 161 | && isset($pidArr[2]) // pid |
||
| 162 | && isset($instances[$pidArr[0]][($pidArr[1].'.'.$pidArr[2])])) { |
||
| 163 | $attributeName = $instances[$pidArr[0]][($pidArr[1].'.'.$pidArr[2])]->getUrn()->getName(); |
||
| 164 | |||
| 165 | if (isset($attributes[$pidArr[0]][$attributeName])) { |
||
| 166 | if (is_array($attributes[$pidArr[0]][$attributeName])) { |
||
| 167 | $attributes[$pidArr[0]][$attributeName][] = $res['value']; |
||
| 168 | } else { |
||
| 169 | $attributes[$pidArr[0]][$attributeName] = [ |
||
| 170 | $attributes[$pidArr[0]][$attributeName], |
||
| 171 | $res['value'], |
||
| 172 | ]; |
||
| 173 | } |
||
| 174 | } else { |
||
| 175 | $attributes[$pidArr[0]][$attributeName] = $res['value']; |
||
| 176 | } |
||
| 177 | } |
||
| 178 | } |
||
| 179 | } |
||
| 180 | |||
| 181 | return $attributes; |
||
| 182 | } else { |
||
| 183 | throw new ApiErrorException('devices data required'); |
||
| 184 | } |
||
| 185 | } |
||
| 186 | |||
| 187 | /** |
||
| 188 | * 按照名称设置属性. |
||
| 189 | * |
||
| 190 | * @param $did |
||
| 191 | * @param $type |
||
| 192 | * @param $data | $data = ['brightness' => 75, 'on' => true] |
||
|
0 ignored issues
–
show
|
|||
| 193 | * |
||
| 194 | * @throws ApiErrorException |
||
| 195 | * @throws \MiotApi\Exception\JsonException |
||
| 196 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 197 | * |
||
| 198 | * @return array|bool|mixed |
||
| 199 | */ |
||
| 200 | public function setPropertyGraceful($did, $type, $data) |
||
| 201 | { |
||
| 202 | if (!empty($data)) { |
||
| 203 | $propertyData = [ |
||
| 204 | $did => [ |
||
| 205 | 'type' => $type, |
||
| 206 | 'data' => $data, |
||
| 207 | ], |
||
| 208 | ]; |
||
| 209 | |||
| 210 | return $this->setPropertiesGraceful($propertyData); |
||
| 211 | } else { |
||
| 212 | throw new ApiErrorException('Properties data required'); |
||
| 213 | } |
||
| 214 | } |
||
| 215 | |||
| 216 | /** |
||
| 217 | * 按照名称设置多个设备属性. |
||
| 218 | * |
||
| 219 | * @param $data |
||
| 220 | * $data = ['AABBCD-did' => |
||
| 221 | * ['type' => 'urn:miot-spec-v2:device:light:0000A001:yeelink-color1:1', data => ['brightness' => 75, 'on' => true]] |
||
| 222 | * ] |
||
| 223 | * |
||
| 224 | * @throws ApiErrorException |
||
| 225 | * @throws \MiotApi\Exception\JsonException |
||
| 226 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 227 | * |
||
| 228 | * @return array|bool|mixed |
||
| 229 | */ |
||
| 230 | public function setPropertiesGraceful($data) |
||
| 231 | { |
||
| 232 | if (!empty($data)) { |
||
| 233 | $properties = []; |
||
| 234 | foreach ($data as $did => $datum) { |
||
| 235 | if (!empty($datum['data']) && isset($datum['type'])) { |
||
| 236 | $instance = new Instance($datum['type']); |
||
| 237 | $propertiesNodes = $instance->getPropertiesNodes(); |
||
| 238 | |||
| 239 | foreach ($datum['data'] as $name => $value) { |
||
| 240 | list($sids, $pids) = $instance->getSidPidByName($name); |
||
| 241 | |||
| 242 | if (!$sids || !$pids) { |
||
| 243 | throw new ApiErrorException('Invalid property! did:'.$did.',name: '.$name); |
||
| 244 | } |
||
| 245 | |||
| 246 | foreach ($sids as $sindex => $sid) { |
||
| 247 | $property = $propertiesNodes[($sid.'.'.$pids[$sindex])]; |
||
| 248 | |||
| 249 | if (!is_array($value)) { |
||
| 250 | $tmpValue = $value; |
||
| 251 | } else { |
||
| 252 | if (!isset($value[$sindex])) { |
||
| 253 | continue; |
||
| 254 | } |
||
| 255 | $tmpValue = $value[$sindex]; |
||
| 256 | } |
||
| 257 | |||
| 258 | if (!$property->verify($tmpValue)) { |
||
| 259 | throw new ApiErrorException('Invalid property value! did:'.$did.',name: '.$name); |
||
| 260 | } |
||
| 261 | |||
| 262 | if (!$property->canWrite()) { |
||
| 263 | throw new ApiErrorException( |
||
| 264 | 'The property does\'t has the write access! did:'.$did.',name: '.$name |
||
| 265 | ); |
||
| 266 | } |
||
| 267 | |||
| 268 | $properties[] = [ |
||
| 269 | 'pid' => $did.'.'.$sid.'.'.$pids[$sindex], |
||
| 270 | 'value' => $tmpValue, |
||
| 271 | ]; |
||
| 272 | } |
||
| 273 | } |
||
| 274 | } else { |
||
| 275 | throw new ApiErrorException('Properties data and device type required'); |
||
| 276 | } |
||
| 277 | } |
||
| 278 | |||
| 279 | return $this->setProperties([ |
||
| 280 | 'properties' => $properties, |
||
| 281 | ]); |
||
| 282 | } else { |
||
| 283 | throw new ApiErrorException('devices data required'); |
||
| 284 | } |
||
| 285 | } |
||
| 286 | |||
| 287 | /** |
||
| 288 | * 根据 devicesList 方法获取到的设备列表信息 订阅设备属性变化. |
||
| 289 | * |
||
| 290 | * @param $devices |
||
| 291 | * @param $customData |
||
| 292 | * @param $receiverUrl |
||
| 293 | * |
||
| 294 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 295 | * |
||
| 296 | * @return array|bool|mixed |
||
| 297 | */ |
||
| 298 | public function subscriptByDevices($devices, $customData, $receiverUrl) |
||
| 299 | { |
||
| 300 | $subscriptProperties = $this->getPropertiesByDevices($devices, ['notify']); |
||
| 301 | |||
| 302 | return $this->subscript($subscriptProperties, $customData, $receiverUrl); |
||
| 303 | } |
||
| 304 | |||
| 305 | /** |
||
| 306 | * 根据 devicesList 方法获取到的设备列表信息 退订设备属性变化. |
||
| 307 | * |
||
| 308 | * @param $devices |
||
| 309 | * |
||
| 310 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 311 | * |
||
| 312 | * @return array|bool|mixed |
||
| 313 | */ |
||
| 314 | public function unSubscriptByDevices($devices) |
||
| 315 | { |
||
| 316 | $subscriptProperties = $this->getPropertiesByDevices($devices, ['notify']); |
||
| 317 | |||
| 318 | return $this->unSubscript($subscriptProperties); |
||
| 319 | } |
||
| 320 | |||
| 321 | /** |
||
| 322 | * 根据设备列表和 access列表 获取对于访问方式的属性. |
||
| 323 | * |
||
| 324 | * @param $devices |
||
| 325 | * @param array $access | ['read'] ['read', 'notify'] ['read', 'write', 'notify'] |
||
| 326 | * |
||
| 327 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 328 | * |
||
| 329 | * @return array|bool |
||
| 330 | */ |
||
| 331 | protected function getPropertiesByDevices($devices, $access = []) |
||
| 332 | { |
||
| 333 | try { |
||
| 334 | $properties = []; |
||
| 335 | if (!empty($devices) && !isset($devices['status'])) { |
||
| 336 | foreach ($devices as $device) { |
||
| 337 | $instance = new Instance($device['type']); |
||
| 338 | $propertiesNodes = $instance->getPropertiesNodes(); |
||
| 339 | if (!empty($propertiesNodes)) { |
||
| 340 | foreach ($propertiesNodes as $index => $property) { |
||
| 341 | if (in_array('read', $access)) { |
||
| 342 | if ($property->canRead()) { |
||
| 343 | $properties[] = $device['did'].'.'.$index; |
||
| 344 | } |
||
| 345 | } |
||
| 346 | if (in_array('write', $access)) { |
||
| 347 | if ($property->canWrite()) { |
||
| 348 | $properties[] = $device['did'].'.'.$index; |
||
| 349 | } |
||
| 350 | } |
||
| 351 | if (in_array('notify', $access)) { |
||
| 352 | if ($property->canNotify()) { |
||
| 353 | $properties[] = $device['did'].'.'.$index; |
||
| 354 | } |
||
| 355 | } |
||
| 356 | } |
||
| 357 | } |
||
| 358 | } |
||
| 359 | } else { |
||
| 360 | throw new ApiErrorException('invalid devices lists'); |
||
| 361 | } |
||
| 362 | |||
| 363 | return $properties; |
||
| 364 | } catch (ApiErrorException $exception) { |
||
| 365 | throw new ApiErrorException('Could not get properties by devices:'.$exception->getMessage()); |
||
| 366 | |||
| 367 | return false; |
||
|
0 ignored issues
–
show
return false is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last Loading history...
|
|||
| 368 | } |
||
| 369 | } |
||
| 370 | } |
||
| 371 |