Passed
Push — master ( 82e9fe...cecb4c )
by Sheldon
04:44
created

BaseApi::put()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 5
nop 2
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
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\Exception\JsonException;
12
use MiotApi\Util\Jsoner\JsonLastError;
13
use MiotApi\Util\Request;
14
15
class BaseApi
16
{
17
    /**
18
     * App-Id
19
     * 在开放平台申请: https://open.home.mi.com.
20
     *
21
     * @var
22
     */
23
    private $appId;
24
25
    /**
26
     * Access-Token
27
     * 小米账号登录后的Oauth Token
28
     * 需要使用者自己实现小米oauth并获取到用户的access token
29
     * oauth使用的应用id一定要与 App-Id一致.
30
     *
31
     * @var
32
     */
33
    private $accessToken;
34
35
    /**
36
     * 名字空间
37
     * 必须是 miot-spec-v2.
38
     *
39
     * @var string
40
     */
41
    private $specNS = 'miot-spec-v2';
42
43
    private $httpClient;
44
45
    private $host = 'api.home.mi.com';
46
47
    private $port = 443;
48
49
    private $timeout = 10;
50
51
    /**
52
     * Api constructor.
53
     *
54
     * @param null   $appId
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $appId is correct as it would always require null to be passed?
Loading history...
55
     * @param null   $accessToken
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $accessToken is correct as it would always require null to be passed?
Loading history...
56
     * @param string $specNS
57
     */
58
    public function __construct($appId = null, $accessToken = null, $specNS = 'miot-spec-v2')
59
    {
60
        $this->appId = $appId;
61
        $this->accessToken = $accessToken;
62
        $this->specNS = $specNS;
63
    }
64
65
    /**
66
     * 设置 请求的 host
67
     * 默认为大陆host,如果要获取其他地区设备的时候,可以使用此方法设置host.
68
     *
69
     * @param $host
70
     */
71
    public function setHost($host)
72
    {
73
        $this->host = $host;
74
    }
75
76
    /**
77
     * 读取抽象设备列表.
78
     *
79
     * @param bool $compact 如果希望读取设备列表时,只想读取最简单的信息,compact设置为true
80
     *
81
     * @return array|mixed
82
     */
83
    public function devices($compact = false)
84
    {
85
        $params = [];
86
        if ($compact) {
87
            $params = [
88
                'compact' => $compact,
89
            ];
90
        }
91
92
        return $this->get('/api/v1/devices', $params);
93
    }
94
95
    /**
96
     * GET.
97
     *
98
     * @param $uri
99
     * @param array $params
100
     *
101
     * @return array|bool|mixed
102
     */
103
    public function get($uri, $params = [])
104
    {
105
        $httpClient = $this->httpClient();
106
107
        $result = $httpClient
108
            ->setRequestURI($uri)
109
            ->setType('GET')
110
            ->setQueryParams($params)
111
            ->execute()
112
            ->getResponseText();
113
114
        if ($result) {
115
            $returnData = json_decode($result, true);
116
            $lastError = JsonLastError::check();
117
118
            return $returnData === null || !is_null($lastError) ? false : $returnData;
119
        } else {
120
            return [
121
                'status'  => '-705002036',
122
                'message' => $httpClient->getError(),
123
            ];
124
        }
125
    }
126
127
    /**
128
     * 获取http Client.
129
     *
130
     * @return Request
131
     */
132
    private function httpClient()
133
    {
134
        $this->httpClient = new Request($this->host, '', $this->port, true, $this->timeout);
135
        $this->httpClient->setHeader('App-Id', $this->appId);
136
        $this->httpClient->setHeader('Access-Token', $this->accessToken);
137
        $this->httpClient->setHeader('Spec-NS', $this->specNS);
138
139
        return $this->httpClient;
140
    }
141
142
    /**
143
     * 读取设备信息
144
     * 读取一个设备 : GET /api/v1/device-information?dids=xxxx
145
     * 读取多个设备: GET /api/v1/device-information?dids=xxxx,yyy,zzzzz.
146
     *
147
     * @param $dids
148
     *
149
     * @return array|mixed
150
     */
151
    public function deviceInformation($dids)
152
    {
153
        if (is_array($dids)) {
154
            $dids = implode(',', $dids);
155
        }
156
157
        $params = [
158
            'dids' => $dids,
159
        ];
160
161
        return $this->get('/api/v1/device-information', $params);
162
    }
163
164
    /**
165
     * 读取属性
166
     * 读取一个属性 : GET /api/v1/properties?pid=AAAD.1.1
167
     * 读取多个属性:GET /api/v1/properties?pid=AAAD.1.1,AAAD.2.3
168
     * 语音控制需要增加voice字段:GET /api/v1/properties?pid=AAAD.1.1,AAAD.2.3&voice={"recognition":"灯开了吗","semantics":"xxx"}.
169
     *
170
     * @param $pid
171
     *
172
     * @param string $voice
173
     * @return array|mixed
174
     */
175
    public function properties($pid, $voice = '')
176
    {
177
        if (is_array($pid)) {
178
            $pid = implode(',', $pid);
179
        }
180
181
        $params = [
182
            'pid' => $pid,
183
        ];
184
185
        if ($voice) {
186
            $params['voice'] = $voice;
187
        }
188
189
        return $this->get('/api/v1/properties', $params);
190
    }
191
192
    /**
193
     * 设置属性.
194
     *
195
     * @param $data
196
     *
197
     * @throws JsonException
198
     *
199
     * @return array|bool|mixed
200
     */
201
    public function setProperties($data)
202
    {
203
        if (!is_array($data)) {
204
            $data = json_decode($data, true);
205
            $lastError = JsonLastError::check();
206
            if (!is_null($lastError)) {
207
                throw new JsonException('It\'s not a json string.');
208
            }
209
        }
210
211
        $data = json_encode($data);
212
213
        return $this->put('/api/v1/properties', $data);
214
    }
215
216
    /**
217
     * PUT.
218
     *
219
     * @param $uri
220
     * @param $data
221
     *
222
     * @return array|bool|mixed
223
     */
224
    public function put($uri, $data)
225
    {
226
        $httpClient = $this->httpClient();
227
        $httpClient->setAdditionalCurlOpt(CURLOPT_POSTFIELDS, $data);
228
229
        $result = $httpClient
230
            ->setRequestURI($uri)
231
            ->setType('PUT')
232
            ->execute()
233
            ->getResponseText();
234
235
        if ($result) {
236
            $returnData = json_decode($result, true);
237
            $lastError = JsonLastError::check();
238
239
            return $returnData === null || !is_null($lastError) ? false : $returnData;
240
        } else {
241
            return [
242
                'status'  => '-705002036',
243
                'message' => $httpClient->getError(),
244
            ];
245
        }
246
    }
247
248
    /**
249
     * 调用方法
250
     * 一次请求只能调用一个设备的一个方法
251
     * PUT /api/v1/action.
252
     *
253
     * @param $data
254
     *
255
     * @throws JsonException
256
     *
257
     * @return array|bool|mixed
258
     */
259
    public function invokeActions($data)
260
    {
261
        if (!is_array($data)) {
262
            $data = json_decode($data, true);
263
            $lastError = JsonLastError::check();
264
            if (!is_null($lastError)) {
265
                throw new JsonException('It\'s not a json string.');
266
            }
267
        }
268
269
        $data = json_encode($data);
270
271
        return $this->put('/api/v1/action', $data);
272
    }
273
274
    /**
275
     * 读取用户在米家设置好的场景列表.
276
     *
277
     * @return array|mixed
278
     */
279
    public function scenes()
280
    {
281
        return $this->get('/api/v1/scenes');
282
    }
283
284
    /**
285
     * 主动触发某个场景.
286
     *
287
     * @param $sceneId
288
     *
289
     * @return array|bool|mixed
290
     */
291
    public function triggerScene($sceneId)
292
    {
293
        $data = [
294
            'id' => $sceneId,
295
        ];
296
        $data = json_encode($data);
297
298
        return $this->post('/api/v1/scene', $data);
299
    }
300
301
    /**
302
     * POST.
303
     *
304
     * @param $uri
305
     * @param $data
306
     *
307
     * @return array|bool|mixed
308
     */
309
    public function post($uri, $data)
310
    {
311
        $httpClient = $this->httpClient();
312
        $httpClient->setAdditionalCurlOpt(CURLOPT_POSTFIELDS, $data);
313
314
        $result = $httpClient
315
            ->setRequestURI($uri)
316
            ->setType('POST')
317
            ->execute()
318
            ->getResponseText();
319
320
        if ($result) {
321
            $returnData = json_decode($result, true);
322
            $lastError = JsonLastError::check();
323
324
            return $returnData === null || !is_null($lastError) ? false : $returnData;
325
        } else {
326
            return [
327
                'status'  => '-705002036',
328
                'message' => $httpClient->getError(),
329
            ];
330
        }
331
    }
332
333
    /**
334
     * 读取家庭列表.
335
     *
336
     * @return array|mixed
337
     */
338
    public function homes()
339
    {
340
        return $this->get('/api/v1/homes');
341
    }
342
343
    /**
344
     * 订阅属性变化
345
     * 开始订阅:
346
     * POST /api/v1/subscriptions
347
     * Content-Type: application/json
348
     * Content-Length: 134
349
     * ​ * {
350
     * "topic": "properties-changed",
351
     * "properties": [
352
     * "AAAB.1.1",
353
     * "AAAC.1.1",
354
     * "AAAD.1.1",
355
     * "AAAD.1.2"
356
     * ],
357
     * "receiver-url": "xxx"
358
     * }.
359
     *
360
     * 订阅成功,应答如下:
361
     * HTTP/1.1 207 Multi-Status
362
     * Content-Type: application/json
363
     * Content-Length: 156
364
     * {
365
     * "expired": 36000,    // 超时时间,单位为秒。
366
     * "properties": [
367
     * {
368
     * "pid": "AAAB.1.1",
369
     * "status": 0
370
     * },
371
     * {
372
     * "pid": "AAAC.1.1",
373
     * "status": -704002023
374
     * },
375
     * {
376
     * "pid": "AAAD.1.1",
377
     * "status": 0
378
     * }
379
     * {
380
     * "pid": "AAAD.1.2",
381
     * "status": 705202023
382
     * }
383
     * ]
384
     * }
385
     *
386
     * @param $properties
387
     * @param $receiverUrl
388
     *
389
     * @return array|bool|mixed
390
     */
391
    public function subscript($properties, $receiverUrl)
392
    {
393
        $data = [
394
            'topic'        => 'properties-changed',
395
            'properties'   => $properties,
396
            'receiver-url' => $receiverUrl,
397
        ];
398
        $data = json_encode($data);
399
400
        return $this->post('/api/v1/subscriptions', $data);
401
    }
402
403
    /**
404
     * 退订属性变化
405
     * POST /api/v1/subscriptions
406
     * Content-Type: application/json
407
     * Content-Length: 134
408
     * ​ * {
409
     * "topic": "properties-changed",
410
     * "properties": [
411
     * "AAAB.1.1",
412
     * "AAAC.1.1",
413
     * "AAAD.1.1",
414
     * "AAAD.1.2"
415
     * ],
416
     * "receiver-url": "xxx"
417
     * }.
418
     *
419
     * 退订成功,应答如下:
420
     * HTTP/1.1 207 Multi-Status
421
     * Content-Type: application/json
422
     * Content-Length: 156
423
     * {
424
     * "expired": 36000,    // 超时时间,单位为秒。
425
     * "properties": [
426
     * {
427
     * "pid": "AAAB.1.1",
428
     * "status": 0
429
     * },
430
     * {
431
     * "pid": "AAAC.1.1",
432
     * "status": -704002023
433
     * },
434
     * {
435
     * "pid": "AAAD.1.1",
436
     * "status": 0
437
     * }
438
     * {
439
     * "pid": "AAAD.1.2",
440
     * "status": 705202023
441
     * }
442
     * ]
443
     * }
444
     *
445
     * @param $properties
446
     *
447
     * @return array|bool|mixed
448
     */
449
    public function unSubscript($properties)
450
    {
451
        $data = [
452
            'topic'      => 'properties-changed',
453
            'properties' => $properties,
454
        ];
455
        $data = json_encode($data);
456
457
        return $this->delete('/api/v1/subscriptions', $data);
458
    }
459
460
    /**
461
     * DELETE.
462
     *
463
     * @param $uri
464
     * @param $data
465
     *
466
     * @return array|bool|mixed
467
     */
468
    public function delete($uri, $data)
469
    {
470
        $httpClient = $this->httpClient();
471
        $httpClient->setAdditionalCurlOpt(CURLOPT_POSTFIELDS, $data);
472
473
        $result = $httpClient
474
            ->setRequestURI($uri)
475
            ->setType('DELETE')
476
            ->execute()
477
            ->getResponseText();
478
479
        if ($result) {
480
            $returnData = json_decode($result, true);
481
            $lastError = JsonLastError::check();
482
483
            return $returnData === null || !is_null($lastError) ? false : $returnData;
484
        } else {
485
            return [
486
                'status'  => '-705002036',
487
                'message' => $httpClient->getError(),
488
            ];
489
        }
490
    }
491
}
492