/******************************************************************************/
/*                                                                                       */
/* 文件名：                                                 版本  		                     */     	
/*                                                                                       */
/*     kk_scene_handle.c                                V1.0                             */
/*                                                                                       */
/* 功能描述：                                                                                 */    
/*     该文件包含了和场景设置服务相关的代码       							                             */           
/*                                                                                       */
/* 更改记录：                    			                                                 */                    
/*                                   			                                         */
/*     日期         作者         摘要                 				                         */
/*                                                			                             */
/*                                                        			                     */
/*                                                       			                     */
/******************************************************************************/


#include <stdio.h>
#include "kk_tsl_api.h"
#include "kk_dm_mng.h"
#include "kk_scene_handle.h"
#include "kk_scene_db.h"
#include "cJSON.h"
#include <time.h>


extern int g_timezone;
static void kk_scene_send_action_msg(kk_scene_action_info_t *pInfo);
static int kk_scene_update_starttime(kk_scene_timer_list_t *pInfo,int starttime,int current);
static time_t kk_scene_creat_timer_starttime(int week,int starttime,time_t current);
static int kk_scene_parse_repeatday(cJSON *repeatday);
static kk_scene_action_delay_t *p_delay_action_list = NULL;
static kk_scene_embed_delay_t *p_delay_embed_list = NULL;
static kk_scene_timer_list_t *p_scene_timer_list = NULL;
extern uint64_t s_start_time;
static kk_scene_action_t *p_kk_scene_action = NULL;
static kk_scene_ctx_t s_kk_scene_ctx = {NULL};


static int kk_scene_check_value_ex(const char * compareType,const char * compareValue1,const char * compareValue2)
{
	int res = FAIL_RETURN;
	int type = 0;
	int ivalue = 0;
	int itemValue = 0;
	double dvalue = 0;
	double ditemValue = 0;

	if(compareType == NULL || compareValue1 == NULL ||compareValue2 == NULL){
		ERROR_PRINT("[%d]kk_scene_check_value fail!!!\n",__LINE__);
		return INVALID_PARAMETER;
	}
	printf("[%s][%d]compareValue1:%s,compareValue2:%s\n",__FUNCTION__,__LINE__,compareValue1,compareValue2);
	if(!strcmp(compareType,"=") && !strcmp(compareValue1,compareValue2)){
			printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		res = 0;
	}
	else if(!strcmp(compareType,">") && strcmp(compareValue1,compareValue2) > 0){
		res = 0;
	}
	else if(!strcmp(compareType,">=") && strcmp(compareValue1,compareValue2) >= 0){
		res = 0;
	}	
	else if(!strcmp(compareType,"<=") && strcmp(compareValue1,compareValue2) <= 0){
		res = 0;
	}	
	else if(!strcmp(compareType,"<") && strcmp(compareValue1,compareValue2) < 0){
		res = 0;
	}		
	
	
	return res;

}

kk_scene_ctx_t *_kk_scene_get_ctx(void)
{
    return &s_kk_scene_ctx;
}
void _kk_scene_lock(void)
{
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
    if (ctx->mutex) {
        HAL_MutexLock(ctx->mutex);
    }
}

void _kk_scene_unlock(void)
{
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();

    if (ctx->mutex) {
        HAL_MutexUnlock(ctx->mutex);
    }
}



#define KK_DEVICE_TSL_TYPE (0x08)
static kk_tsl_t *s_scene_shadow = NULL;
static int kk_scene_tsl_load(void)
{
	int res = 0;
	char *tsl_str = NULL;
	int heartTime = 0;
	char isDormancyDev = 0;
	tsl_str = kk_load_json("15", KK_DEVICE_TSL_TYPE);
	if(tsl_str != NULL)
	{
		res = kk_tsl_create(tsl_str,strlen(tsl_str),&s_scene_shadow,&heartTime,&isDormancyDev);
		free(tsl_str);
		if(res != 0){
			return FAIL_RETURN;
		}
	}
	return SUCCESS_RETURN;

}
/******************************************************************************/
/* 函 数 名:  kk_scene_timer_check_able                                                     */
/* 描    述:  check定时场景是否有效         										                 */ 	                        
/* 输入参数:  mina_recmsg:	接收到的命令                                      */
/* 返 回 值:  返回'0'表示成功，其它返回值表示出错号                           */
/******************************************************************************/
static int kk_scene_timer_check_able(char *sceneId)
{
	int res = 0;
	int sceneType = 0;
	int enable = 0;
	if(sceneId == NULL){
		return INVALID_PARAMETER;
	}
	res = kk_scene_get_scene_info(sceneId,&sceneType,&enable);
	if(res == SUCCESS_RETURN&&sceneType == DB_SCENETYPE_TIMING && enable == 1){
		return SUCCESS_RETURN;
	}
	return FAIL_RETURN;
}
static int kk_scene_timer_load(void)
{
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	sqlite3_stmt *stmt;
	char *sceneId = NULL;
	char *sqlCmd = "select * from SceneTimerInfo;";
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
	    sceneId = sqlite3_column_text(stmt, DB_SCENETIMER_SCENEID);
		if(kk_scene_timer_check_able(sceneId) == SUCCESS_RETURN){
			int starttime = sqlite3_column_int(stmt, DB_SCENETIMER_TIME);
			int repeatday = sqlite3_column_int(stmt, DB_SCENETIMER_WEEK);
			kk_scene_push_timer_info(starttime,repeatday,sceneId);
		}
	}
	sqlite3_finalize(stmt);
	
	return SUCCESS_RETURN;

}
kk_tsl_t * kk_scene_shadow(void)
{
	return s_scene_shadow;
}


