<?php

class BStationManager {

	var $cloudSvr = null;
	var $cloudPort = null;
	var $timeoutSec = null;

	var $adminId = null;	
	var $adminPass = null;

	var $downData = null;
	var $downDataSize = 0;
	var $downDataPos = 0;
	var $downProgress = 0;
	var $downRetry = 0;

	var $logLevel = 0;

	var $errMsg = '';
	var $errCode = '';

	function __construct($timeoutSec) {		
		
		$this->timeoutSec = $timeoutSec;

		$this->cloudSvr = Config::get('editorenv.urcCloudServerAddr');			
		$this->cloudPort = Config::get('editorenv.urcCloudServerPort');

		$this->adminId = Config::get('editorenv.urcCloudServerAdmin');			
		$this->adminPass = Config::get('editorenv.urcCloudServerAdminPass');
	}

	
	public static function getControllerId($modelTypeId, $macData, $randId) {

		//ErrorDebug::write('getControllerId : '.$modelTypeId.'-4354-524C-49'.$randId.'-'.$macData);
		return $modelTypeId.'-4354-524C-49'.$randId.'-'.$macData;
	}

	public static function getControllerIdFromKey($systemKey) {

		$mac = '';
		$modelTypeId = '';
		$randId = '';

		if(!BStationManager::getDataFromKey($systemKey, $mac, $modelTypeId, $randId))
			return false;

		//ErrorDebug::write('getControllerIdFromKey : '.BStationManager::getControllerId($modelTypeId, $mac, $randId));

		return BStationManager::getControllerId($modelTypeId, $mac, $randId);
	}

	public static function getDataFromKey($systemKey, &$mac, &$modelTypeId, &$randId) {

		$len = strlen($systemKey);
		if($len != 36) {
			return false;
		}

		$arData = explode('-', $systemKey);

		if(count($arData) !== 5 || strlen($arData[0]) != 8 ||
			$arData[1] !== '5052' || $arData[2] != '4F47' ||
			strlen($arData[3]) != 4 || strlen($arData[4]) != 12) {

			return false;
		}

		$mac = $arData[4];

		$modelTypeId = $arData[0];
		
		$randId = substr($arData[3], 2, 2);

		return true;
	}

	public static function getMACFromControllerId($controllerId) {

		$arData = explode('-', $controllerId);
		if(count($arData) != 5)
			return false;

		//ErrorDebug::write('getMACFromControllerId : '.$arData[4]);

		return $arData[4];
	}

	/*
	public static function getModelTypeFromControllerId($controllerId) {

		$arData = explode('-', $controllerId);
		if(count($arData) != 5)
			return false;

		return BStationManager::getModelTypeFromId($arData[0]);
	}
	*/

	public static function genKeyFromUserData($modelType, $keyValue) {

		$typeId = URCValues::getModelTypeId($modelType);
		if($typeId === false) {
			return false;
		}

		$keyValue = str_replace('-', '', $keyValue);
		if(strlen($keyValue) != 16) {
			return false;
		}

		
		$progKey = $typeId.'-5052-4F47-'.substr($keyValue, 0, 4).'-'.substr($keyValue, 4, 16);

		//ErrorDebug::write('progKey : '.$progKey);

		return $progKey;
	}


	public function genAuthentication($username, $password) {

		return base64_encode($username.':'.$password);
	}

	public function chkLogController($mac_addr, $event, $description, $timeoutSec) {
		
		$this->logLevel = 0;

		$logSvr = Config::get('editorenv.urcLogServerAddr');
		$logUser = Config::get('editorenv.urcLogServerUserInfo');

		$sendData = $logSvr.'GetControllerEnv?mac='.urlencode($mac_addr).'&event_name='.urlencode($event).'&description='.urlencode($description);

		$ch = curl_init();
	 
	 	curl_setopt($ch, CURLOPT_URL, $sendData);
	    curl_setopt($ch, CURLOPT_USERPWD, $logUser);
	    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
	    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
	    
	    $result = curl_exec($ch);
	    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	    curl_close($ch);

	    if($httpCode == 200 && $result) {

			$xml = simplexml_load_string($result);
		
	    	$option = array('alwaysArray' => array());
			$resultInfo = StringGenerator::xmlToArray($xml, $option);
			//$resultJson = json_decode(json_encode($resultInfo));

			if(isset($resultInfo['ROOT']['controller_info']['debug_log_level'])) {
	    		
	    		$this->logLevel = $resultInfo['ROOT']['controller_info']['debug_log_level'];
	    	}
	    }

	    //ErrorDebug::write('logLevel'.$this->logLevel);
	}

	public function logEventToServer($mac_addr, $event, $description, $timeoutSec) {
		
		$logSvr = Config::get('editorenv.urcLogServerAddr');
		$logUser = Config::get('editorenv.urcLogServerUserInfo');

		$log = '<result>:'.$httpCode.'<data>:'.$data;//$resultData;

		$sendData = $logSvr.'AddEventLog?mac='.urlencode($mac_addr).'&event_name='.urlencode($event).'&description='.urlencode($description);

	    $ch = curl_init();
	 
	 	curl_setopt($ch, CURLOPT_URL, $sendData);
	    curl_setopt($ch, CURLOPT_USERPWD, $logUser);
	    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
	    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
	    
	    $result = curl_exec($ch);
	    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	    curl_close($ch);
	}

	public function logToServer($mac_addr, $path, $httpCode, $resultData, $data, $timeoutSec) {
		
		$logSvr = Config::get('editorenv.urcLogServerAddr');
		$logUser = Config::get('editorenv.urcLogServerUserInfo');

		$log = '<result>:'.$httpCode.'<data>:'.$data;//$resultData;

		$sendData = $logSvr.'AddDebugLog?mac='.urlencode($mac_addr).'&type='.urlencode($path).'&log='.urlencode($log);

	    $ch = curl_init();
	 
	 	curl_setopt($ch, CURLOPT_URL, $sendData);
	    curl_setopt($ch, CURLOPT_USERPWD, $logUser);
	    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
	    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
	    
	    $result = curl_exec($ch);
	    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	    curl_close($ch);
	}

