only used for debugging //----------------------------------------------------- function str2Hex($string) { $hex=''; for ($i=0; $i < strlen($string); $i++) { $hex .= dechex(ord($string[$i])).' '; } return $hex; } //----------------------------------------------------- // Open connection // klf200 uses a self signed cert with TLS. Does this make sense? // It takes around 5!!! secs to establish a connection! //----------------------------------------------------- function socketOpen($url) { $stream_context = stream_context_create([ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true, ]]); $fp = stream_socket_client('ssl://'.$url.':51200',$errno, $errstr, 10, STREAM_CLIENT_CONNECT, $stream_context); return $fp; } //----------------------------------------------------- // Send a command and get a response //----------------------------------------------------- function socketSend($fp,$payload) { $resp = ''; if ($fp) { fwrite($fp, $payload); //echo 'tx:'.str2Hex($payload).'
'; $resp = fread($fp, 255); //echo 'rx:'.str2Hex($resp).'
'; } return $resp; } //----------------------------------------------------- // Close connection //----------------------------------------------------- function socketClose($fp) { fclose($fp); } //----------------------------------------------------- // Wrap with slip //----------------------------------------------------- function slip_pack($data) { $data = str_replace(SLIP_ESC,SLIP_ESC.SLIP_ESC_ESC,$data); $data = str_replace(SLIP_END,SLIP_ESC.SLIP_ESC_END,$data); return (SLIP_END.$data.SLIP_END); } //----------------------------------------------------- // Unwrap from slip //----------------------------------------------------- function slip_unpack($data) { if (substr($data,-1) == SLIP_END) $data = substr_replace($data ,"",-1); if (substr($data, 0, 1) == SLIP_END) $data = substr($data ,1); $data = str_replace(SLIP_ESC.SLIP_ESC_END,SLIP_END,$data); $data = str_replace(SLIP_ESC.SLIP_ESC_ESC,SLIP_ESC,$data); return $data; } //----------------------------------------------------- // Add the xor checksum //----------------------------------------------------- function calc_checksum($data) { $chk = 0; for ($i=0; $i < strlen($data); $i++) { $chk = $chk ^ ord($data[$i]); } return $chk; } //----------------------------------------------------- // Build the command with checksum and slip //----------------------------------------------------- function build_cmd_str($cmd,$param) { $data = $cmd.$param; $data = chr(strlen($data)+1).$data; // add length $data = chr(0x00).$data.chr(calc_checksum($data)); // add protocol id and checksum return slip_pack($data); // add slip } //----------------------------------------------------- // Select a scene from the KLF200 //----------------------------------------------------- function klf_scene($val) { // Open connection (takes around 5secs!!!) $sock = socketOpen(KLF_IP); if (!$sock) return 'nOpen'; // Send Password (takes a few ms) $cmd = build_cmd_str(GW_PASSWORD_ENTER_REQ,KLF_PW); $resp = socketSend($sock,$cmd); // Send scene selection (takes a few tens of ms) $param = chr(19).chr($val); // SessionID, we use scene number here to differentiate interleaving calls $param = $param.chr(01); // Command Originator = user $param = $param.chr(03); // PriorityLevel = User2 $param = $param.chr($val); // SceneID $param = $param.chr(00); // Velocity = Default $cmd = build_cmd_str(GW_ACTIVATE_SCENE_REQ,$param); $resp = socketSend($sock,$cmd); // Close connection socketClose($sock); return 'ok'; } //----------------------------------------------------- // main //----------------------------------------------------- // For testing if (!isset($_GET["cmd"]) $_GET["cmd"] = '4close'; // Check the GET Parameter $res = '???'; if (isset($_GET["cmd"])) { switch (htmlspecialchars($_GET["cmd"])) { case '4close': $res = klf_scene(0); // 4OG Close break; case '4open': $res = klf_scene(1); // 4OG Open break; case '5close': $res = klf_scene(2); // 5OG Open break; case '5open': $res = klf_scene(3); // 5OG Open break; } } echo $res; ?>