44
55use Aqara \Models \Gateway ;
66use Aqara \Models \Response ;
7- use Clue \React \Multicast \Factory ;
87use Evenement \EventEmitter ;
8+ use React \Datagram \Socket ;
99use React \EventLoop \ExtEventLoop ;
1010use React \EventLoop \LibEventLoop ;
1111use React \EventLoop \LibEvLoop ;
1212use React \EventLoop \StreamSelectLoop ;
13+ use RuntimeException ;
1314
1415class Aqara extends EventEmitter
1516{
@@ -29,13 +30,16 @@ class Aqara extends EventEmitter
2930 */
3031 protected $ loop ;
3132
33+ /**
34+ * @var Socket
35+ */
3236 protected $ socket ;
3337
3438 public function __construct ()
3539 {
3640 $ this ->loop = \React \EventLoop \Factory::create ();
37- $ factory = new Factory ( $ this -> loop );
38- $ this ->socket = $ factory -> createReceiver (static :: MULTICAST_ADDRESS . ' : ' . static :: SERVER_PORT );
41+
42+ $ this ->createReceiver ();
3943
4044 $ this ->socket ->on ('message ' , function ($ data ) {
4145 $ this ->handleMessage ($ data );
@@ -44,6 +48,38 @@ public function __construct()
4448 $ this ->triggerWhois ();
4549 }
4650
51+ protected function createReceiver ()
52+ {
53+ $ stream = @stream_socket_server ('udp://0.0.0.0: ' . static ::SERVER_PORT , $ errno , $ errstr , STREAM_SERVER_BIND );
54+ if ($ stream === false ) {
55+ throw new RuntimeException ('Unable to create receiving socket: ' . $ errstr , $ errno );
56+ }
57+
58+ $ socket = socket_import_stream ($ stream );
59+ if ($ stream === false ) {
60+ throw new RuntimeException ('Unable to access underlying socket resource ' );
61+ }
62+
63+ // allow multiple processes to bind to the same address
64+ $ ret = socket_set_option ($ socket , SOL_SOCKET , SO_REUSEADDR , 1 );
65+ if ($ ret === false ) {
66+ throw new RuntimeException ('Unable to enable SO_REUSEADDR ' );
67+ }
68+
69+ // join multicast group and bind to port
70+ $ ret = socket_set_option (
71+ $ socket ,
72+ IPPROTO_IP ,
73+ MCAST_JOIN_GROUP ,
74+ ['group ' => static ::MULTICAST_ADDRESS , 'interface ' => 0 ]
75+ );
76+ if ($ ret === false ) {
77+ throw new RuntimeException ('Unable to join multicast group ' );
78+ }
79+
80+ $ this ->socket = new Socket ($ this ->loop , $ stream );
81+ }
82+
4783 protected function triggerWhois ()
4884 {
4985 $ message = '{"cmd": "whois"} ' ;
@@ -64,7 +100,7 @@ protected function handleMessage($message)
64100
65101 switch ($ response ->cmd ) {
66102 case 'heartbeat ' :
67- if (!isset ($ this ->gatewayList [$ response ->sid ])) {
103+ if ($ parsed [ ' model ' ] === ' gateway ' && !isset ($ this ->gatewayList [$ response ->sid ])) {
68104 $ handled = true ;
69105 $ this ->triggerWhois ();
70106 }
@@ -111,6 +147,7 @@ public function tick()
111147
112148 public function close ()
113149 {
150+ $ this ->loop ->stop ();
114151 $ this ->socket ->close ();
115152 }
116153}
0 commit comments