void *kk_scene_yield(void *args)
{
	time_t current_time = 0;
	kk_scene_action_delay_t *actionDelayInfo = NULL;
	kk_scene_action_delay_t *pTemp = NULL;	
	kk_scene_embed_delay_t *embedDelayInfo = NULL;
	kk_scene_embed_delay_t *pTempEmbed = NULL;		
	kk_scene_timer_list_t *scene_timer_list = NULL;
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
    while (1) {
		current_time = HAL_GetTime();
		/****系统起来15s后开始定时处理****/
		if((HAL_UptimeMs() - s_start_time) <= 15000){
			sleep(1);
			continue;
		}
		
		_kk_scene_lock();
		/*处理action delay*/
		actionDelayInfo = p_delay_action_list;
		while(actionDelayInfo){	
			INFO_PRINT("[%s][%d] current_time:%d\n",__FUNCTION__,__LINE__,current_time);
			INFO_PRINT("[%s][%d] actionDelayInfo->starttime:%d\n",__FUNCTION__,__LINE__,actionDelayInfo->starttime);
			if(current_time >= actionDelayInfo->starttime){
				INFO_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
				kk_scene_send_action_msg(actionDelayInfo->action);
				if(actionDelayInfo == p_delay_action_list){
					pTemp = p_delay_action_list;
					p_delay_action_list = p_delay_action_list->next;
					free(pTemp);
					actionDelayInfo = p_delay_action_list;
				}
				else{
					pTemp->next = actionDelayInfo->next;
					free(actionDelayInfo);
					actionDelayInfo = pTemp->next;
				}
			}
			else{
				pTemp= actionDelayInfo;
				actionDelayInfo = actionDelayInfo->next;
			}
		}
		_kk_scene_unlock();
		sleep(1);		
		
		_kk_scene_lock();
		/*处理场景嵌套delay*/
		embedDelayInfo = p_delay_embed_list;
		while(embedDelayInfo){	
			INFO_PRINT("[%s][%d] current_time:%d\n",__FUNCTION__,__LINE__,current_time);
			INFO_PRINT("[%s][%d] embedDelayInfo->starttime:%d\n",__FUNCTION__,__LINE__,embedDelayInfo->starttime);
			if(current_time >= embedDelayInfo->starttime){
				kk_scene_execute_action(embedDelayInfo->executeSceneId);
				if(embedDelayInfo == p_delay_embed_list){
					pTempEmbed = p_delay_embed_list;
					p_delay_embed_list = p_delay_embed_list->next;
					free(pTempEmbed);
					embedDelayInfo = p_delay_embed_list;
				}
				else{
					pTempEmbed->next = embedDelayInfo->next;
					free(embedDelayInfo);
					embedDelayInfo = pTempEmbed->next;
				}
			}
			else{
				pTempEmbed= embedDelayInfo;
				embedDelayInfo = embedDelayInfo->next;
			}
		}
		_kk_scene_unlock();
		sleep(1);
		
		/*******定时模式**********/
		_kk_scene_lock();
		scene_timer_list = p_scene_timer_list;
		while(scene_timer_list){	
			INFO_PRINT("scene_timer_list->starttime:%d\n",scene_timer_list->starttime);
			INFO_PRINT("current_time %d\n",current_time);
			if(scene_timer_list->starttime != 0 && current_time >= scene_timer_list->starttime){
				kk_scene_execute_action(scene_timer_list->sceneId);
				kk_scene_update_starttime(scene_timer_list,scene_timer_list->starttime,current_time);
			}
			scene_timer_list = scene_timer_list->next;
		}
		_kk_scene_unlock();
		sleep(1);
    }

    return NULL;
}

int kk_scene_init(void)
{
	int res = 0;
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();

    /* Create Mutex */
    ctx->mutex = HAL_MutexCreate();
    if (ctx->mutex == NULL) {
        return FAIL_RETURN;
    }

	kk_scene_db_init();

	res = kk_scene_tsl_load();
	if(res != SUCCESS_RETURN){
		ERROR_PRINT("[%s][%d]kk_scene_init FAIL!!!\n",__FUNCTION__,__LINE__);
	}

	kk_scene_timer_load();
    res = pthread_create(&ctx->s_scene_thread, NULL, kk_scene_yield, NULL);
    if (res < 0) {
        ERROR_PRINT("HAL_ThreadCreate mid Failed\n");
        //IOT_Linkkit_Close(mid_ctx->master_devid);
        return -1;
    }	

	return SUCCESS_RETURN;
}

static int kk_scene_action_info_add(kk_scene_action_info_ex_t **head,kk_scene_action_detail_t detail)
{
	int len;
	kk_scene_action_info_ex_t *ptr,*pre;
	
	ptr = pre = *head;

	while(ptr!=NULL){
		pre = ptr;
		ptr = ptr->next;
	}
	ptr = (kk_scene_action_info_ex_t*)malloc(sizeof(kk_scene_action_info_ex_t));
	if(ptr == NULL){
		return FAIL_RETURN;
	}
	//printf("kk_scene_action_add 11 add:%p\n",ptr);

	memset(ptr,0,sizeof(kk_scene_action_info_ex_t));
	memcpy(&ptr->info,&detail,sizeof(kk_scene_action_detail_t));

	if(*head==NULL){
		*head = ptr;
	}else{
		pre->next = ptr;
	}

	return SUCCESS_RETURN;
}

