<?php

// Configuration
// SERVER root to Domoticz
$domoticz_server = 'http://localhost:8080';

// PLUGS
// mac (without special chars and lowercase) = IDX
// change next arrays and add / remove lines to add / remove plugs
$mienchufe['accf23514ddd'] = '106';	// Description
$mienchufe['accf23514eee'] = '107';	// Description


// Do NOT change these
$orvibo['ip'] = "0.0.0.0";
$orvibo['port'] = 10000;
$orvibo['NEED_DISCOVER'] = 1;


 function makePayload($data) {
  $res='';
  foreach($data as $v) {
   $res.=chr($v);
  }
  return $res;
 }
 
  function HexStringToArray($buf) {
   $res=array();
   for($i=0;$i<strlen($buf)-1;$i+=2) {
    $res[]=(hexdec($buf[$i].$buf[$i+1]));
   }
   return $res;   
  }

  function HexStringToString($buf) {
   $res='';
   for($i=0;$i<strlen($buf)-1;$i+=2) {
    $res.=chr(hexdec($buf[$i].$buf[$i+1]));
   }
   return $res;   
  }


  function binaryToString($buf) {
   $res='';
   for($i=0;$i<strlen($buf);$i++) {
    $num=dechex(ord($buf[$i]));
    if (strlen($num)==1) {
     $num='0'.$num;
    }
    $res.=$num;
   }
   return $res;
  }
  

//Create a UDP socket
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)))
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
     
    die("Couldn't create socket: [$errorcode] $errormsg \n");
}
 
echo "Socket created \n";
 
// Bind the source address
if( !socket_bind($sock, $orvibo['ip'] , $orvibo['port']) )
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
     
    die("Could not bind socket : [$errorcode] $errormsg \n");
}

echo "Socket bind (".$orvibo['ip'].":".$orvibo['port'].") OK \n";

socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1);

$discover=1;
 

$latest_config_read=time();
$tiempo_ejecucion=time();
$subscribed=array();
$ahora = time()+20;

//Do some communication, this loop can handle multiple clients
while(1)
{

//    setGlobal((str_replace('.php', '', basename(__FILE__))).'Run', time(), 1);

    if ((time()-$latest_config_read)>10) {
     $latest_config_read=time();

     if ($orvibo['NEED_DISCOVER']) {
      echo date('H:i:s')." Need discover flag set ... \n";
      $discover=1;
      $orvibo['NEED_DISCOVER']=0;
     }
    }

    if ((time()-$latest_discover)>5*60) {
     echo date('H:i:s')." Discover timeout, rediscovering ... \n";
     $discover=1;
    }

    if ($discover) {
     echo date('H:i:s')." Discovering ... \n";

	 $payload = makePayload(array(0x68, 0x64, 0x00, 0x06, 0x71, 0x61));
     echo date('H:i:s')." Sending multicast: ".binaryToString($payload)."\n";
     socket_sendto($sock, $payload, strlen($payload), 0, '255.255.255.255', $orvibo['port']);  
	 
     $latest_discover=time();
     $discover=0;
    }

    echo date('H:i:s')." Waiting for data ... \n";
     
    //Receive some data
    socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,array("sec"=>10,"usec"=>0));
    $buf='';
    @$r = socket_recvfrom($sock, $buf, 512, 0, $remote_ip, $remote_port);
    if ($remote_ip!=$orvibo['ip'] && $buf!='') {
     processMessage($buf, $remote_ip, $sock);
    }
	$ahora2 = time();