	public function curl_req($path, $req, $authorization, $data = '', &$resultData, $timeoutSec)
	{
		//ErrorDebug::write('curl_req1');
	    $ch = curl_init();
	    curl_setopt($ch, CURLOPT_URL, $this->cloudSvr.$path);
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $req);
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

	    if($timeoutSec > 0) {
	    	curl_setopt($ch, CURLOPT_TIMEOUT, $timeoutSec);
	    }
	    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
	    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false );
	    curl_setopt($ch, CURLOPT_PORT, $this->cloudPort);

	    //ErrorDebug::write('curl_req2'.$data);
	    //http_build_query
	    if($req == 'POST') {
	    	curl_setopt($ch, CURLOPT_POST, true );
	    	curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
	    }
	    else if($req == 'PUT') {
	    	//curl_setopt($ch, CURLOPT_POST, true );
	    	//curl_setopt($ch, CURLOPT_PUT, true);
	    	curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
			//curl_setopt($ch, CURLOPT_INFILE, $data);
			//curl_setopt($ch, CURLOPT_INFILESIZE, strlen($data));
	    }	    
	    else if($req == 'DELETE') {
	    	curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
	    }

	    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Basic '.$authorization, 
	    	'Content-Type: application/json','Content-Length: ' . strlen($data)));

	    $resultData = curl_exec($ch);
	    //ErrorDebug::write('curl_req3Result:'.$resultData);
	    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	    curl_close($ch);

	    $logWritten = 0;
	    if($httpCode != 200 && $data) {
	    	$dataInfo = json_decode($data);
	    	if(isset($dataInfo->target_id)) {
		    	$mac_addr = BStationmanager::getMACFromControllerId($dataInfo->target_id);
	    		$this->logToServer($mac_addr, $path, $httpCode, $resultData, $resultData, 5);
	    		$logWritten = 1;
	    	}
	    }

	    if($this->logLevel > 0 && $logWritten == 0) {
	    	$mac_addr = 'unknown';
	    	if($data) {
	    		$dataInfo = json_decode($data);
	    		if(isset($dataInfo->target_id)) {
	    			$mac_addr = BStationmanager::getMACFromControllerId($dataInfo->target_id);
	    		}
	    	}
	    	
	    	$this->logToServer($mac_addr, $path, $httpCode, $resultData, $resultData, 5);
	    }

	    
		//ErrorDebug::write('curl_req4Code:'.$httpCode);
	    return $httpCode;
	}		

	public function getErrResult() {
		if(Config::get('editorenv.prg_version') == 0) {
			return $this->errMsg;
		}
		else {
			return $this->errMsg.'('.$this->errCode.')';
		}
	}

	public function getErrMsg() {
		return $this->errMsg;
	}

	public function getErrCode() {
		return $this->errCode;
	}

	public function setErrMsg($msg, $code) {
		$this->errMsg = $msg;
		$this->errCode = $code;
	}

	public function requestEnc($msgId, &$requestData) {

		$requestDataJson = json_encode($requestData);
		return $msgId.base64_encode($requestDataJson);
	}

	public function responseParse($responserId, &$resultData, $msgId, &$response) {

		$resultInfo = json_decode($resultData);
	    if(!isset($resultInfo->status) || $resultInfo->status !== 'succeeded') {
	    	if(isset($resultInfo->cause)) {
	    		$this->setErrMsg($resultInfo->cause, '');
	    	}
	    	else {
	    		$this->setErrMsg('Wrong Result', 'No cause');
	    	}
	    	$mac_addr = BStationmanager::getMACFromControllerId($responserId);
	    	$this->logToServer($mac_addr, "responseParseErr", 0, $resultData, $resultData, 5);
	    	return false;
	    }

	    if(strncmp($resultInfo->response, $msgId, 8)) {
	    	ErrorDebug::write('critical Error:MessageID Wrong');
	    	$this->setErrMsg('Wrong Result', 'The message id is wrong');
	    	$mac_addr = BStationmanager::getMACFromControllerId($responserId);
	    	$this->logToServer($mac_addr, "responseParseErr", 0, $resultData, $resultData, 5);
	    	return false;
		}

		$response = base64_decode(substr($resultInfo->response, 8));
		return true;
	}

	public function responseParseObj($responserId, &$resultData, $msgId, &$response) {

		$responseJson = '';
		if($this->responseParse($responserId, $resultData, $msgId, $responseJson) === false) {
			return false;
		}

	    $response = json_decode($responseJson);
	    return true;
	}

	public function customCheckKey($systemKey) {
		
		$mac_addr = '';
		$modelTypeId = '';
		$randId = '';
		if(BStationManager::getDataFromKey($systemKey, $mac_addr, $modelTypeId, $randId) !== true) {
			$this->setErrMsg("system key type error", '');
			return false;
		}
		
		$authData64 = $this->genAuthentication($this->adminId, $this->adminPass);
		
		$controllerId = BStationManager::getControllerId($modelTypeId, $mac_addr, $randId);
		$msgId = StringGenerator::gen_msg_id();

		//ErrorDebug::write('msgId:'.$msgId);
	
		$requestData = array('method' => 'GET', 'uri' => '/rest/registration/key?device='.urlencode($mac_addr));
		$pdata = array('from_id' => $this->adminId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		//$time = microtime(TRUE);

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, 10);
		if($httpCode != 200) {
	   		$this->setErrMsg('Communication error - Check the System Key', 'registration:'.$httpCode);
	   		return false;
	    }

	    //$dif = microtime(TRUE) - $time;
	    //ErrorDebug::write('time spent(custom) : '.$dif);

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->program_key)) {
	    	$this->setErrMsg('Wrong result', '');
	    	return false;
	    }
	
		//ErrorDebug::write('bstation:'.$response->program_key);
		//ErrorDebug::write('org:'.$systemKey);
	    if($response->program_key !== $systemKey) {
	    	$this->setErrMsg('Please check the programming key', '');
	    	return false;
	    }
		
		return true;
	}
	
	public function customCheckConnection($sipId, $password, $controllerId) {
		
		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
	
		$mac_addr = BStationManager::getMACFromControllerId($controllerId);
	
		$echo64 = base64_encode('ECHO');
		$requestData = array('method' => 'POST', 'uri' => '/rest/echo?device='.urlencode($mac_addr), 'body' => $echo64);
		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, 15);
		if($httpCode != 200) {
	   		//ErrorDebug::write($resultData.$httpCode);
	   		$this->setErrMsg('Communication error - The basestation is not connected', 'echo:'.$httpCode);
	   		return false;
	    }
	    
	    $response = '';
	    if($this->responseParse($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }
	    
	    if($response !== base64_encode('ECHO')) {
	       	$this->setErrMsg('Wrong result', '');
	    	return false;
	    }
		
		return true;
	}

	public function createUser($sipId, $password, &$httpCode) {
		
		$authData64 = $this->genAuthentication($this->adminId, $this->adminPass);

		/*
		$resultData = '';
		$httpCode = $this->curl_req('/users', 'GET', $authData64, '', $resultData, -1);
	   	if($httpCode != 200) {
	   		return false;
	    }
	    //ErrorDebug::write('Result Data : '.$resultData);

		$deleteData = json_decode($resultData);
		foreach($deleteData->items as $item) {

			if(strncmp($item->username, 'cy', 2) == 0 ||
				strncmp($item->username, 'ey', 2) == 0) {

				ErrorDebug::write(json_encode($item));
				if(strcmp($item->username, 'cyrpro') == 0)
					continue;

				$this->deleteUser($item->username);
				ErrorDebug::write('DELETED:'.$item->username);
			}
		}
		*/

		$pdata = array(
			//'id' => $username.'-'.$password,
			'username' => $sipId,
			'password' => $password
		);		

		//$time = microtime(TRUE);

		$resultData = '';
		$httpCode = $this->curl_req('/addUser', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
	   	
	   		$this->setErrMsg('Communication error - Fail to create user', 'createUser:'.$httpCode);
	   		//ErrorDebug::write('createUser Err'.$resultData.$httpCode);
	   		return false;
	    }
	    
	    //ErrorDebug::write('createUser'.$resultData.$httpCode);
	    //$dif = microtime(TRUE) - $time;
	    //ErrorDebug::write('time spent(user Create) : '.$dif);

	    //$resultInfo = json_decode($resultData);
		//$resultId = $sipId;//$resultInfo->id;

		return true;
	}

	public function deleteUser($sipId) {
		
		$authData64 = $this->genAuthentication($this->adminId, $this->adminPass);

		$pdata = array(
			//'id' => $username.'-'.$password,
			'username' => $sipId
		);

		$resultData = '';
		$httpCode = $this->curl_req('/deleteUser', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
	   		$this->setErrMsg('Communication Error - Fail to delete user', 'deleteUser:'.$httpCode);
	   		return false;
	    }
		
		return true;
	}

	public function updateUser($sipId, $newPass) {

		$authData64 = $this->genAuthentication($this->adminId, $this->adminPass);

		$pdata = array(
			'username' => $sipId,
			'password' => $newPass
		);

		$resultData = '';
		$httpCode = $this->curl_req('/updateUser', 'POST', $authData64, json_encode($pdata), $resultData, -1);
	   	if($httpCode != 200) {
	   		$this->setErrMsg('Communication Error - Fail to update user', 'updateUser:'.$httpCode);
	   		return false;
	    }

		return true;
	}	

	public function createBasestation($sipId, $password, $controllerId) {//HCM-C100-TEST-TEST-TEST-605BAE641872
	    
	    $authData64 = $this->genAuthentication($sipId, $password);

    	$pdata = array(
			'username' => $sipId,
			'controller_id' => $controllerId
		);
		$resultData = '';
		$httpCode = $this->curl_req('/addController', 'POST', $authData64, json_encode($pdata), $resultData, -1);	   	
		if($httpCode != 200) {
			$this->setErrMsg('Communication Error', 'createBasestation:'.$httpCode.$resultData);
			ErrorDebug::write($httpCode.$resultData);
	   		return false;
		}
		
		return true;
	}
	
	public function deleteBasestation($sipId, $password, $controllerId) {//HS-C100-TEST-TEST-TEST-605BAE641872
	    
	    $authData64 = $this->genAuthentication($this->adminId, $this->adminPass);

	    $pdata = array(
			'username' => $sipId,
			'controller_id' => $controllerId
		);

		$resultData = '';
		$httpCode = $this->curl_req('/deleteController', 'POST', $authData64, json_encode($pdata), $resultData, -1);
	   	if($httpCode != 204) {
	   		$this->setErrMsg('Communication Error - Fail to delete basestation', 'deleteBasestation:'.$httpCode);
	   		//ErrorDebug::write('ERROR : deleteBasestation('.$controllerId.'):'.$httpCode);
	   		return false;
	    }
		
		return true;
	}

	/*
	public function customDeleteBasestation($username, $password, $userUniqueId, $controllerId) {
		
		$authData64 = $this->genAuthentication($username, $password);
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);

		$requestData = array('method' => 'GET', 'uri' => '/rest/registration/remove?device='.$mac_addr);
		$pdata = array('from_id' => $username, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, 10);

		$response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

		return $this->deleteBasestation($username, $password, $userUniqueId, $controllerId);
	}
	*/

	public function customSearchDevice($sipId, $controllerId, $deviceType, $deviceMac) {

		/*
		$arDevice = array();
		switch($deviceType)
		{
		case 'HCM-C1':
			$arDevice[0] = (object)array('name' =>'HCM-C1', 'mac' => '112233445566');
			$arDevice[1] = (object)array('name' =>'HCM-C1', 'mac' =>'112233445567');
			$arDevice[2] = (object)array('name' =>'HCM-C1', 'mac' =>'112233445568');
			$arDevice[3] = (object)array('name' =>'HCM-C1', 'mac' =>'112233445569');
			return $arDevice;
		case 'HCM-R1':
			$arDevice[0] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445566');
			$arDevice[1] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445567');
			$arDevice[2] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445568');
			$arDevice[3] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445569');
			return $arDevice;
		default:
			return false;
		}

		return $arDevice;
		*/
		
		$authData64 = $this->genAuthentication($this->adminId, $this->adminPass);
		$msgId = StringGenerator::gen_msg_id();
		$modelUriId = URCValues::getModelUriId($deviceType);

		$requestData = array('method' => 'GET', 'uri' => '/rest/discover?model='.urlencode($modelUriId).'&device='.$deviceMac);
		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg('Cannot communicate with the system. Check network connections', 'searchDevice:'.$httpCode);
	   		//ErrorDebug::write($resultData.$httpCode);
	   		return false;
	    }
	    //ErrorDebug::write($resultData.$httpCode);
	    
	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->devices) || count($response->devices) < 1) {
	    	$this->setErrMsg('NO DEVICE', '');
	    	return false;
	    }

   		$cnt = count($response->devices);

   		$retDevices = array();
   		if(URCValues::isBasestation($deviceType)) {
   			for($i = 0; $i < $cnt; $i++) {
		    	if(URCValues::isBasestation($response->devices[$i]->name)) {
		    		$item = $response->devices[$i];
		    		unset($item->ctrl_url);
		    		$retDevices[] = $item;
		    	}
		    }
		}
		else if(URCValues::isRemoteControl($deviceType)) {
			for($i = 0; $i < $cnt; $i++) {
		    	if(URCValues::isRemoteControl($response->devices[$i]->name)) {
		    		$item = $response->devices[$i];
		    		unset($item->ctrl_url);
		    		$retDevices[] = $item;
		    	}
		    }
		}
		else {
			$retDevices = $response->devices;
		}	    

		return $retDevices;
   		/*
   		if(URCValues::isBasestation($deviceType)) {
   			ErrorDebug::write('bcnt'.$cnt);
		    for($i = 0; $i < $cnt; $i++) {
		    	if(!URCValues::isBasestation($response->devices[$i]->name)) {
		    		$cnt--;
		    		$i--;
		    		unset($response->devices[$i]);
		    	}
		    	unset($response->devices[$i]->ctrl_url);
		    }

		    ErrorDebug::write('finalCnt'.$cnt);
		    ErrorDebug::write(json_encode($response->devices));   		
		}
		else if(URCValues::isRemoteControl($deviceType)) {
			for($i = 0; $i < $cnt; $i++) {
		    	if(!URCValues::isRemoteControl($response->devices[$i]->name)) {
		    		$cnt--;
		    		$i--;
		    		unset($response->devices[$i]);
		    	}	
		    	unset($response->devices[$i]->ctrl_url);
		    }
		}	    
	    
	    return $response->devices;
	    */
	}

	public function customSearchDeviceTRFZW($sipId, $controllerId, $deviceType) {

		/*
		$arDevice = array();
		switch($deviceType)
		{
		case 'HCM-C1':
			$arDevice[0] = (object)array('name' =>'HCM-C1', 'mac' => '112233445566');
			$arDevice[1] = (object)array('name' =>'HCM-C1', 'mac' =>'112233445567');
			$arDevice[2] = (object)array('name' =>'HCM-C1', 'mac' =>'112233445568');
			$arDevice[3] = (object)array('name' =>'HCM-C1', 'mac' =>'112233445569');
			return $arDevice;
		case 'HCM-R1':
			$arDevice[0] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445566');
			$arDevice[1] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445567');
			$arDevice[2] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445568');
			$arDevice[3] = (object)array('name' =>'HCM-R1', 'mac' =>'312233445569');
			return $arDevice;
		default:
			return false;
		}

		return $arDevice;
		*/
		
		$authData64 = $this->genAuthentication($this->adminId, $this->adminPass);
		$msgId = StringGenerator::gen_msg_id();
		//$modelUriId = URCValues::getModelUriId($deviceType);

		$requestData = array('method' => 'GET', 'uri' => '/rest/tcl/discover');
		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg('Cannot communicate with the system. Check network connections', 'searchDevice:'.$httpCode);
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    //ErrorDebug::write(json_encode($response));	    
	    

	    if(!isset($response->discovered) || count($response->discovered) < 1) {
	    	$this->setErrMsg('NO DEVICE', '');
	    	return false;
	    }

   		
   		foreach($response->discovered as &$device) {
	    	$device->name = "TRF-ZW1";
	    	$device->mac  = str_replace(':', '', $device->MAC);
	    	unset($device->MAC);
	    }
	    

	    return $response->discovered;
	}

	public function customTest($sipId, $password, $controllerId, $target, $attr, $data) {
		
		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		/*
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false)
			return false;
		*/
		
		/*
		$requestData = array('method' => 'GET', 
			'uri' => '/rest/timestamp?id='.urlencode($msgId));
		*/
		
		switch($target->type) 
		{
		case URCValues::DB_TYPE_IR:
			$requestData = array('method' => 'POST', 
				'uri' => '/rest/test_cmd?type=ir&device='.urlencode($target->mac).'&ir_type='.urlencode($target->ir_type).'&ir_port='.urlencode($target->ir_port).
				'&repeat='.$attr->repeat, 'body' => $data);
			break;
		case URCValues::DB_TYPE_IP:
			$requestData = array('method' => 'POST', 
				'uri' => '/rest/test_cmd?type=tcp&ip='.urlencode($target->ip).'&port='.urlencode($target->port).
				'&repeat='.$attr->repeat.'&ramp_start='.$attr->ramp_start.'&ramp_speed='.$attr->ramp_speed, 'body' => $data);
			break;
		case URCValues::DB_TYPE_UDP:
			$requestData = array('method' => 'POST', 
				'uri' => '/rest/test_cmd?type=udp&ip='.urlencode($target->ip).'&port='.urlencode($target->port).
				'&repeat='.$attr->repeat.'&ramp_start='.$attr->ramp_start.'&ramp_speed='.$attr->ramp_speed, 'body' => $data);
			break;
		default:
			$this->setErrMsg('Target Type Error', '');	    	
			return false;
		}		

		//ErrorDebug::write(json_encode($requestData));

		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		//ErrorDebug::write(json_encode($pdata));
		
		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg('Communication Error - Fail to test', 'test:'.$httpCode);
	   		//ErrorDebug::write($resultData.$httpCode);
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg('Testing Error', '');
	    	return false;
	    }

	    //ErrorDebug::write('retur : TRUE');

	    return true;
	}

	public function customDeviceStatus($sipId, $password, $controllerId, $devices) {

		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}
		
		$devicesObj = new stdClass;
		$devicesObj->devices = $devices;
		$requestUri = '/rest/dev_status';
		$requestData = array('method' => 'POST', 'uri' => $requestUri, 'body' => $devicesObj);
		//ErrorDebug::write('src : '.$requestDataJson);

		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
	   		$this->setErrMsg('Communication Error', 'dev_status:'.$httpCode);
	   		return false;
		}

		$response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }
		
		if(!isset($response->devices)) {
			$this->setErrMsg('NO DEVICE', '');
			return false;
		}

		return $response->devices;
	}

	public function customLearnStart($sipId, $password, $userId, $controllerId) {
		
		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		//learn start flag
		DB::table('user')->where('id', '=', $userId/*//JWT->Auth::id()*/)->
			update(array('status' => 'l_start'));			

		$requestUri = '/rest/ir_learn?device='.urlencode($mac_addr);
		$requestData = array('method' => 'GET', 'uri' => $requestUri);

		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg("Failed to start learning - base station didn't respond", 'ir_learn:'.$httpCode);
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg("Failed to start learning - base station didn't respond", '');
	    	return false;
	    }

		DB::table('user')->where('id', '=', $userId/*//JWT->Auth::id()*/)->
			update(array('status' => 'l_doing'.StringGenerator::doGen(20)));	

	    return true;
	}

	public function customGetLearnData($sipId, $password, $userId, $controllerId) {
	
		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$userChk = DB::table('user')->where('id', '=', $userId/*//JWT->Auth::id()*/)->first();
		$learnDoingCode = $userChk->status;
		//ErrorDebug::write('learnCode'.$learnDoingCode);
		
		$requestUri = '/rest/ir_data?device='.urlencode($mac_addr);
		$requestData = array('method' => 'GET', 'uri' => $requestUri);

		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';

		$time = microtime(TRUE);
		$dif = microtime(TRUE) - $time;		
		while($dif < 30) {
			
			$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, 3);
			if($httpCode == 200) {

				$response = '';
			    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == true) {

			    	if(isset($response->result) && $response->result == 'ok') {
				    	//ErrorDebug::write('continue'.json_encode($response));
			    		if($response->code == 204) {
			    			sleep(2);
			    			$dif = microtime(TRUE) - $time;
			    			//ErrorDebug::write('aa9'.$dif);
							continue;
			    		}
			    		return $response->data;
			    	}
			    }
			}

			$dif = microtime(TRUE) - $time;
			//ErrorDebug::write('aa9'.$dif);
			if($dif < 30) {
				$userChk = DB::table('user')->where('id', '=', $userId/*//JWT->Auth::id()*/)->first();
				if($userChk->status == $learnDoingCode) continue;
			}
			if($httpCode !== 200) {
	   			$this->setErrMsg('Communication error interrupted learning', 'ir_data:'.$httpCode);
   				return false;
   			}

   			break;
	    }
	    
	    $this->setErrMsg('Failed, try again', '');
	    return false;
	}

	public function customGetVersionInfo($sipId, $password, $controllerId, $firmwareType) {

		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$requestUri = '/rest/conf/net_cfg';
		$requestData = array('method' => 'GET', 'uri' => $requestUri);

		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg("Failed to get version info", 'get_version:'.$httpCode);
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	$this->setErrMsg("Failed to get version info - parse error", 'get_version:'.$httpCode);
	   		return false;
	    }

	    //ErrorDebug::write('response'.json_encode($response));	    

	    if(!isset($response->result) || $response->result !== 'ok' || !isset($response->ext_versions)) {
	    	$this->setErrMsg("Failed to get version info - wrong response", '');
	    	return false;
	    }

	    foreach($response->ext_versions as $versionObj) {
	    	if($versionObj->name == $firmwareType) {
	    		return $versionObj->version;
	    	}
	    }
	    
		$this->setErrMsg("Failed to find version info", '');
	    return false;
	}

	/*
	public function customLearnStart($username, $password, $controllerId) {
		
		$authData64 = $this->genAuthentication($username, $password);
		
		$msgId = StringGenerator::gen_uuid();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}
		
		$requestUri = '/rest/ir_learn?device='.urlencode($mac_addr);
		$requestData = array('method' => 'GET', 'uri' => $requestUri);
		$requestDataJson = json_encode($requestData);

		$pdata = array('id' => $msgId, 'controllerId' => $controllerId, 'request' => base64_encode($requestDataJson));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg('Communication Error - Fail to start the learning mode', 'ir_learn:'.$httpCode);
	   		return false;
	    }
	    $resultInfo = json_decode($resultData);
	    $responseJson = base64_decode($resultInfo->response);

	   
	    $response = json_decode($responseJson);
	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg('Fail to start the learning mode', '');
	    	return false;
	    }

	    return true;
	}

	public function customGetLearnData($username, $password, $controllerId) {
	
		$authData64 = $this->genAuthentication($username, $password);
		
		$msgId = StringGenerator::gen_uuid();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}
		
		$requestUri = '/rest/ir_data?device='.urlencode($mac_addr);
		$requestData = array('method' => 'GET', 'uri' => $requestUri);
		$requestDataJson = json_encode($requestData);

		$pdata = array('id' => $msgId, 'controllerId' => $controllerId, 'request' => base64_encode($requestDataJson));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
	   		$this->setErrMsg('Communication Error', 'ir_data:'.$httpCode);
	   		return false;
	    }
	    $resultInfo = json_decode($resultData);
	    $responseJson = base64_decode($resultInfo->response);

		//ErrorDebug::write('learn data : '.$responseJson);

	    $response = json_decode($responseJson);
	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg('Learn Error', '');
	    	return false;
	    }

	    return $response->data;
	}
	*/

	public function initDownRetry() {
		
		$this->downRetry = 0;
	}

	public function isDownRetryOver() {
	
		if($this->downRetry > 3) {
			return true;
		}

		return false;
	}

	public function increaseDownRetry() {

		$this->downRetry++;
	}

	public function customDownStart($sipId, $password, $controllerId, &$data) {
		
		$this->downData = $data;
		$this->downDataSize = strlen($data);
		$this->downDataPos = 0;
		$this->downProgress = 0;

		$this->downUser = $sipId;
		$this->downPass = $password;
		$this->downCtrlId = $controllerId;

		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$body = (object)array( 'file' => 'system.json', 'size' => $this->downDataSize);

		//ErrorDebug::write('DownStart Size: '.$this->downDataSize);

		$requestUri = '/rest/upgrade?device='.urlencode($mac_addr).'&mode=start';
		$requestData = array('method' => 'POST', 'uri' => $requestUri, 'body' => $body);
		
		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		if($this->logLevel > 1) {
			$this->logToServer($mac_addr, 'downloading Start', 'start', '', '', 5);
		}

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
	   		$this->setErrMsg('Communication Error - Fail to start downloading', 'upgrade:'.$httpCode);
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg('Fail to download', '');
	    	return false;
	    }

	    return true;
	}

	public function customDownStartHTTP($sipId, $password, $controllerId, &$data) {
		
		$this->downData = $data;
		$this->downDataSize = strlen($data);
		$this->downDataPos = 0;
		$this->downProgress = 0;

		$this->downUser = $sipId;
		$this->downPass = $password;
		$this->downCtrlId = $controllerId;

		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$body = (object)array( 'file' => 'system.json', 'size' => $this->downDataSize);

		//ErrorDebug::write('DownStart Size: '.$this->downDataSize);

		$requestUri = '/rest/db_down_http?device='.urlencode($mac_addr).'&mode=start';
		$requestData = array('method' => 'POST', 'uri' => $requestUri, 'body' => $body);
		
		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		if($this->logLevel > 1) {
			$this->logToServer($mac_addr, 'downloading Start', 'start', '', '', 5);
		}

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
	   		$this->setErrMsg('Communication Error - Fail to start downloading', 'upgrade:'.$httpCode);
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg('Fail to download', '');
	    	//ErrorDebug::write(json_encode($response));
	    	return false;
	    }

	    return true;
	}

	public function customDownProgress() {
		
		return $this->downProgress;
	}

	public function customDownSend($isSendProgress) {

		$ret = false;
		$downSize = $this->downDataSize - $this->downDataPos;
		if($downSize <= 0) {
			$ret = $this->customDownSendDone($isSendProgress, 'upgrade');
		}
		else {
			
			$ret = $this->customDownSendInner($downSize);
		}

		if($isSendProgress) {
			if($ret === false) {

				echo ';ERROR : sending error';
				//ob_flush();
				flush();
				//ErrorDebug::write('customDownSend : ERRRR');
			}
			else {

				//ErrorDebug::write('customDownSend st');
				echo ';'.$this->customDownProgress();
				//ob_flush();
		    	flush();	    	
		    	//ErrorDebug::write('customDownSend : '.$this->customDownProgress());
			}
		}

	    return $ret;
	}

	public function customDownSendInner($downSize) {

		if($downSize > 1024*8) {
			$downSize = 1024*8;
		}

		//ErrorDebug::write('customDownSendInner : '.$downSize);

		$downSeq = (int) (($this->downDataPos +(1024*8)-1) / (1024*8) + 1);
		//ErrorDebug::write('downSeq : '.$downSeq.'   downsize :'.$downSize);

		$dataSub64 = base64_encode(subStr($this->downData, $this->downDataPos, $downSize));
		
		$authData64 = $this->genAuthentication($this->downUser, $this->downPass);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($this->downCtrlId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}
			
		$requestUri = '/rest/upgrade?device='.urlencode($mac_addr).'&mode=file&seq='.$downSeq;

		//ErrorDebug::write('request info : '.$requestUri);
		$requestData = array('method' => 'POST', 'uri' => $requestUri, 'body' => $dataSub64);
		$pdata = array('from_id' => $this->downUser, 'target_id' => $this->downCtrlId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$pdataJson = json_encode($pdata);

		//ErrorDebug::write($pdataJson);		

		$resultData = '';
		$selfClassData = $this;

		if($this->logLevel > 1) {
			$this->logToServer($mac_addr, 'downloading', 'start', '', $requestUri, 5);
		}

		//ErrorDebug::write('down:'.$downSeq);
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, 5);
		if($httpCode != 200) {

			//ErrorDebug::write('err:'.$httpCode.$resultData);
			
			if($this->isDownRetryOver()) {
	    		$this->setErrMsg('Over the retry count', 'upgrade:'.$httpCode);	    	
				return false;
	    	}

			//ErrorDebug::write('RetrySend');
	    	$this->increaseDownRetry();
	    	return true;//for retry
	    }

	   //ErrorDebug::write('ok:'.$httpCode.$resultData);

	    
	    /*
		$ch = curl_init();
	    curl_setopt($ch, CURLOPT_URL, $this->cloudSvr.'/sendRequest');
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
	    //http_build_query
	    curl_setopt($ch, CURLOPT_POST, true );
	    curl_setopt($ch, CURLOPT_POSTFIELDS, $pdataJson);
	    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Basic '.$authData64, 
	    	'Content-Type: application/json','Content-Length: ' . strlen($pdataJson)));

	    curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 
	    	function($resource, $dltotal, $dlnow, $ultotal, $ulnow) use($selfClassData) {
	    		
	    		ErrorDebug::write('callback Start : dnDownPos:'.$selfClassData->downDataPos.' dnDownSize:'.$selfClassData->downDataSize.' dltotal:'.$dltotal.'dlnow:'.$dlnow);

	    		$dnPercent = @round((($ulnow + $selfClassData->downDataPos)*100)/$selfClassData->downDataSize);
	    		ErrorDebug::write('callback : '.$dnPercent.'dltotal'.$dltotal.'dlnow'.$dlnow.'ultotal'.$ultotal.'ulnow'.$ulnow);
	    		if($dnPercent >= 100) $dnPercent = 99;
				
				if($selfClassData->downProgress != $dnPercent) {
	    			echo ';'.$dnPercent;

	    			//ob_flush();
				    flush();
				    //sleep(1);
	    			$selfClassData->downProgress = $dnPercent;
	    			ErrorDebug::write('dnPercent : '.$dnPercent);
	    		}
	    	});

		//curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
		//curl_setopt($ch, CURLOPT_NOPROGRESS, false);
		//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		//curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);

		ErrorDebug::write('curl_req2Result:');

	    $resultData = curl_exec($ch);
	    ErrorDebug::write('curl_req3Result:'.$resultData);
	    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	    curl_close($ch);

		if($httpCode != 200) {
	   		ErrorDebug::write('error send : '.$resultData.$httpCode);
	   		return false;
	    }
	    */

	    $response = '';
	    if($this->responseParseObj($this->downCtrlId, $resultData, $msgId, $response) == false ||
	    	!isset($response->result) || $response->result !== 'ok' || $response->seq != $downSeq) {
	    	
	    	$this->logToServer($mac_addr, 'download_err', 200, '', json_encode($response), 5);

	    	if($this->isDownRetryOver()) {
	    		$this->setErrMsg('Over the retry count', '');	    	
				return false;
	    	}

			//ErrorDebug::write('RetrySend');
	    	$this->increaseDownRetry();
	    	return true;//for retry
	    }

	    $this->downDataPos += $downSize;

		$this->initDownRetry();
		$dnPercent = @round(($this->downDataPos*100)/$this->downDataSize);
		if($dnPercent >= 100) $dnPercent = 99;

		$this->downProgress = $dnPercent;

		//ErrorDebug::write('downDataPos'.$this->downDataPos);

	    return true;
	}

	public function customDownSendHTTPStatus() {

		$retStatus = 0;
		$ret = $this->customDownSendInnerHTTPStatus($retStatus);

		if($ret === false) {

			//echo ';ERROR : sending error';
			//flush();
			//ErrorDebug::write('customDownSend : ERRRR');
		}
		else {

			if($retStatus >= 100) {
				$isSendProgress = 1;
				$ret = $this->customDownSendDone($isSendProgress, 'db_down_http');
			}
			else {
				$this->downProgress = $retStatus;
				echo ';'.$this->customDownProgress();
				//ob_flush();
		    	flush();
			}
		}

	    return $ret;
	}

	public function customDownSendInnerHTTPStatus(&$retStatus) {

		$authData64 = $this->genAuthentication($this->downUser, $this->downPass);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($this->downCtrlId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$body = '';
		$requestUri = '/rest/db_down_http?device='.urlencode($mac_addr).'&mode=status';
		$requestData = array('method' => 'POST', 'uri' => $requestUri, 'body' => $body);
		$pdata = array('from_id' => $this->downUser, 'target_id' => $this->downCtrlId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		if($this->logLevel > 1) {
			$this->logToServer($mac_addr, 'downloading Status', 'start', '', '', 5);
		}

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			if($this->isDownRetryOver()) {
	    		$this->setErrMsg('Over the retry count', '');	    	
				return false;
	    	}

			//ErrorDebug::write('RetryDone');
	    	$this->increaseDownRetry();
	    	$this->setErrMsg('Communication Error', 'upgrade_status:'.$httpCode);	
			//ErrorDebug::write($resultData.$httpCode);
	   		return $this->customDownProgress();
	    }

   	    $response = '';	    
	    if($this->responseParseObj($this->downCtrlId, $resultData, $msgId, $response) == false || 
	    	!isset($response->result) || $response->result !== 'ok') {
	    	if($this->isDownRetryOver()) {
	    		$this->setErrMsg('Over the retry count', '');	    	
				return false;
	    	}

	    	//ErrorDebug::write(json_encode($response));
			//ErrorDebug::write('RetryDone');
	    	$this->increaseDownRetry();
	    	return $this->customDownProgress();//for retry
	    }

	    //flush();
 
	    $this->initDownRetry();
	    $retStatus = $response->status;
	    //ErrorDebug::write('ok'.json_encode($response));

	    return true;
	}

	public function customDownSendDone($isSendProgress, $cmdType) {

//ErrorDebug::write('Done1');
		$authData64 = $this->genAuthentication($this->downUser, $this->downPass);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($this->downCtrlId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$checksum = md5($this->downData);
		$body = (object)array( 'checksum' => $checksum);

		$requestUri = '/rest/'.$cmdType.'?device='.urlencode($mac_addr).'&mode=end';
		$requestData = array('method' => 'POST', 'uri' => $requestUri, 'body' => $body);
		$pdata = array('from_id' => $this->downUser, 'target_id' => $this->downCtrlId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		if($this->logLevel > 1) {
			$this->logToServer($mac_addr, 'downloading Done', 'start', '', '', 5);
		}

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg('Communication Error', 'upgrade_done:'.$httpCode);	
			//ErrorDebug::write($resultData.$httpCode);
	   		return false;
	    }

   	    $response = '';	    
	    if($this->responseParseObj($this->downCtrlId, $resultData, $msgId, $response) == false || 
	    	!isset($response->result) || $response->result !== 'ok') {
	    	if($this->isDownRetryOver()) {
	    		$this->setErrMsg('Over the retry count', '');	    	
				return false;
	    	}

			//ErrorDebug::write('Done'.json_encode($response));
	    	$this->increaseDownRetry();
	    	return true;//for retry
	    }

	    //flush();
 
	    $this->initDownRetry();

	    $this->downProgress = 100;
	    if($isSendProgress) {
	    	echo ';'.$this->downProgress;
	    	//ob_flush();
	    	flush();

	    	usleep(100);
	    }

	    //ErrorDebug::write('Done');

	    return true;
	}

	public function customDownStop($cmdType) {
		
		$authData64 = $this->genAuthentication($this->downUser, $this->downPass);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($this->downCtrlId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		$requestUri = '/rest/'.$cmdType.'?device='.urlencode($mac_addr).'&mode=abort';
		$requestData = array('method' => 'POST', 'uri' => $requestUri);
		$pdata = array('from_id' => $this->downUser, 'target_id' => $this->downCtrlId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		if($this->logLevel > 1) {
			$this->logToServer($mac_addr, 'downloading Stop', 'start', '', '', 5);
		}

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg('Communication Error', 'upgrade_stop:'.$httpCode);	
	   		return false;
	    }

	    $response = '';
	    if($this->responseParseObj($this->downCtrlId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg('Fail to stop', '');
	    	return false;
	    }

	    return true;
	}			


	public function customUpdateTwowayData($sipId, $password, $controllerId, $deviceType, $targetAddr) {

		if($deviceType == 'TRF-ZW1') {
			$scenes = $this->customUpdateTRFCmd($sipId, $password, $controllerId, $targetAddr, 'scenes');
			if($scenes === false) {
				return false;
			}

			$rooms = $this->customUpdateTRFCmd($sipId, $password, $controllerId, $targetAddr, 'rooms');
			if($rooms === false) {
				return false;
			}

			foreach($scenes as &$scene) {
			
				$found = false;	
				foreach($rooms as $room){
					if($scene->room == $room->id) {
						$scene->room = $room->name;
						$found = true;
						break;
					}
				}

				if($found == false) {
					$scene->room = '';
				}
			}

			return $scenes;
		}

		return false;
	}

	public function customUpdateTRFCmd($sipId, $password, $controllerId, $targetAddr, $cmdType) {

		$authData64 = $this->genAuthentication($sipId, $password);
		
		$msgId = StringGenerator::gen_msg_id();
		$mac_addr = BStationmanager::getMACFromControllerId($controllerId);
		if($mac_addr === false) {
			$this->setErrMsg('Controller Id Error', '');	    	
			return false;
		}

		/*
		if(strpos($targetAddr, ':') === false) {

			$targetAddr = wordwrap($targetAddr, 2, ":", TRUE);
		}
		*/
		//ErrorDebug::write('target'.$targetAddr);

		switch($cmdType) {
		case 'scenes':
			$requestUri = '/rest/tcl/zw1/scenes?value='.urlencode($targetAddr);
			break;
		case 'rooms':
			$requestUri = '/rest/tcl/zw1/rooms?value='.urlencode($targetAddr);
			break;
		default:
			$this->setErrMsg('Unknown command', '');
			return false;
		}

		$requestData = array('method' => 'GET', 'uri' => $requestUri);
		$pdata = array('from_id' => $sipId, 'target_id' => $controllerId, 'message_id' => $msgId, 'request' => $this->requestEnc($msgId, $requestData));

		$resultData = '';
		$httpCode = $this->curl_req('/sendRequest', 'POST', $authData64, json_encode($pdata), $resultData, -1);
		if($httpCode != 200) {
			$this->setErrMsg("Failed to get ".$cmdType, $cmdType.':'.$httpCode);
			//ErrorDebug::write('err'.$resultData.$httpCode);
	   		return false;
	    }
	    //ErrorDebug::write($resultData.$httpCode);

	    $response = '';
	    if($this->responseParseObj($controllerId, $resultData, $msgId, $response) == false) {
	    	return false;
	    }

	    //ErrorDebug::write(json_encode($response));

	   	if(!isset($response->result) || $response->result !== 'ok') {
	    	$this->setErrMsg("Failed to get twoway data - ".$response->code, '');
	    	return false;
	    }

	    switch($cmdType) {
		case 'scenes':
			if(!isset($response->scenes)) {
		    	$this->setErrMsg('NO SCENES', $reponse->code);
		    	return false;
		    }

		    /*
		    if(count($response->scenes) == 0) {
		    	$response->scenes = array();
		    	$response->scenes[] = (object)array('active' => 0, 'name' => 'test1', 'id' => 1, 'room' => 10);
		    	$response->scenes[] = (object)array('active' => 0, 'name' => 'test2', 'id' => 2, 'room' => 11);
		    }
			*/
			return $response->scenes;
			break;
		case 'rooms':
			if(!isset($response->rooms)) {
		    	$this->setErrMsg('NO ROOMS', $reponse->code);
		    	return false;
		    }
		    /*
		    if(count($response->rooms) == 0) {
		    	$response->rooms = array();
		    	$response->rooms[] = (object)array( 'name' => 'testr1', 'id' => 10, 'section' => 1);
		    	$response->rooms[] = (object)array( 'name' => 'testr2', 'id' => 11, 'section' => 1);
		    
		    }
    		*/
    		return $response->rooms;
			break;
		}

		$this->setErrMsg("Failed to get twoway data - Unknown result", '');
		return false;
	}
}