int kk_scene_action_add(const char *gwdeviceCode,const char *sceneId,kk_scene_action_detail_t detail)
{
	int len;
	kk_scene_action_t *ptr,*pre;
	
	ptr = pre = p_kk_scene_action;
	if(gwdeviceCode == NULL || sceneId == NULL){
		return FAIL_RETURN;
	}
	while(ptr!=NULL){
		pre = ptr;
		if(strcmp(ptr->gwdeviceCode,gwdeviceCode) == 0){
			kk_scene_action_info_add(&ptr->actionInfo,detail);
			return SUCCESS_RETURN;
		}
		ptr = ptr->next;
	}
	ptr = (kk_scene_action_t*)malloc(sizeof(kk_scene_action_t));
	if(ptr == NULL){
		return FAIL_RETURN;
	}	
	//printf("kk_scene_action_add add:%p\n",ptr);

	memset(ptr,0,sizeof(kk_scene_action_t));
	memcpy(ptr->gwdeviceCode,gwdeviceCode,strlen(gwdeviceCode));
	memcpy(ptr->sceneId,sceneId,strlen(sceneId));
	kk_scene_action_info_add(&ptr->actionInfo,detail);

	if(p_kk_scene_action==NULL){
		p_kk_scene_action = ptr;
	}else{
		pre->next = ptr;
	}

	return SUCCESS_RETURN;
}

 static int kk_scene_action_free(void)
 {
	 int len;
	 kk_scene_action_t *ptr,*pnext;
	 kk_scene_action_info_ex_t *actionTemp = NULL;
	 ptr = p_kk_scene_action;
	 
	 while(ptr){
		pnext = ptr->next;
		actionTemp = ptr->actionInfo;
		while(actionTemp != NULL){
			kk_scene_action_info_ex_t *ptemp = actionTemp->next;
			//printf("kk_scene_action_free free:%p\n",actionTemp);
			free(actionTemp);
			actionTemp = NULL;
			actionTemp = ptemp;
		}
		//printf("kk_scene_action_free free ptr:%p\n",ptr);
		free(ptr);
		ptr = NULL;
		ptr = pnext;
	 }
	 p_kk_scene_action = NULL;
	 
	 return SUCCESS_RETURN;
 }
 int kk_scene_delete_send_to_gw(const char *sceneId)
 {
	 char gwdevice[][DEVICE_CODE_MAXLEN] = {0};
	 sqlite3_stmt *stmt; 
	 char *sqlCmd = NULL;
	 char *zErrMsg = 0;
	 char *gwdeviceCode = NULL;
	 kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	 int idx=0,num = 0;
	 int res = 0;
 
	 sqlCmd = sqlite3_mprintf("select * from SceneActionInfo WHERE sceneId = '%s'",sceneId);
	 sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
 
 next:	 
	 while(sqlite3_step(stmt) == SQLITE_ROW){		 
		 gwdeviceCode = sqlite3_column_text(stmt,DB_SCENEACTION_GWDEVICECODE);
		 if(kk_subDev_check_scene_support(gwdeviceCode) == 1){
			 for(idx = 0; idx < num;idx++){
				 /*此网关已经发送过*/
				 if(!strcmp(gwdevice[idx],gwdeviceCode)){
					 INFO_PRINT("kk_scene_delete_send_to_gw repeat,ignore!!!\n");
					 goto next;
				 }
			 }
			 memcpy(gwdevice[num],gwdeviceCode,strlen(gwdeviceCode));
			 num++;
			 cJSON *root=cJSON_CreateObject();
			 cJSON_AddStringToObject(root,MSG_SCENE_SCENEID,sceneId);
			 char *out=cJSON_Print(root);
			 res = kk_msg_execute_scene_delete(out,gwdeviceCode);
			 cJSON_Delete(root); 
			 free(out); 		 
		 }
	 }
	 sqlite3_finalize(stmt);
	 sqlite3_free(sqlCmd);
	 return res;
 
 }

 int kk_scene_action_info_send(int isUpdate)
{
	kk_scene_action_t *ptr = p_kk_scene_action;
	kk_scene_action_info_ex_t *ptmp = NULL;
	if(ptr == NULL){
		return FAIL_RETURN;
	}
	while(ptr){
		cJSON *root=cJSON_CreateObject();
		cJSON *array = cJSON_CreateArray(); 	
		cJSON_AddStringToObject(root,MSG_SCENE_SCENEID,ptr->sceneId);
		ptmp = ptr->actionInfo;
		while(ptr->actionInfo){
			cJSON *info=cJSON_CreateObject();
			cJSON_AddStringToObject(info,MSG_DEVICE_CODE_STR,ptr->actionInfo->info.deviceCode);
			cJSON_AddStringToObject(info,MSG_SCENE_PROPERTYNAME,ptr->actionInfo->info.propertyName);
			cJSON_AddStringToObject(info,MSG_SCENE_PROPERTYVALUE,ptr->actionInfo->info.propertyValue);
			cJSON_AddNumberToObject(info,MSG_SCENE_DELAY,ptr->actionInfo->info.delay);
			cJSON_AddNumberToObject(info,MSG_SCENE_EPNUM,ptr->actionInfo->info.epNum);
			cJSON_AddItemToArray(array,info);
			ptr->actionInfo = ptr->actionInfo->next;
		}
		ptr->actionInfo = ptmp;
		cJSON_AddItemToObject(root,MSG_SCENE_ACTIONS,array);
		char *out=cJSON_Print(root);
		//printf("out:%s\n",out);
		kk_msg_execute_scene_set(out,ptr->gwdeviceCode,isUpdate);
		cJSON_Delete(root); 
		free(out);
		ptr = ptr->next;
	}

	kk_scene_action_free();
	return SUCCESS_RETURN;
}

 int kk_scene_muticontrol_info_send(cJSON* action,const char *gwdeviceCode,const char *sceneId)
{
	if(action == NULL || gwdeviceCode == NULL || sceneId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *root=cJSON_CreateObject();	
	cJSON_AddStringToObject(root,MSG_SCENE_SCENEID,sceneId);
	cJSON_AddStringToObject(root,MSG_SCENE_ACTIONS,action->valuestring);	
	char *out=cJSON_Print(root);
	printf("kk_scene_muticontrol_info_send:%s\n",out);
	kk_msg_execute_scene_set(out,gwdeviceCode);
	cJSON_Delete(root); 
	free(out);
	return SUCCESS_RETURN;
}

static int kk_scene_parse_trigger_detail(const char *type,const cJSON *item,const char *sceneId)
{
	int res = FAIL_RETURN;
	if(type == NULL || item == NULL || sceneId == NULL){
		return INVALID_PARAMETER;
	}
	cJSON *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR);
	if(deviceCode == NULL) return FAIL_RETURN;	
	cJSON *epNum = cJSON_GetObjectItem(item,MSG_SCENE_EPNUM);
	if(epNum == NULL) return FAIL_RETURN;		
	cJSON *propertyName = cJSON_GetObjectItem(item,MSG_SCENE_PROPERTYNAME);
	if(propertyName == NULL) return FAIL_RETURN;
	cJSON *compareType = cJSON_GetObjectItem(item,MSG_SCENE_COMPARETYPE);
	if(compareType == NULL) return FAIL_RETURN; 	
	cJSON *compareValue = cJSON_GetObjectItem(item,MSG_SCENE_COMPAREVALUE);
	if(compareValue == NULL) return FAIL_RETURN;	
	res = kk_scene_insert_scene_trigger(type,deviceCode->valuestring,deviceCode->valueint,
			propertyName->valuestring,compareType->valuestring,compareValue->valuestring,sceneId);
	if(res != SUCCESS_RETURN){
		ERROR_PRINT("kk_scene_parse_scene_trigger fail!!!\n");
	}
	return res;

}

int kk_scene_parse_scene_trigger(const cJSON* str,const char *sceneId)
{
	int res = 0;
	int weekflag = 0;
	if(str == NULL || sceneId == NULL){
		return INVALID_PARAMETER;
	}

	cJSON *triggers = cJSON_GetObjectItem(str,MSG_SCENE_TRIGGERS);
	if(triggers == NULL) return FAIL_RETURN;	
	cJSON *items = cJSON_GetObjectItem(triggers,MSG_SCENE_ITEMS);
	if(items == NULL) return FAIL_RETURN;
	cJSON * item = items->child;
	while(item != NULL){
		cJSON *type = cJSON_GetObjectItem(item,MSG_SCENE_TYPE);
		if(type == NULL) return FAIL_RETURN;
		if(!strcmp("trigger/thing/property",type->valuestring)){
			res = kk_scene_parse_trigger_detail(type->valuestring,item,sceneId);
			if(res != SUCCESS_RETURN){
				ERROR_PRINT("kk_scene_parse_scene_trigger fail!!!\n");
				return res;
			}
		}
		else if(!strcmp("trigger/timing",type->valuestring)){
			cJSON *week = cJSON_GetObjectItem(item,MSG_SCENE_WEEK);
			if(week == NULL) return FAIL_RETURN;
			weekflag = kk_scene_parse_repeatday(week);
			cJSON *time = cJSON_GetObjectItem(item,MSG_SCENE_TIME);
			if(time == NULL) return FAIL_RETURN;
			time_t current = HAL_GetTime();			
			time_t newStart = kk_scene_creat_timer_starttime(weekflag,atoi(time->valuestring),current);
			kk_scene_insert_scene_timer(newStart,weekflag,sceneId);
			kk_scene_push_timer_info(newStart,weekflag,sceneId);
		}
		item = item->next;	
	}
	INFO_PRINT("kk_scene_parse_scene_trigger success!!!\n");
	return SUCCESS_RETURN;
}
static int kk_scene_parse_repeatday(cJSON *repeatday)
{
	/***weekflag 01111111  ---> week 7 6 5 4 3 2 1*/
	char weekflag = 0;
	int iCnt = 0;
	if(repeatday == NULL){
		return INVALID_PARAMETER;
	}
	int  array_size = cJSON_GetArraySize (repeatday);
	INFO_PRINT("array_size:%d\n",array_size);
	if(array_size == 0){
		weekflag = 0;
	}else{
		for(iCnt = 0; iCnt < array_size; iCnt++){
			cJSON * pSub = cJSON_GetArrayItem(repeatday, iCnt);
			if(pSub != NULL){
				weekflag = weekflag|(1<<(pSub->valueint-1));
			}
		}
	}
	INFO_PRINT("kk_scene_parse_repeatday weekflag:%d!!!\n",weekflag);
	return weekflag;
	
}
void kk_scene_remove_timer_info(char *sceneId)
{
	kk_scene_timer_list_t *ptr = NULL,*ptemp = NULL;
	_kk_scene_lock();
	ptemp = ptr = p_scene_timer_list;
	while(ptr){ 		
		if(!strcmp(ptr->sceneId,sceneId)){
			if(ptr == p_scene_timer_list){
				ptemp = p_scene_timer_list;
				p_scene_timer_list = p_scene_timer_list->next;
				free(ptemp);
				ptr = p_scene_timer_list;
			}
			else{
				ptemp->next = ptr->next;
				free(ptr);
				ptr = ptemp->next;
			}
		}
		else{
			ptemp= ptr;
			ptr = ptr->next;
		}
	}
	_kk_scene_unlock();

}
int kk_scene_push_timer_info(time_t starttime,int repeatday,char *sceneId)
{
	kk_scene_timer_list_t *ptr = NULL,*ptemp = NULL;
	if(sceneId == NULL){
		return INVALID_PARAMETER;
	}
	_kk_scene_lock();
	ptemp = ptr = p_scene_timer_list;
	while(ptr){
		ptemp = ptr;
		ptr = ptr->next;
	}		
	ptr = malloc(sizeof(kk_scene_timer_list_t));
	if(ptr == NULL) {
		_kk_scene_unlock();		
		return MEMORY_NOT_ENOUGH;
	}
	memset(ptr,0x0,sizeof(kk_scene_timer_list_t));
	ptr->starttime = starttime;
	ptr->repeatday = repeatday;
	memcpy(ptr->sceneId,sceneId,strlen(sceneId));
	if(p_scene_timer_list == NULL){
		p_scene_timer_list = ptr;
	}else{
		ptemp->next = ptr;
	}
	_kk_scene_unlock();
	INFO_PRINT("kk_scene_push_timer_info called!!!\n");
	return SUCCESS_RETURN;
}