//   if (file_exists('./reboot') || IsSet($_GET['onetime']) || $ahora2 < $ahora)
   if (file_exists('./reboot') || IsSet($_GET['onetime']) || $contador > 12 )
   {
   	  print_r($enchufe);

// MENSAJE	  
//json.htm?type=command&param=addlogmessage&message=MESSAGE
//  Initiate curl
//$mensaje = urlencode("Mensaje de prueba en LOG");
//$url = $domoticz_server.'/json.htm?type=command&param=addlogmessage&message='.$mensaje;
//$respuesta = send_url($url);
//$result = file_get_contents($url);

// Will dump a beauty json :3
// var_dump(json_decode($result, true));
foreach($enchufe as $k => $v) {
if ( $mienchufe[$k] ) {

$switchcmd = '';
if ( $v == "1" ) {
	$switchcmd = 'On';
} elseif ( $v == "0" ) {
	$switchcmd = 'Off';
}

if ( $switchcmd != '' ) {
	$url = $domoticz_server.'/json.htm?type=command&param=switchlight&idx='.$mienchufe[$k].'&switchcmd='.$switchcmd;
	$respuesta = send_url($url);
	$respuesta_json = json_decode($respuesta, true);
print_r($respuesta_json);
$mensaje = urlencode("Orvibo S20 - idx: ".$mienchufe[$k]." - mac: ".$k." - status: ".$switchcmd." - response: ".$respuesta_json['status']);
$url = $domoticz_server.'/json.htm?type=command&param=addlogmessage&message='.$mensaje;
$respuesta = send_url($url);
	
	}
}

//$mensaje = urlencode("Mensaje de prueba en LOG");
//$url = $domoticz_server.'/json.htm?type=command&param=addlogmessage&message='.$mensaje;
//$respuesta = send_url($url);

}
// TURN ON / OFF
//

   socket_close($sock);
//      $db->Disconnect();
      exit;
   }

   $contador++;

}
 
socket_close($sock);


