5
5
use MiIO \Models \Device ;
6
6
use MiIO \Models \Packet ;
7
7
use MiIO \Models \Request ;
8
+ use MiIO \Models \Response ;
9
+ use React \Promise \Promise ;
10
+ use Socket \Raw \Factory ;
8
11
9
12
/**
10
13
* Class MiIO
@@ -15,19 +18,37 @@ class MiIO
15
18
{
16
19
const CACHE_KEY = 'MiIO ' ;
17
20
18
- const PORT = 54321 ;
21
+ const INFO = ' miIO.info ' ;
19
22
20
- const TIMEOUT = 5 ;
23
+ /**
24
+ * @var Factory
25
+ */
26
+ protected $ socketFactory ;
21
27
22
- const INFO = 'miIO.info ' ;
28
+ public function __construct (Factory $ socketFactory )
29
+ {
30
+ $ this ->socketFactory = $ socketFactory ;
31
+ }
32
+
33
+ /**
34
+ * @param string $deviceName
35
+ * @param string $token
36
+ * @return Device
37
+ */
38
+ public function createDevice (string $ deviceName , string $ token )
39
+ {
40
+ return new Device ($ this ->socketFactory ->createUdp4 (), $ deviceName , $ token );
41
+ }
23
42
24
43
/**
25
44
* @param Device $device
26
- * @return array
45
+ * @return Promise
27
46
*/
28
47
public function getInfo (Device $ device )
29
48
{
30
- return $ this ->send ($ device , static ::INFO );
49
+ $ this ->send ($ device , static ::INFO );
50
+
51
+ return $ this ->read ($ device );
31
52
}
32
53
33
54
/**
@@ -36,77 +57,51 @@ public function getInfo(Device $device)
36
57
*/
37
58
private function init (Device &$ device )
38
59
{
39
- if (strlen ($ device ->getIpAddress ())) {
40
- $ packet = new Packet ();
41
- $ helo = $ packet ->getHelo ();
42
-
43
- $ start = time ();
44
- $ socket = socket_create (AF_INET , SOCK_DGRAM , SOL_UDP );
45
-
46
- while (time () < ($ start + 10 )) {
47
- $ response = $ this ->getSocketResponse ($ device ->getIpAddress (), $ socket , $ helo );
48
-
49
- if (!empty ($ response )) {
50
- $ response = bin2hex ($ response );
51
- }
52
-
53
- if (!empty ($ response )) {
54
- $ packet = new Packet ($ response );
55
- if ($ packet ->getDeviceType ()
56
- && $ packet ->getSerial ()) {
57
- $ device ->setDeviceType ($ packet ->getDeviceType ());
58
- $ device ->setSerial ($ packet ->getSerial ());
59
- $ device ->setTimeDelta (hexdec ($ packet ->getTimestamp ()) - time ());
60
- socket_close ($ socket );
61
-
62
- return $ device ;
63
- }
64
- }
65
- }
66
- if ($ socket ) {
67
- socket_close ($ socket );
60
+ $ packet = new Packet ();
61
+ $ helo = $ packet ->getHelo ();
62
+
63
+ $ device ->send ($ helo );
64
+ $ response = $ device ->read ();
65
+
66
+ if (!empty ($ response )) {
67
+ $ response = bin2hex ($ response );
68
+ }
69
+
70
+ if (!empty ($ response )) {
71
+
72
+ $ packet = new Packet ($ response );
73
+
74
+ if ($ packet ->getDeviceType ()
75
+ && $ packet ->getSerial ()) {
76
+
77
+ $ device ->setDeviceType ($ packet ->getDeviceType ());
78
+ $ device ->setSerial ($ packet ->getSerial ());
79
+ $ device ->setTimeDelta (hexdec ($ packet ->getTimestamp ()) - time ());
68
80
}
69
81
}
70
82
71
- return null ;
83
+ return $ device ;
72
84
}
73
85
74
86
/**
75
87
* @param Device $device
76
88
* @param string $command
77
89
* @param array $params
78
- * @return array
79
90
*/
80
91
public function send (Device $ device , $ command , $ params = [])
81
92
{
82
93
if (!$ device ->isInitialized ()) {
83
94
$ this ->init ($ device );
84
95
}
85
96
86
- if (!$ device ->isInitialized ()) {
87
- return [];
88
- }
97
+ $ cacheKey = static ::CACHE_KEY . $ device ->getIpAddress ();
98
+ $ requestId = \Cache::increment ($ cacheKey );
89
99
90
100
$ request = new Request ();
91
101
$ request
92
102
->setMethod ($ command )
93
- ->setParams ($ params );
94
-
95
- return $ this ->getResponse ($ device , $ request );
96
- }
97
-
98
- /**
99
- * @param Device $device
100
- * @param Request $request
101
- * @return array
102
- */
103
- public function getResponse (Device $ device , Request $ request )
104
- {
105
- $ cacheKey = static ::CACHE_KEY . $ device ->getIpAddress ();
106
- $ requestId = (int )\Cache::get ($ cacheKey );
107
- \Cache::forever ($ cacheKey , $ requestId + 1 );
108
-
109
- $ request ->setId ($ requestId );
103
+ ->setParams ($ params )
104
+ ->setId ($ requestId );
110
105
111
106
$ data = $ device ->encrypt ($ request );
112
107
@@ -115,73 +110,35 @@ public function getResponse(Device $device, Request $request)
115
110
->setData ($ data )
116
111
->setDevice ($ device );
117
112
118
- $ start = time ();
119
- $ socket = socket_create (AF_INET , SOCK_DGRAM , SOL_UDP );
120
-
121
- while (time () < ($ start + 10 )) {
122
- $ packet ->setTimestamp ($ device ->getTimeDelta () + time ());
123
- $ response = $ this ->getSocketResponse ($ device ->getIpAddress (), $ socket , (string )$ packet );
124
-
125
- if (!empty ($ response )) {
126
- $ response = bin2hex ($ response );
127
- }
128
-
129
- $ result = $ this ->decrypt ($ device , $ response );
130
-
131
- if (strlen ($ result )) {
132
- $ response = json_decode (preg_replace ('/[\x00-\x1F\x7F]/ ' , '' , $ result ), true );
133
-
134
- if (!empty ($ response ['id ' ]) && $ response ['id ' ] === $ requestId ) {
135
- socket_close ($ socket );
136
-
137
- return $ response ;
138
- }
139
- }
140
- }
141
-
142
- return [];
113
+ $ device ->send ((string )$ packet );
143
114
}
144
115
145
116
/**
146
- * @param string $ip
147
- * @param \Resource $socket
148
- * @param string $data
149
- * @return string|null
117
+ * @param Device $device
118
+ * @return Promise
150
119
*/
151
- private function getSocketResponse ( $ ip , $ socket , $ data )
120
+ public function read ( Device $ device )
152
121
{
153
- if (ctype_xdigit ($ data )) {
154
- $ data = hex2bin ($ data );
155
- }
156
-
157
- $ buf = null ;
122
+ return new Promise (function (callable $ resolve , callable $ reject ) use ($ device ) {
123
+ $ buf = $ device ->read ();
158
124
159
- try {
160
- socket_set_option ( $ socket , SOL_SOCKET , SO_BROADCAST , 1 );
161
- socket_set_option ( $ socket , SOL_SOCKET , SO_RCVTIMEO , [ ' sec ' => 5 , ' usec ' => 0 ]);
125
+ if (! empty ( $ buf )) {
126
+ $ buf = bin2hex ( $ buf );
127
+ }
162
128
163
- socket_sendto ($ socket , $ data , strlen ($ data ), 0 , $ ip , static ::PORT );
129
+ $ packet = new Packet ($ buf );
130
+ $ result = $ device ->decrypt ($ packet ->getData ());
164
131
165
- socket_recvfrom ( $ socket , $ buf , 1024 , 0 , $ name , $ port );
166
- } catch ( \ Throwable $ e ) {
167
- }
132
+ $ response = new Response (
133
+ json_decode ( preg_replace ( ' /[\x00-\x1F\x7F]/ ' , '' , $ result ), true )
134
+ );
168
135
169
- return $ buf ;
170
- }
136
+ if ( $ response -> isSuccess ()) {
137
+ $ resolve ( $ response );
171
138
172
- /**
173
- * @param Device $device
174
- * @param string $response
175
- * @return string
176
- */
177
- private function decrypt (Device $ device , $ response )
178
- {
179
- if (!empty ($ response )) {
180
- $ packet = new Packet ($ response );
181
-
182
- return $ device ->decrypt ($ packet ->getData ());
183
- }
184
-
185
- return '' ;
139
+ return ;
140
+ }
141
+ $ reject ($ response ->getException ());
142
+ });
186
143
}
187
144
}
0 commit comments