int kk_scene_parse_scene_condition(const cJSON* str,const char *sceneId)
{
	char weekflag = 0;
	int res = 0;
	if(str == NULL || sceneId == NULL){
		ERROR_PRINT("kk_scene_parse_scene_condition failed\n");
		return INVALID_PARAMETER;
	}

	cJSON *conditon = cJSON_GetObjectItem(str,MSG_SCENE_CONDITIONS);
	if(conditon == NULL) return FAIL_RETURN;	

	cJSON *items = cJSON_GetObjectItem(conditon,MSG_SCENE_ITEMS);
	if(items == NULL) return FAIL_RETURN;
	cJSON * item = items->child;
	while(item != NULL){
		cJSON *type = cJSON_GetObjectItem(item,MSG_SCENE_TYPE);
		if(type == NULL) return FAIL_RETURN;
		if(!strcmp("condition/timeRange",type->valuestring)){
			cJSON *startTime = cJSON_GetObjectItem(item,MSG_SCENE_STARTTIME);
			if(startTime == NULL) return FAIL_RETURN;
			cJSON *endTime = cJSON_GetObjectItem(item,MSG_SCENE_ENDTIME);
			if(endTime == NULL) return FAIL_RETURN;	
			cJSON *repeatday = cJSON_GetObjectItem(item,MSG_SCENE_REPEATDAYS);
			if(repeatday == NULL) return FAIL_RETURN;
			weekflag = kk_scene_parse_repeatday(repeatday);			
			//kk_scene_push_timer_info(startTime->valueint,endTime->valueint,weekflag,sceneId);
			res = kk_scene_insert_scene_condition(type->valuestring,startTime->valueint,endTime->valueint,
					0,weekflag,sceneId);
			if(res != SUCCESS_RETURN){
				INFO_PRINT("kk_scene_insert_scene_condition fail!!!\n");
				return res;
			}			
		}
		else if(!strcmp("condition/property",type->valuestring)){
			kk_scene_parse_trigger_detail(type->valuestring,item,sceneId);
		}
		else{
			INFO_PRINT("kk_scene_parse_scene_condition wrong type!!!\n");
		}
		item = item->next;
	}
	INFO_PRINT("kk_scene_parse_scene_condition success!!!\n");
	return SUCCESS_RETURN;
}

int kk_scene_parse_scene_action(const cJSON* str,const char *sceneId,int isUpdate)
{
	int res = 0;
	int propertySetType = 0;
    dm_mgr_dev_node_t *node = NULL;	
	if(str == NULL || sceneId == NULL){
		ERROR_PRINT("kk_scene_parse_scene_action failed\n");
		return INVALID_PARAMETER;
	}

	cJSON *action = cJSON_GetObjectItem(str,MSG_SCENE_ACTIONS);
	if(action == NULL) return FAIL_RETURN;
	cJSON * item = action->child;
	while(item != NULL){
		cJSON *type = cJSON_GetObjectItem(item,MSG_SCENE_TYPE);
		if(type == NULL) return FAIL_RETURN;
		/*内嵌场景设置*/
		if(type->valuestring == "action/scene")
		{
			cJSON *delay = cJSON_GetObjectItem(item,MSG_SCENE_DELAY);
			if(delay == NULL) return FAIL_RETURN;
			cJSON *exeucteSceneId = cJSON_GetObjectItem(item,MSG_SCENE_SCENEID);
			if(exeucteSceneId == NULL) return FAIL_RETURN;		
			kk_scene_insert_scene_embed(delay->valueint,exeucteSceneId->valuestring,sceneId);
		}
		else
		{
			propertySetType = 1;
			cJSON *propertyName = cJSON_GetObjectItem(item,MSG_SCENE_PROPERTYNAME);
			if(propertyName == NULL) return FAIL_RETURN;
			cJSON *propertyValue = cJSON_GetObjectItem(item,MSG_SCENE_PROPERTYVALUE);
			if(propertyValue == NULL) return FAIL_RETURN;	
			cJSON *productType = cJSON_GetObjectItem(item,MSG_PRODUCT_TYPE_STR);
			if(productType != NULL){
				kk_subDev_set_action_by_productType(productType->valuestring,sceneId,propertyName->valuestring,
									propertyValue->valuestring,type->valuestring);
			}
			else{
			
				cJSON *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR);
				if(deviceCode == NULL) return FAIL_RETURN;	
				cJSON *epNum = cJSON_GetObjectItem(item,MSG_SCENE_EPNUM);
				if(epNum == NULL) return FAIL_RETURN;	
				epNum = epNum->valueint;
				cJSON *delay = cJSON_GetObjectItem(item,MSG_SCENE_DELAY);
				if(delay == NULL) return FAIL_RETURN;
				delay = delay->valueint;
				res = dm_mgr_get_device_by_devicecode(deviceCode->valuestring,&node);
			    if (res != SUCCESS_RETURN) {
					item = item->next;
			        continue;
			    }		
				if(kk_subDev_check_scene_support(node->fatherDeviceCode) == 1){
					kk_scene_action_detail_t info = {0};
					memcpy(info.deviceCode,node->deviceCode,strlen(node->deviceCode));
					memcpy(info.propertyName,propertyName->valuestring,strlen(propertyName->valuestring));
					memcpy(info.propertyValue,propertyValue->valuestring,strlen(propertyValue->valuestring));
					info.epNum = epNum;
					info.delay = delay;
					kk_scene_action_add(node->fatherDeviceCode,sceneId,info);

				}
				res = kk_scene_insert_scene_action(type->valuestring,node->deviceCode,epNum,
						propertyName->valuestring,propertyValue->valuestring,delay,sceneId,node->fatherDeviceCode);
				if(res != SUCCESS_RETURN){
					INFO_PRINT("kk_scene_insert_scene_action fail!!!\n");
					return res;
				}			
			}
		}
		item = item->next;
	}
	if(propertySetType){
		kk_scene_action_info_send(isUpdate);
	}
	return SUCCESS_RETURN;
}