function send_url($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
curl_close($ch);
return($result);
}



 function processMessage($buf, $remote_ip, $sock) {
	global $subscribed,$enchufe;

     echo date('H:i:s')." $remote_ip : " . binaryToString($buf)."\n";
     $twenties=array(0x20, 0x20, 0x20, 0x20, 0x20, 0x20);

     $message=binaryToString($buf);
     $macAddress = '';
     if (is_integer(strpos($message, 'accf'))) {
      $macAddress = substr($message, strpos($message, 'accf'),12);
     }
     if (!$macAddress) {
      return;
     }

     echo date('H:i:s')." MAC: ".$macAddress."\n";
     $command=substr($message, 8,4);
	 echo "Command: $command \n";
//     $rec=SQLSelectOne("SELECT * FROM orvibodevices WHERE MAC LIKE '".DBSafe($macAddress)."'");
     if (!$rec['ID'] && $command!='7161') {
      echo date('H:i:s')." Unknown device.";
      return;
     }
     if ($command=='7161') { // We've asked for all sockets on the network, and smoeone has replied!
      echo date('H:i:s')." Discover reply from $macAddress\n";
      if (is_integer(strpos($message, '4952443030'))) { //from a known AllOne (because IR00 appears in the packet)
       $rec['TYPE']=1;
       if (!$rec['TITLE']) {
        $rec['TITLE']='AllOne - '.$macAddress;
       }
      } elseif (is_integer(strpos($message, '534f433030'))) { //socket
       $rec['TYPE']=0;
       if (!$rec['TITLE']) {
        $rec['TITLE']='Socket - '.$macAddress;
       }
      } else {
       $rec['TYPE']=1;
       if (!$rec['TITLE']) {
        $rec['TITLE']='Unknown - '.$macAddress;
       }
      }
	  echo $rec['TITLE']."\n";
      $rec['MAC']=$macAddress;
      $rec['IP']=$remote_ip;
      $rec['UPDATED']=date('Y-m-d H:i:s');
	  $rec['status']=substr($message,-1);
	  // AQUI ACTUALIZAMOS
	  $enchufe[$macAddress] = $rec['status'];
	  
      if ($rec['ID']) {
//       SQLUpdate('orvibodevices', $rec);
      } else {
//       SQLInsert('orvibodevices', $rec);
      }

      //subscribe to it
      //if (!$this->subscribed[$rec['MAC']] || ((time()-$this->subscribed[$rec['MAC']])>30)) {
       $macReversed=array_reverse(HexStringToArray($rec['MAC']));
       $payload = makePayload(array(0x68, 0x64, 0x00, 0x1e, 0x63, 0x6c)).makePayload(HexStringToArray($rec['MAC'])).makePayload($twenties).makePayload($macReversed).makePayload($twenties);
       echo date('H:i:s')." Sending subscribe request: ".binaryToString($payload)."\n";
       socket_sendto($sock, $payload, strlen($payload), 0, $rec['IP'], $orvibo['port']); 
       $subscribed[$rec['MAC']]=time();
       //query for name (optional)
       /*
       $payload = $this->makePayload(array(0x68, 0x64, 0x00, 0x1d, 0x72, 0x74));
       $payload.=$this->makePayload($this->HexStringToArray($rec['MAC']));
       $payload.=$this->makePayload($twenties);
       $payload.=$this->makePayload(array(0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
       echo date('H:i:s')." Sending name request: ".$this->binaryToString($payload)."\n";
       socket_sendto($sock, $payload, strlen($payload), 0, $rec['IP'], $this->port); 
       */
      //}


     } elseif ($command=='7274') { // We've queried the socket for the name, and we've got data coming back
       echo date('H:i:s')." Name reply from $macAddress\n";
       $tmp=explode('202020202020', $message);
       $strName=$tmp[4];
       if(strName == "ffffffffffffffffffffffffffffffff") {
        $strName='Orvibo '.$rec['MAC'];
        if ($rec['TYPE']==0) {
         $strName.=" (socket)";
        }
       } else {
        $strName=trim(HexStringToString($strName));
       }
       if (!$rec['TITLE']) {
        $rec['TITLE']=$strName;
//        SQLUpdate('orvibodevices', $rec);
       }

     } elseif ($command=='636c') { // We've asked to subscribe to an AllOne, and this is confirmation.
       echo date('H:i:s')." Subscription reply from $macAddress\n";
     } elseif ($command=='6463') { // We've asked to change our state, and it's happened
       echo date('H:i:s')." State change reply from $macAddress\n";
     } elseif ($command=='6469') { // Possible button press, or just a ping thing?
       echo date('H:i:s')." Button pressed from $macAddress\n";
        if ($rec['LINKED_OBJECT'] && $rec['LINKED_METHOD_BUTTON']) {
          $params=array();
          $params['VALUE']=$rec['VALUE_IR'];
          callMethod($rec['LINKED_OBJECT'].'.'.$rec['LINKED_METHOD_BUTTON'], $params);
        }
     } elseif ($command=='7366') { // Something has changed our socket state externally
       echo date('H:i:s')." Socket state changed from $macAddress\n";
       if ($rec['TYPE']==0) {
        $state=substr($message, strlen($message)-1, 1);
        $this->statusChanged($rec['ID'], (int)$state);
       }
     } elseif ($command=='6963') { // We've asked to emit some IR and it's been done.
       echo date('H:i:s')." Emit IR done from $macAddress\n";
     } elseif ($command=='6c73') { // We're in learning mode, and we've got some IR back!
       echo date('H:i:s')." IR learning mode done from $macAddress\n";
       if (substr($message, 4, 4)!='0018') {
        $code=substr($message, 52);
        echo date('H:i:s')." Code: ".$code."\n";
        $rec['VALUE_IR']=$code;
        $rec['UPDATED']=date('Y-m-d H:i:s');
        SQLUpdate('orvibodevices', $rec);

        if ($rec['LINKED_OBJECT'] && $rec['LINKED_PROPERTY']) {
         setGlobal($rec['LINKED_OBJECT'].'.'.$rec['LINKED_PROPERTY'], $rec['VALUE_IR'], array($this->name=>'0'));
        }

        if ($rec['LINKED_OBJECT'] && $rec['LINKED_METHOD']) {
          $params=array();
          $params['VALUE']=$rec['VALUE_IR'];
          callMethod($rec['LINKED_OBJECT'].'.'.$rec['LINKED_METHOD'], $params);
        }


       } else {
        echo date('H:i:s')." Ignoring result\n";
       }
     } else {
      echo date('H:i:s')." Unknown command: $command \n";
     }

  
 }