/library/Octopus/X10/Event/Publisher/Service.php

https://github.com/rukavina/Octopus · PHP · 231 lines · 127 code · 25 blank · 79 comment · 17 complexity · eaaee24e8e16e1c73449959e0d136dbb MD5 · raw file

  1. <?php
  2. /**
  3. * X10 Event Publisher Service
  4. * reading from Mochad writting to RabbitMQ
  5. *
  6. * @author milan
  7. * @package X10
  8. * @subpackage Event
  9. */
  10. class Octopus_X10_Event_Publisher_Service {
  11. /**
  12. *
  13. * @var Octopus_X10_Event_Publisher_Service
  14. */
  15. protected static $_instance = null;
  16. /**
  17. *
  18. * @var array
  19. */
  20. protected $config = array();
  21. /**
  22. * All device Statuses
  23. * @var array
  24. */
  25. protected $status = array();
  26. /**
  27. * house => device
  28. *
  29. * @var array
  30. */
  31. protected $selectedDevices = array();
  32. /**
  33. *
  34. * @var resource
  35. */
  36. protected $socket = null;
  37. /**
  38. *
  39. * @var AMQPChannel
  40. */
  41. protected $amqChannel = null;
  42. /**
  43. *
  44. * @var $amqConn
  45. */
  46. protected $amqConn = null;
  47. /**
  48. *
  49. * @var Octopus_X10_Command
  50. */
  51. protected $commander = null;
  52. /**
  53. *
  54. * @var boolean
  55. */
  56. protected $stop = false;
  57. /**
  58. * constructor
  59. *
  60. * @param array $config
  61. */
  62. private function __construct($config) {
  63. require_once('amqplib/amqp.inc');
  64. $this->config = $config;
  65. $this->commander = Octopus_X10_Command::getInstance($config);
  66. }
  67. /**
  68. * returns singleton instance of Octopus_X10_Event_Publisher_Service
  69. *
  70. * @param array $config
  71. * @return Octopus_X10_Event_Publisher_Service
  72. */
  73. public static function getInstance($config = null)
  74. {
  75. if(self::$_instance === null)
  76. {
  77. self::$_instance = new self($config);
  78. }
  79. return self::$_instance;
  80. }
  81. /**
  82. * destructor
  83. */
  84. public function __destruct() {
  85. if($this->socket){
  86. echo "Closing socket...";
  87. socket_close($this->socket);
  88. echo "OK.\n\n";
  89. }
  90. if($this->amqChannel){
  91. echo "Closing AMQ Channel...";
  92. $this->amqChannel->close();
  93. echo "OK.\n\n";
  94. }
  95. if($this->amqConn){
  96. echo "Closing AMQ Connection...";
  97. $this->amqConn->close();
  98. echo "OK.\n\n";
  99. }
  100. }
  101. public function stop(){
  102. $this->stop = true;
  103. }
  104. /**
  105. * start service
  106. */
  107. public function run() {
  108. echo "X10.Event.Publisher is starting...\n================\n";
  109. // Create Rabbit MQ channel
  110. $this->amqConn = new AMQPConnection($this->config['amqp']['host'], $this->config['amqp']['port'], $this->config['amqp']['user'], $this->config['amqp']['pass']);
  111. $this->amqChannel = $this->amqConn->channel();
  112. $this->amqChannel->access_request($this->config['amqp']['vhost'], false, false, true, true);
  113. /* Create a TCP/IP socket. */
  114. $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  115. if ($this->socket === false) {
  116. echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
  117. } else {
  118. echo "OK.\n";
  119. }
  120. //get status
  121. echo "Reading devices status ...\n\n";
  122. $this->status = $this->commander->getStatus();
  123. foreach($this->status['selected'] as $house => $device){
  124. $this->selectedDevices[$house] = $device;
  125. }
  126. echo "Attempting to connect to '" . $this->config['mochad']['host'] . "' on port '" . $this->config['mochad']['port'] . "'...\n";
  127. $result = socket_connect($this->socket, $this->config['mochad']['host'], $this->config['mochad']['port']);
  128. if ($result === false) {
  129. echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($this->socket)) . "\n";
  130. } else {
  131. echo "OK.\n";
  132. }
  133. echo "Reading socket:\n\n";
  134. while (!$this->stop && ($out = socket_read($this->socket, 2048))) {
  135. echo "\nSocket Text:\n$out\n=====================\n";
  136. $events = $this->parseEvents($out);
  137. foreach ($events as $event) {
  138. $this->processEvent($event);
  139. }
  140. }
  141. }
  142. /**
  143. * parse read string into events array
  144. *
  145. * @param string $text
  146. * @return array
  147. */
  148. protected function parseEvents($text){
  149. $text .= "\n";
  150. $events = array();
  151. $matches = array();
  152. $regex = "/([0-9]{2})\/([0-9]{2}) ([0-9]{2})\:([0-9]{2})\:([0-9]{2}) ([T,R]x) ([PL|RF]{2}) House(Unit)*: ([A-F]{1})([0-9]{0,2})( Func: (.*))*/";
  153. $matchResult = preg_match_all($regex, $text, $matches, PREG_SET_ORDER);
  154. echo "\nMatch result: $matchResult\n";
  155. if($matchResult > 0){
  156. foreach ($matches as $match) {
  157. $type = isset($match['12'])? $match['12']:"";
  158. $house = $match['9'];
  159. $device = $match['10'];
  160. $time = mktime($match['3'], $match['4'], $match['5'], $match['1'], $match['2'], date("Y"));
  161. if($type == ''){
  162. //address selector - not function
  163. $this->selectedDevices[$house] = $device;
  164. }
  165. else{
  166. $fParts = array();
  167. if(preg_match("/(.*)\(([0-9]+)\)/", $type, $fParts) > 0){
  168. $type = $fParts[1];
  169. $param = $fParts[2];
  170. }
  171. else{
  172. $param = null;
  173. }
  174. //function generate event
  175. $event = array(
  176. "type" => $type,
  177. "time" => $time,
  178. "direction" => $match['6'],
  179. "medium" => $match['7'],
  180. "house" => $house,
  181. "device" => ($device != "")?$device:$this->selectedDevices[$house]
  182. );
  183. if($param != null){
  184. $event['parameter'] = $param;
  185. }
  186. //attach status
  187. $event['status'] = $this->commander->getStatus();
  188. $this->status = $event['status'];
  189. echo "Found Event: \n==============\n";
  190. print_r($event); echo "\n\n";
  191. $events[] = $event;
  192. }
  193. }
  194. }
  195. return $events;
  196. }
  197. /**
  198. * Process event - send AMQ message
  199. *
  200. * @param array $event
  201. */
  202. protected function processEvent(&$event){
  203. $msg = new AMQPMessage(json_encode($event), array('content_type' => 'text/json'));
  204. $this->amqChannel->basic_publish($msg, $this->config['amqp']['exchange']);
  205. }
  206. }