int kk_scene_parse_scene_muticontrol(const cJSON* str,const char *sceneId)
{
	int res = 0;
    dm_mgr_dev_node_t *node = NULL;	
	if(str == NULL){
		ERROR_PRINT("kk_scene_parse_scene_muticontrol failed\n");
		return INVALID_PARAMETER;
	}

	cJSON *action = cJSON_GetObjectItem(str,MSG_SCENE_ACTIONS);
	if(action == NULL) return FAIL_RETURN;
	cJSON * item = action->child;
	while(item != NULL){
		cJSON *type = cJSON_GetObjectItem(item,MSG_SCENE_TYPE);
		if(type == NULL) return FAIL_RETURN;	
		if(!strcmp(type->valuestring,"action/thing/group")){
			cJSON *deviceCode = cJSON_GetObjectItem(item,MSG_DEVICE_CODE_STR);
			if(deviceCode == NULL) return FAIL_RETURN;
			res = dm_mgr_get_device_by_devicecode(deviceCode->valuestring,&node);
		    if (res != SUCCESS_RETURN) {
				item = item->next;
		        continue;
		    }
			break;
		}

		item = item->next;
	}
	kk_scene_muticontrol_info_send(action,node->fatherDeviceCode,sceneId);
	return SUCCESS_RETURN;
}


int kk_scene_parse_addscene(const cJSON* args,char *sceneId,int isUpdate)
{
	int res = 0;

	if(args == NULL||sceneId == NULL){
		ERROR_PRINT("[%d]kk_scene_parse_addscene fail!!!\n",__LINE__);
		return INVALID_PARAMETER;
	}
	
	cJSON *name = cJSON_GetObjectItem(args,MSG_SCENE_NAME);
	if(name == NULL) return FAIL_RETURN;
	cJSON *sceneType = cJSON_GetObjectItem(args,MSG_SCENE_SCENCTYPE);
	if(sceneType == NULL) return FAIL_RETURN;
	cJSON *enable = cJSON_GetObjectItem(args,MSG_SCENE_ENABLE);
	if(enable == NULL) return FAIL_RETURN;	
	if(!isUpdate){
		HAL_GetTime_s(sceneId);//use time to create the sceneId
	}
	/*多控直接下发给网关处理*/
	if(enable->valueint == 1 && sceneType->valueint ==  DB_SCENETYPE_MUTICONTROL){
		kk_scene_parse_scene_muticontrol(args,sceneId);
	}
	else{
		res = kk_scene_insert_scene_info(name->valuestring,sceneType->valueint,enable->valueint,sceneId);
		if(res != SUCCESS_RETURN){
			INFO_PRINT("kk_scene_insert_scene_info fail!!!\n");
			return res;
		}	

		res = kk_scene_parse_scene_trigger(args,sceneId);
		if(res != SUCCESS_RETURN){
			ERROR_PRINT("kk_scene_parse_scene_trigger failed\n");
			return FAIL_RETURN;
		}
		res = kk_scene_parse_scene_condition(args,sceneId);
		if(res != SUCCESS_RETURN){
			ERROR_PRINT("kk_scene_parse_scene_condition failed\n");
			//return FAIL_RETURN;
		}	

		res = kk_scene_parse_scene_action(args,sceneId,isUpdate);
		if(res != SUCCESS_RETURN){
			ERROR_PRINT("kk_scene_parse_scene_action failed\n");
			return FAIL_RETURN;
		}		
	}
	return SUCCESS_RETURN;

}
static void kk_scene_delete(char* sceneId)
{
	kk_scene_remove_timer_info(sceneId);
	kk_scene_delete_scene_timing(sceneId);	
	kk_scene_delete_scene_info(sceneId);
	kk_scene_delete_scene_trigger(sceneId);
	kk_scene_delete_scene_condition(sceneId);	
	kk_scene_delete_scene_action(sceneId);
}
int kk_scene_parse_updatescene(const cJSON* arg,char *sceneId)
{

	if(arg == NULL||sceneId == NULL){
		ERROR_PRINT("[%d]kk_scene_parse_addscene fail!!!\n",__LINE__);
		return INVALID_PARAMETER;
	}
	kk_scene_delete(sceneId);
	return kk_scene_parse_addscene(arg,sceneId,1);
}
int kk_scene_parse_deletescene(char *sceneId)
{

	if(sceneId == NULL){
		ERROR_PRINT("[%d]kk_scene_parse_deletescene fail!!!\n",__LINE__);
		return INVALID_PARAMETER;
	}
	kk_scene_delete(sceneId);	
	return SUCCESS_RETURN;
}

int kk_scene_get_scene_info(const char* sceneId,int *sceneType,int *enable)
{	
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	sqlite3_stmt *stmt;
	int res = FAIL_RETURN;
	char *sqlCmd = NULL;
	sqlCmd = sqlite3_mprintf("select * from SceneInfo WHERE sceneId = '%s'",sceneId);	
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
	    *sceneType = sqlite3_column_int(stmt, DB_SCENEINFO_SCENETYPE);
		*enable = sqlite3_column_int(stmt, DB_SCENEINFO_ENABLE);
		res =  SUCCESS_RETURN;
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);	
	return res;
}
static char kk_scene_date_to_week(time_t t)
{
	struct tm *p = localtime(&t);  
	INFO_PRINT("kk_scene_date_to_week t p->tm_wday:%d\n",p->tm_wday);
    return ((p->tm_wday == 0)?7 : p->tm_wday);
}
static int kk_scene_update_starttime(kk_scene_timer_list_t *pInfo,int starttime,int current)
{
	char curWeek = 0;
	char i = 0;
	if(pInfo == NULL){
		return FAIL_RETURN;
	}
	/*only support once*/
	if(pInfo->repeatday == 0){
		pInfo->starttime = 0;
		kk_scene_update_scene_enable(0,pInfo->sceneId);
		return SUCCESS_RETURN;
	}else{
		curWeek = kk_scene_date_to_week(current);
		for(i = 1; i < 8; i++){
			if(curWeek == 0x40){ //0x40 ==>01000000 ,sunday
				curWeek = curWeek>>6;
			}
			else{
				curWeek = curWeek<<1;
			}
			if(curWeek & pInfo->repeatday){
				pInfo->starttime = pInfo->starttime + 86400*i;
				return SUCCESS_RETURN;
			}			
		}
	
	}
	return FAIL_RETURN;

}

static time_t kk_scene_creat_new_starttime(time_t starttime,time_t current)
{
	int hour,min,sec;
	time_t newTime = 0;

	printf("[%d]startTime :%d\n",__LINE__,starttime);

	hour = starttime/3600;
	min = starttime%3600/60;

	printf("[hour:%d][min:%d]\n",hour,min);
	struct tm *c = localtime(&current); 
	c->tm_hour = hour;
	c->tm_min = min;
	c->tm_sec = 0;
	newTime = mktime(c);
	INFO_PRINT("kk_scene_creat_new_starttime:%ld\n",newTime);
    return newTime;
}
static time_t kk_scene_creat_timer_starttime(int week,int starttime,time_t current)
{
	int hour,min,sec;
	time_t newTime = 0;
	char curWeek = 0;
	int startNew = 0;
	int i = 0;
	curWeek = kk_scene_date_to_week(current);
	startNew = starttime + g_timezone*3600;
	startNew = (startNew - 86400) >= 0?(startNew - 86400) : startNew;	
	INFO_PRINT("kk_scene_creat_timer_starttime:%d\n",startNew);
	
	/*today is not repeat day*/
	if((week > 0)&&(!(week &(1<<(curWeek-1)))))
	{
		for(i = 1; i < 8; i++){
			if(curWeek == 0x40){ //0x40 ==>01000000 ,sunday
				curWeek = curWeek>>6;
			}
			else{
				curWeek = curWeek<<1;
			}
			if(curWeek & week){
				newTime = current + 86400*i;
				return kk_scene_creat_new_starttime(startNew,newTime);
			}			
		}
	}
	else
	{
		return kk_scene_creat_new_starttime(startNew,current);
	}
}

int kk_scene_check_trigger_condition(const char *sceneId)
{
	int res = FAIL_RETURN;
	char *sqlCmd = NULL;
	char *pdeviceCode = NULL;
	char *identifier = NULL;
	char *compareType = NULL;
	char *compareValue = NULL;
	int propertyValueType = 0;
	int conditionFlag = 0;
	sqlite3_stmt *stmt;	
	char currentValue[64] = {0};	
	dm_mgr_dev_node_t *node = NULL;	
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();

	sqlCmd = sqlite3_mprintf("select * from SceneTriggerInfo WHERE sceneId = '%s' and type = '%s'",sceneId,"condition/property");
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		conditionFlag = 1;
		
	    pdeviceCode = sqlite3_column_text(stmt, DB_SCENETRIGGER_DEVICECODE);
		identifier = sqlite3_column_text(stmt,DB_SCENETRIGGER_PROPERTYNAME);
		compareType = sqlite3_column_text(stmt,DB_SCENETRIGGER_COMPARETYPE);
		compareValue = sqlite3_column_text(stmt,DB_SCENETRIGGER_COMPAREVALUE);

		kk_property_db_get_value_directly(pdeviceCode,identifier,currentValue);	
		printf("currentValue:%s\n",currentValue);
		res = kk_scene_check_value_ex(compareType,currentValue,compareValue);
		INFO_PRINT("kk_scene_check_value_ex:res:%d\n",res);		
		if(res != 0){
			break;
		}

	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);

	/*如果没有设置条件，直接return success*/
	if(conditionFlag == 0){
		res =  SUCCESS_RETURN;
	}
	INFO_PRINT("kk_scene_check_trigger_condition:res:%d\n",res);	
	return res;

}

int kk_scene_check_condition(const char *sceneId)
{
	int res = FAIL_RETURN;
	char *sqlCmd = NULL;
	char curWeek = 0;
	char repeatday = 0;
	time_t startTime = 0,startTime_m = 0;
	time_t endTime = 0,endTime_m = 0;
	int duration = 0;
	int crossDay = 0;
	int conditionFlag = 0;
	sqlite3_stmt *stmt;	
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	time_t current = HAL_GetTime();
	curWeek = kk_scene_date_to_week(current);

	sqlCmd = sqlite3_mprintf("select * from SceneConditionInfo WHERE sceneId = '%s'",sceneId);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		conditionFlag = 1;
	    repeatday = sqlite3_column_int(stmt, DB_SCENECONDITION_REPEATDAY);
		startTime = sqlite3_column_int(stmt, DB_SCENECONDITION_STARTTIME);
		endTime = sqlite3_column_int(stmt, DB_SCENECONDITION_ENDTIME);
		//crossDay = sqlite3_column_int(stmt, DB_SCENECONDITION_CROSSDAY);
		startTime = startTime + g_timezone*3600;
		startTime = (startTime - 86400) >= 0?(startTime - 86400) : startTime;
		endTime = endTime + g_timezone*3600;
		endTime = (endTime - 86400) >= 0?(endTime - 86400) : endTime;

		duration = endTime - startTime;
		startTime_m = kk_scene_creat_new_starttime(startTime,current);
		INFO_PRINT("current:%ld,startTime_m:%ld,repeatday:%d\n",current,startTime_m,repeatday);
		/********check today is one of repeatday**************/
		if((repeatday > 0) && (repeatday &(1<<(curWeek-1)))){	
			if(crossDay && current < startTime_m){
				/*跨天处理，判断当前时间是否在上一天的结束时间内*/
				if(current <= (startTime_m + duration - 86400)){
					res =  SUCCESS_RETURN;
				}
			}
			else if(current >= startTime_m && current <= (startTime_m + duration)){
				res =  SUCCESS_RETURN;
			}
			else{
				INFO_PRINT("time not match current:%ld,startTime_m:%ld,repeatday:%d\n",current,startTime_m,repeatday);
			}
		}
		else if((repeatday > 0)&&(!(repeatday &(1<<(curWeek-1))))){
			/*跨天处理,获取前一天的星期*/
			if(crossDay == 1){
		    	curWeek = (curWeek - 1) == 0? 7:(curWeek - 1);
				/*前一天的星期必须要在重复星期内*/
				if(repeatday &(1<<(curWeek-1))){
					if(current <= (startTime_m + duration - 86400)){
						res =  SUCCESS_RETURN;
					}
				}
			}
		}
		else{
			if(current >= startTime_m && current <= (startTime_m + duration)){
				res =  SUCCESS_RETURN;
			}
			else
			{
				INFO_PRINT("time not match current:%ld,startTime_m:%ld\n",current,startTime_m);
			}
		}
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);

	/*如果没有设置条件，直接return success*/
	if(conditionFlag == 0){
		res =  SUCCESS_RETURN;
	}
	INFO_PRINT("kk_scene_check_condition:res:%d\n",res);
	return res;

}

static int kk_scene_check_value(const char * compareType,const char * compareValue,cJSON *item,int valueType)
{
	int res = FAIL_RETURN;
	int type = 0;
	int ivalue = 0;
	int itemValue = 0;
	double dvalue = 0;
	double ditemValue = 0;

	if(compareType == NULL || compareValue == NULL ||item == NULL){
		ERROR_PRINT("[%d]kk_scene_check_value fail!!!\n",__LINE__);
		return INVALID_PARAMETER;
	}
	switch(valueType){
		case KK_TSL_DATA_TYPE_INT:
		case KK_TSL_DATA_TYPE_ENUM:
		case KK_TSL_DATA_TYPE_BOOL:
			ivalue = atoi(compareValue);
		    itemValue = item->valueint;
			break;
		case KK_TSL_DATA_TYPE_FLOAT:
		case KK_TSL_DATA_TYPE_DOUBLE:
			dvalue = atof(compareValue);
			ditemValue = item->valuedouble;
			type = 1;
			break;	
		case KK_TSL_DATA_TYPE_TEXT:
		case KK_TSL_DATA_TYPE_DATE:
			type = 2;//字串
			break;
	}
	if(type == 2){
		if(!strcmp(compareType,"=") && !strcmp(compareValue,item->valuestring)){
			res = 0;
		}
		else if(!strcmp(compareType,">") && strcmp(item->valuestring,compareValue) > 0){
			res = 0;
		}
		else if(!strcmp(compareType,">=") && strcmp(item->valuestring,compareValue) >= 0){
			res = 0;
		}	
		else if(!strcmp(compareType,"<=") && strcmp(item->valuestring,compareValue) <= 0){
			res = 0;
		}	
		else if(!strcmp(compareType,"<") && strcmp(item->valuestring,compareValue) < 0){
			res = 0;
		}		
	}
	else if(type == 1){
		if(!strcmp(compareType,"=")){
			if(ditemValue == dvalue) 
				res = 0;
		}
		else if(!strcmp(compareType,">")){
			if(ditemValue > dvalue) 
				res = 0;
		}
		else if(!strcmp(compareType,">=")){
			if(ditemValue >= dvalue) 
				res = 0;
		}
		else if(!strcmp(compareType,"<=")){
			if(ditemValue <= dvalue) 
				res = 0;
		}
		else if(!strcmp(compareType,"<")){
			if(ditemValue < dvalue) 
				res = 0;
		}	
	}
	else{
		if(!strcmp(compareType,"=")){
			if(itemValue == ivalue) 
				res = 0;
		}
		else if(!strcmp(compareType,">")){
			if(itemValue > ivalue) 
				res = 0;
		}
		else if(!strcmp(compareType,">=")){
			if(itemValue >= ivalue) 
				res = 0;
		}
		else if(!strcmp(compareType,"<=")){
			if(itemValue <= ivalue) 
				res = 0;
		}
		else if(!strcmp(compareType,"<")){
			if(itemValue < ivalue) 
				res = 0;
		}	

	}
	return res;

}
static void kk_scene_send_action_msg(kk_scene_action_info_t *pInfo)
{
	int ivalue = 0;
	double dvalue = 0; 
	int valueType = 0;
	if(pInfo == NULL){
		return;
	}
	cJSON *root=cJSON_CreateObject();	

	valueType = kk_dm_get_property_type(pInfo->deviceCode,pInfo->propertyName);
	if(valueType < 0){
		ERROR_PRINT("[%d]kk_scene_send_action_msg valueType < 0!!!\n",__LINE__);
		free(pInfo);
		return 0;
	}
	switch(valueType){
		case KK_TSL_DATA_TYPE_INT:
		case KK_TSL_DATA_TYPE_ENUM:
		case KK_TSL_DATA_TYPE_BOOL:
			ivalue = atoi(pInfo->propertyValue);
			cJSON_AddNumberToObject(root,pInfo->propertyName,ivalue);
			break;
		case KK_TSL_DATA_TYPE_FLOAT:
		case KK_TSL_DATA_TYPE_DOUBLE:
			dvalue = atof(pInfo->propertyValue);
			cJSON_AddNumberToObject(root,pInfo->propertyName,dvalue);
			break;
		case KK_TSL_DATA_TYPE_TEXT:
		case KK_TSL_DATA_TYPE_DATE:
			cJSON_AddStringToObject(root,pInfo->propertyName,pInfo->propertyValue);
			break;
	}
	
	char *out=cJSON_Print(root);
	kk_msg_execute_property_set(pInfo->productCode,pInfo->deviceCode,out,pInfo->fatherdeviceCode);
	cJSON_Delete(root); 
	free(out);
	free(pInfo);
	return;
}
static int kk_scene_push_action_list(kk_scene_action_info_t *actionInfo,int delay)
{
	kk_scene_action_delay_t *ptr = NULL,*ptemp = NULL;
	if(actionInfo == NULL){
		return INVALID_PARAMETER;
	}
	ptemp = ptr = p_delay_action_list;
	while(ptr){
		ptemp = ptr;
		ptr = ptr->next;
	}		
	ptr = malloc(sizeof(kk_scene_action_delay_t));
	if(ptr == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(ptr,0x0,sizeof(kk_scene_action_delay_t));
	ptr->starttime = HAL_GetTime()+delay;
	ptr->action = actionInfo;
	if(p_delay_action_list == NULL){
		p_delay_action_list = ptr;
	}else{
		ptemp->next = ptr;
	}
	return SUCCESS_RETURN;

}
static int kk_scene_start_action(const char *deviceCode,const char *propertyName,const char *valueS,int delay)
{
	int res = 0;
	
	INFO_PRINT("[%s][%d]kk_scene_start_action called\n",__FUNCTION__,__LINE__);
	dm_mgr_dev_node_t *node = NULL;
	kk_scene_action_info_t *actionInfo = NULL;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	
	if(deviceCode == NULL || propertyName == NULL || valueS == NULL){
		ERROR_PRINT("[%d]kk_scene_send_action fail!!!\n",__LINE__);
		return INVALID_PARAMETER;
	}
	res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
	actionInfo = malloc(sizeof(kk_scene_action_info_t));
	if(actionInfo == NULL) {
		return MEMORY_NOT_ENOUGH;	
	}
	memset(actionInfo,0x0,sizeof(kk_scene_action_info_t));
	memcpy(actionInfo->deviceCode,deviceCode,strlen(deviceCode));
	memcpy(actionInfo->productCode,node->productCode,strlen(node->productCode));
	memcpy(actionInfo->fatherdeviceCode,node->fatherDeviceCode,strlen(node->fatherDeviceCode));
	memcpy(actionInfo->propertyName,propertyName,strlen(propertyName));	
	memcpy(actionInfo->propertyValue,valueS,strlen(valueS));		
	if(delay == 0){
		kk_scene_send_action_msg(actionInfo);
	}else{
		INFO_PRINT("[%s][%d]delay:%d\n",__FUNCTION__,__LINE__,delay);
		kk_scene_push_action_list(actionInfo,delay);
	}
	return SUCCESS_RETURN;


}
int kk_scene_execute_action(const char* sceneId)
{
	int res = FAIL_RETURN;
	char *deviceCode = NULL;
	char *propertyName = NULL;
	char *propertyValue = NULL;	
	char *gwdeviceCode = NULL;
	int delay = 0;
	char *sqlCmd = NULL;
	char gwdevice[][DEVICE_CODE_MAXLEN] = {0};
	int idx=0,num = 0;
	sqlite3_stmt *stmt;	
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	INFO_PRINT("[%s][%d] kk_scene_execute_action now!!!\n",__FUNCTION__,__LINE__);
	sqlCmd = sqlite3_mprintf("select * from SceneActionInfo WHERE sceneId = '%s'",sceneId);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
next:		
	while(sqlite3_step(stmt) == SQLITE_ROW){	
	    deviceCode = sqlite3_column_text(stmt, DB_SCENEACTION_DEVICECODE);
		propertyName = sqlite3_column_text(stmt,DB_SCENEACTION_PROPERTYNAME);
		propertyValue = sqlite3_column_text(stmt,DB_SCENEACTION_PROPERTYVALUE);
		delay = sqlite3_column_int(stmt,DB_SCENEACTION_DELAY);
		gwdeviceCode = sqlite3_column_text(stmt,DB_SCENEACTION_GWDEVICECODE);
		if(kk_subDev_check_scene_support(gwdeviceCode) == 1){
			for(idx = 0; idx < num;idx++){
				if(!strcmp(gwdevice[idx],gwdeviceCode)){
					goto next;
				}
			}
			memcpy(gwdevice[num],gwdeviceCode,strlen(gwdeviceCode));
			num++;
			cJSON *root=cJSON_CreateObject();
			cJSON_AddStringToObject(root,MSG_SCENE_SCENEID,sceneId);
			char *out=cJSON_Print(root);
			res = kk_msg_execute_scene_action(out,gwdeviceCode);
			cJSON_Delete(root); 
			free(out);			
		}
		else{
			res = kk_scene_start_action(deviceCode,propertyName,propertyValue,delay);
		}
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	return res;

}
static int kk_scene_push_embed_list(int delay,const char* sceneId)
{
	if(sceneId == NULL){
		return INVALID_PARAMETER;
	}
	kk_scene_embed_delay_t *ptr = NULL,*ptemp = NULL;
	_kk_scene_lock();
	ptemp = ptr = p_delay_embed_list;
	while(ptr){
		ptemp = ptr;
		ptr = ptr->next;
	}		
	ptr = malloc(sizeof(kk_scene_embed_delay_t));
	if(ptr == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(ptr,0x0,sizeof(kk_scene_embed_delay_t));
	ptr->starttime = HAL_GetTime()+delay;
	memcpy(ptr->executeSceneId,sceneId,strlen(sceneId));
	if(p_delay_embed_list == NULL){
		p_delay_embed_list = ptr;
	}else{
		ptemp->next = ptr;
	}
	_kk_scene_unlock();
	return SUCCESS_RETURN;

}
static int kk_scene_embed_find(const char *sceneId)
{
	int find = 0;
	char *sqlCmd = NULL;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	sqlite3_stmt *stmt;	
	int delay = 0;
	char *executeSceneId = NULL;
	if(sceneId == NULL){
		return INVALID_PARAMETER;
	}
	sqlCmd = sqlite3_mprintf("select * from SceneEmbedInfo WHERE sceneId= '%s'",sceneId);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);	
	while(sqlite3_step(stmt) == SQLITE_ROW){
		find = 1;
		delay = sqlite3_column_int(stmt,DB_SCENEEMBED_WEEK);
		executeSceneId = sqlite3_column_text(stmt,DB_SCENEEMBED_EXECUTESCENEID);
		/*如果有延时，加入到队列*/
		if(delay > 0){
			kk_scene_push_embed_list(delay,executeSceneId);
		}
		else{
			kk_scene_execute_action(executeSceneId);
		}
	}	
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);	
	return find;
}

int kk_scene_query_trigger_info(const char *deviceCode,cJSON *param)
{
	int res = FAIL_RETURN;
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	char *sceneId = NULL;
	char *identifier = NULL;
	char *compareType = NULL;	
	char *compareValue = NULL;	
	int propertyValueType = 0;
	int sceneType = 0,isEnable = 0;
	sqlite3_stmt *stmt;	
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();

	sqlCmd = sqlite3_mprintf("select * from SceneTriggerInfo WHERE deviceCode= '%s'",deviceCode);	
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		
	    sceneId = sqlite3_column_text(stmt, DB_SCENETRIGGER_SCENEID);
		identifier = sqlite3_column_text(stmt,DB_SCENETRIGGER_PROPERTYNAME);
		compareType = sqlite3_column_text(stmt,DB_SCENETRIGGER_COMPARETYPE);
		compareValue = sqlite3_column_text(stmt,DB_SCENETRIGGER_COMPAREVALUE);
		res = kk_scene_get_scene_info(sceneId,&sceneType,&isEnable);
		if(res == SUCCESS_RETURN && sceneType == DB_SCENETYPE_IFTT && isEnable){
			cJSON *item = cJSON_GetObjectItem(param,identifier);
			if(item != NULL){
				propertyValueType = kk_dm_get_property_type(deviceCode,identifier);
				res = kk_scene_check_value(compareType,compareValue,item,propertyValueType);
				if(res == SUCCESS_RETURN){
					INFO_PRINT("[%d]kk_scene_check_condition enter!!!\n",__LINE__);
					res = kk_scene_check_condition(sceneId);
					if(res == SUCCESS_RETURN){
						res = kk_scene_check_trigger_condition(sceneId);
						if(res == SUCCESS_RETURN){
							/*check是否时内嵌场景*/
							if(kk_scene_embed_find(sceneId) == 0){
								res = kk_scene_execute_action(sceneId);
							}
						}
					}
				}
			}
		}

	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	return res;
}
int kk_scene_iftt_check(const char*deviceCode,cJSON *param)
{
	printf("[%s][%d] deviceCode:%s\n",__FUNCTION__,__LINE__,deviceCode);
	return kk_scene_query_trigger_info(deviceCode,param);
}

int kk_scene_execute_scene(const char *sceneId)
{
	int res = 0;
	int sceneType = 0;
	int isEnable = 0;
	if(sceneId == NULL){
		return INVALID_PARAMETER;
	}
	res = kk_scene_get_scene_info(sceneId,&sceneType,&isEnable);
	if(res == SUCCESS_RETURN && sceneType == DB_SCENETYPE_SCENE && isEnable){
		res = kk_scene_check_condition(sceneId);
		if(res == SUCCESS_RETURN){
			_kk_scene_lock();
			res = kk_scene_execute_action(sceneId);
			_kk_scene_unlock();
		}
	}
	INFO_PRINT("[%d]kk_scene_execute_scene called!!!\n",__LINE__);
	return res;
}


