#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>

#include "kk_newccu_msg.h"
#include "kk_voice_panel_cfg.h"
#include "kk_voice_panel_handle.h"
#include "uart_proto.h"
#include "kk_lan_vp_ctrl.h"
#include "Serial.h"
#include "kk_oldccu_msg.h"
#include <ctype.h>
#ifdef VOICE_SUPPORT
#define MK_VERSION(x)			((*x<<24) | (*(x+1)<<16) | (*(x+2)<<8) | *(x+3))

#define MK_UINT32(x)			((*x<<24) | (*(x+1)<<16) | (*(x+2)<<8) | *(x+3))
#define MK_UINT24(x)			((*x<<16) | (*(x+1)<<8) | *(x+2))
#define MK_UINT16(x)			((*(x)<<8) | *(x+1))




static char s_voice_sw[16] = {0};

static uint16_t _g_seq;
static FILE *update_fp = NULL;
static FILE *ota_fp = NULL;


#define VP_CH						0
#define SOUND_SETE_VP_CH			9
#define VP_RES						0


static void kk_vp_get_8009_snapshoot_handle(pro_data_t *pro_data);
static void kk_vp_get_snapshoot_handle(pro_data_t *pro_data);
static void kk_vp_scene_trigger_handle(pro_data_t *pro_data);
static void kk_vp_set_8009_system_time_handle(pro_data_t *pro_data);
static void kk_vp_get_system_time_handle(pro_data_t *pro_data);
static void kk_vp_action_handle(pro_data_t *pro_data);
static void kk_vp_config_file_update_notify_handle(pro_data_t *pro_data);
static void kk_vp_config_file_update_data_req_handle(pro_data_t *pro_data);
static void kk_vp_config_file_update_stop_handle(pro_data_t *pro_data);
static void kk_vp_config_file_info_query_handle(pro_data_t *pro_data);
static void kk_vp_config_file_update_status_handle(pro_data_t *pro_data);
static void kk_vp_voice_control_handle(pro_data_t *pro_data);

static void kk_vp_ota_file_update_data_req_handle(pro_data_t *pro_data);
static void kk_vp_ota_file_update_start_handle(pro_data_t *pro_data);
static void kk_vp_ota_file_update_stop_handle(pro_data_t *pro_data);
static void kk_vp_ota_info_query_handle(pro_data_t *pro_data);
static void kk_vp_ota_file_update_status_handle(pro_data_t *pro_data);
static void kk_voice_switch_handle(pro_data_t *pro_data);
static void kk_voice_volume_handle(pro_data_t *pro_data);


static VP_OPCODE_HANDLE vp_opcode_table[] = {
	{OPCODE_8009_SNAPSHOOT,kk_vp_get_8009_snapshoot_handle},
	{OPCODE_SNAPSHOOT,kk_vp_get_snapshoot_handle},
	{OPCODE_SCENE_ID_NOTIFY,kk_vp_scene_trigger_handle},
	{OPCODE_SYSTEM_TIME_SET,kk_vp_set_8009_system_time_handle},
	{OPCODE_SYSTEM_TIME_GET,kk_vp_get_system_time_handle},
	{OPCODE_ACTION_NOTIFY,kk_vp_action_handle},
	{OPCODE_CONFIG_FILE_UPDATE_NOTIFY,kk_vp_config_file_update_notify_handle},
	{OPCODE_CONFIG_DATA_REQUEST,kk_vp_config_file_update_data_req_handle},
	{OPCODE_CONFIG_FILE_UPDATE_STOP,kk_vp_config_file_update_stop_handle},
	{OPCODE_CONFIG_FILE_INFO_GET,kk_vp_config_file_info_query_handle},
	{OPCODE_CONFIG_FILE_UPDATE_STATUS,kk_vp_config_file_update_status_handle},
	{OPCODE_VOICE_CONTROL_NOTIFY,kk_vp_voice_control_handle},
	{OPCODE_VOICE_OTA_INFO_GET,kk_vp_ota_info_query_handle},
	{OPCODE_VOICE_OTA_UPGRADE_STATR,kk_vp_ota_file_update_start_handle},
	{OPCODE_VOICE_OTA_REQUEST,kk_vp_ota_file_update_data_req_handle},
	{OPCODE_VOICE_OTA_UPGRADE_STOP,kk_vp_ota_file_update_stop_handle},
	{OPCODE_VOICE_OTA_STATUS_NOTIFY,kk_vp_ota_file_update_status_handle},
	{OPCODE_VOICE_SWITCH,kk_voice_switch_handle},
	{OPCODE_VOICE_CONTROL,kk_voice_volume_handle}	
};







uint32_t ms_uiCrc32Tab[256] = { /* CRC polynomial 0xedb88320 */
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

uint32_t CreateCrc32(const uint8_t* s, uint32_t len) {
    uint32_t i;
    uint32_t crc32val;
    crc32val = ~0;
    for (i = 0; i < len; i++) {
        crc32val = ms_uiCrc32Tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
    }

    return ~crc32val;
}



typedef struct VP_SCENE_MAP
{
	int raw_id;
	uint16_t map_id;
	struct VP_SCENE_MAP *next;
}VP_SCENE_MAP;
static VP_SCENE_MAP *vp_scene_map;
static uint16_t vp_map_id = 1;

static int vp_scene_id_get_scene_id(uint16_t map_id)
{
	VP_SCENE_MAP *pScene = vp_scene_map;

	while(pScene!=NULL){
		if(pScene->map_id==map_id){
			return pScene->raw_id;
		}
		pScene = pScene->next;
	}
	return -1;
}



void vp_scene_id_map_deinit(void)
{

	VP_SCENE_MAP *pNext = NULL;
	VP_SCENE_MAP *pScene = vp_scene_map;

	debug_log(LOG_NOTICE_LEVEL,"vp_scene_id_map_deinit.\n");

	while(pScene!=NULL){
		pNext = pScene->next;
		if(pScene!=NULL){
			free(pScene);
		}
		pScene = pNext;
	}

	vp_map_id = 1;
	vp_scene_map = NULL;
}


int vp_scene_id_item_add(int scene_id)
{
	VP_SCENE_MAP *ptr = NULL,*pre = NULL;
	VP_SCENE_MAP *pScene = NULL;
	
	pScene = malloc(sizeof(VP_SCENE_MAP));
	memset(pScene,0,sizeof(VP_SCENE_MAP));

	pScene->raw_id = scene_id;
	pScene->map_id = vp_map_id++;

	debug_log(LOG_DEBUG_LEVEL,"[vp scene map]%d->%d\n",pScene->raw_id,pScene->map_id);
	
	if(vp_scene_map == NULL){
		vp_scene_map = pScene;
	}else{
		ptr = vp_scene_map;
		while(ptr){
			pre = ptr;
			ptr = ptr->next;
		}
		ptr = pre;
		ptr->next = pScene;
	}

	return pScene->map_id;
}

int vp_scene_id_item_load(int scene_id,uint16_t map_id)
{
	VP_SCENE_MAP *ptr = NULL,*pre = NULL;
	VP_SCENE_MAP *pScene = NULL;

	pScene = malloc(sizeof(VP_SCENE_MAP));
	memset(pScene,0,sizeof(VP_SCENE_MAP));

	pScene->raw_id = scene_id;
	pScene->map_id = map_id;

	debug_log(LOG_DEBUG_LEVEL,"[vp scene map load]%d->%d\n",pScene->raw_id,pScene->map_id);



	
	if(vp_scene_map == NULL){
		vp_scene_map = pScene;
	}else{
		ptr = vp_scene_map;
		while(ptr){
			pre = ptr;
			ptr = ptr->next;
		}
		ptr = pre;
		ptr->next = pScene;
	}

	return pScene->map_id;
}

#define VP_SCENE_ID_STRING						"scene_id"
#define VP_SCENE_ID_RAW_STRING					"CCU"
#define VP_SCENE_ID_MAP_STRING					"VP"


cJSON *vp_scene_id_map_file_build(void)
{
	VP_SCENE_MAP *pScene = vp_scene_map;
	
	cJSON *json = cJSON_CreateObject();
	cJSON *SceMapAry = cJSON_CreateArray();

	

	while(pScene!=NULL){
		cJSON * mapItem = cJSON_CreateObject();
		cJSON_AddNumberToObject(mapItem,VP_SCENE_ID_MAP_STRING,pScene->map_id);
		cJSON_AddNumberToObject(mapItem,VP_SCENE_ID_RAW_STRING,pScene->raw_id);
		cJSON_AddItemToArray(SceMapAry,mapItem);

		pScene = pScene->next;
	}
	cJSON_AddItemToObject(json,VP_SCENE_ID_STRING,SceMapAry);
	
	return json;
}

int vp_scene_id_map_file_prase(char *data)
{
	VP_SCENE_MAP *pScene = vp_scene_map;

	cJSON *map_id = NULL,*raw_id = NULL;
	cJSON *json = cJSON_Parse(data);
	cJSON *SceMapAry = NULL;
	int i,SceMapNum = 0;
	if(json==NULL){
		return 0;
	}
	SceMapAry = cJSON_GetObjectItem(json,VP_SCENE_ID_STRING);
	SceMapNum = cJSON_GetArraySize(SceMapAry);

	vp_scene_id_map_deinit();

	for(i=0;i<SceMapNum;i++){
		cJSON *mapItem = cJSON_GetArrayItem(SceMapAry,i);
		map_id = cJSON_GetObjectItem(mapItem,VP_SCENE_ID_MAP_STRING);
		raw_id = cJSON_GetObjectItem(mapItem,VP_SCENE_ID_RAW_STRING);
		vp_scene_id_item_load(raw_id->valueint,map_id->valueint);
	}

	cJSON_Delete(json);
	return 1;
}

int vp_scene_id_map_save(void)
{
	char *pStr = NULL;
	char *pWrite = NULL;
	FILE *fp = NULL;

	int w_len = 0,length = 0;

	cJSON *json = vp_scene_id_map_file_build();

	pStr = cJSON_Print(json);

	debug_log(LOG_DEBUG_LEVEL,"[vp scene id file]%s\n",pStr);
	cJSON_Minify(pStr);
	
	length = strlen(pStr);
	pWrite = pStr;

	if((fp= fopen(VP_SCENE_ID_FILE, "w"))==NULL) {
		return 0;
	}
	
	while(length>0){
		w_len = fwrite(pWrite, 1, length, fp);
		pWrite+=w_len;
		length -= w_len;
	}

	cJSON_Delete(json);
	free(pStr);
	fclose(fp);

	system("sync");
	
	return 1;
}

int vp_scene_id_map_load(void)
{
	char *buff = NULL;
	char *pRead = NULL;
	int t_len = 0;
	int remain = 0;
	int r_len = 0;

	FILE *fp = NULL;
	int size = 0;
	
	fp = fopen (VP_SCENE_ID_FILE,"r");
	if(fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",VP_SCENE_ID_FILE);
		return -1;
	}


	fseek (fp, 0, SEEK_END);
	size=ftell(fp);


	fseek (fp, 0, SEEK_SET);

	buff = malloc(size+1);
	memset(buff,0,size+1);
	pRead = buff;
	remain = size;
	
	
	while(remain>0){
		r_len = fread(pRead, 1, size, fp);
		
		if(remain>=r_len){
			remain -= r_len;
			pRead+=r_len;
		}else{
			remain = 0;
			pRead[size] = '\0';
		}
	}

	vp_scene_id_map_file_prase(buff);


	
	free(buff);
	fclose(fp);

	return 1;
}



uint16_t vp_get_seq(void)
{
	return _g_seq++;
}
void vp_send_data_build_ex(uint16_t opCode,int len,uint8_t *data)
{
	uint8_t data_buf[1024] = {0};
	int data_len = 0;
	
	pro_data_t pro_data;
	memset(&pro_data,0,sizeof(pro_data_t));

	pro_data.seq = vp_get_seq();
	pro_data.ch = SOUND_SETE_VP_CH;
	pro_data.opcode = opCode;

	pro_data.cf.ack = 0;
	pro_data.cf.dir = 1;
	pro_data.cf.sof_flag = 1;

	pro_data.args_len = len;
	memcpy(pro_data.arg,data,len);

	data_len = proto_frame_to_uart(&pro_data,data_buf);

	debug_log(LOG_INFO_LEVEL,"\n[LAN->VP]len=%d\n",data_len);
	uint8_t dataStr[512] = {0};
	for(int i=0;i<data_len;i++){
		snprintf((char *)dataStr + strlen((char *)dataStr), sizeof(dataStr), "%02X ",data_buf[i]);
	}
	debug_log(LOG_INFO_LEVEL,"%s\n\n",dataStr);


	voice_uart_lock();
	eSerial_WriteBuffer(data_buf, data_len);
	voice_uart_unlock();
}
void vp_send_data_build(uint16_t opCode,int len,uint8_t *data)
{
	uint8_t data_buf[1024] = {0};
	int data_len = 0;
	
	pro_data_t pro_data;
	memset(&pro_data,0,sizeof(pro_data_t));

	pro_data.seq = vp_get_seq();
	pro_data.ch = VP_CH;
	pro_data.opcode = opCode;

	pro_data.cf.ack = 0;
	pro_data.cf.dir = 1;
	pro_data.cf.sof_flag = 1;

	pro_data.args_len = len;
	memcpy(pro_data.arg,data,len);

	data_len = proto_frame_to_uart(&pro_data,data_buf);


	debug_log(LOG_INFO_LEVEL,"\n[LAN->VP]len=%d\n",data_len);
	uint8_t dataStr[512] = {0};
	for(int i=0;i<data_len;i++){
		snprintf((char *)dataStr + strlen((char *)dataStr), sizeof(dataStr), "%02X ",data_buf[i]);
	}
	debug_log(LOG_INFO_LEVEL,"%s\n\n",dataStr);
	
	voice_uart_lock();
	eSerial_WriteBuffer(data_buf, data_len);
	voice_uart_unlock();
}

void vp_reply_data_build(uint16_t seq,uint8_t ch,uint16_t opCode,int len,uint8_t *data)
{
	uint8_t data_buf[1024] = {0};
	int data_len = 0;
	
	pro_data_t pro_data;
	memset(&pro_data,0,sizeof(pro_data_t));

	pro_data.seq = seq;
	pro_data.ch = ch;
	pro_data.opcode = opCode;

	pro_data.cf.ack = 0;
	pro_data.cf.dir = 1;
	pro_data.cf.sof_flag = 0;

	pro_data.args_len = len;
	memcpy(pro_data.arg,data,len);

	data_len = proto_frame_to_uart(&pro_data,data_buf);



	uint8_t dataStr[1024] = {0};
	for(int i=0;i<data_len;i++){
		snprintf((char *)dataStr + strlen((char *)dataStr), sizeof(dataStr), "%02X ",data_buf[i]);
	}
	debug_log(LOG_INFO_LEVEL,"%s\n\n",dataStr);

	voice_uart_lock();
	eSerial_WriteBuffer(data_buf, data_len);
	voice_uart_unlock();
}




























int _vp_get_cfg_file_size(void)
{
	int size = 0;
	FILE *fp = NULL;
	
	fp = fopen (VP_CONFIG_FILE_TAR_GZ,"r");
	if(fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",VP_CONFIG_FILE_TAR_GZ);
		return 0;
	}
	fseek (fp, 0, SEEK_END);
	size=ftell(fp);
	printf("size=%d\n",size);

	fclose(fp);
	
	return size;
}
int _vp_get_cfg_file_crc32(void)
{
	char *buff = NULL;
	char *pRead = NULL;
	int t_len = 0;
	int remain = 0;
	int r_len = 0;
	uint32_t crc32 = 0;
	FILE *fp = NULL;
	int size = 0;
	
	fp = fopen (VP_CONFIG_FILE,"r");
	if(fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",VP_CONFIG_FILE);
		printf("open err.\n");
		return -1;
	}

	fseek (fp, 0, SEEK_END);
	size=ftell(fp);

	fseek (fp, 0, SEEK_SET);

	buff = malloc(size+1);
	memset(buff,0,size+1);
	pRead = buff;
	remain = size;
	
	
	while(remain>0){
		r_len = fread(pRead, 1, size, fp);
		
		if(remain>=r_len){
			remain -= r_len;
			pRead+=r_len;
			printf("[remain]r_len=%d,remain=%d\n",r_len,remain);
		}else{
			remain = 0;
			
			pRead[size] = '\0';
		}
	}
	crc32 = CreateCrc32((uint8_t *)buff, size);
	printf("crc32=%x\n",crc32);
	
	free(buff);
	fclose(fp);

	return crc32;
}
int kk_vp_voice_version_set(char *ver,int len)
{
	if(ver == NULL || len >= strlen(s_voice_sw)){
		return -1;
	}
	memcpy(s_voice_sw,ver,strlen(ver));
	return 0;
}

static void vp_open_fd()
{
	if(update_fp!=NULL){
		fclose (update_fp);
	}

	update_fp = fopen (VP_CONFIG_FILE_TAR_GZ,"rb");

	if(update_fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",VP_CONFIG_FILE_TAR_GZ);
	}
}

int kk_vp_voice_version_get(char *ver,int len)
{
	if(ver == NULL || len < strlen(s_voice_sw)){
		return -1;
	}
	memcpy(ver,s_voice_sw,strlen(s_voice_sw));
	return 0;
}



























































static void kk_vp_get_8009_snapshoot_handle(pro_data_t *pro_data)
{
	uint8_t err;
	uint32_t sv,hv,f_ver;
	uint16_t year;
	uint8_t month,day;
	uint8_t hour,minute,second;
	uint8_t volume;

	if(pro_data->args_len==0){
		return ;
	}

	if((err = pro_data->arg[0])==0){
		if(pro_data->args_len!=19){
			return ;
		}
		sv = MK_UINT24(&pro_data->arg[1]);
		hv = MK_UINT24(&pro_data->arg[4]);
		year = MK_UINT16(&pro_data->arg[7]);
		month = pro_data->arg[9];
		day = pro_data->arg[10];
		hour = pro_data->arg[11];
		minute = pro_data->arg[12];
		second = pro_data->arg[13];
		volume = pro_data->arg[14];

		f_ver = MK_UINT32(&pro_data->arg[15]);
			
		kk_get_voice_version();
		kk_vp_set_config_file_version(f_ver);
		memset(s_voice_sw,0x0,sizeof(s_voice_sw));
		//string version=std::to_string(pro_data->arg[1])+"."+std::to_string(pro_data->arg[2])+"."+std::to_string(pro_data->arg[3]);
		sprintf(s_voice_sw,"%d.%d.%d",pro_data->arg[1],pro_data->arg[2],pro_data->arg[3]);
		debug_log(LOG_INFO_LEVEL,"\nsv=%06X,hv=%06X,%d-%d-%d %d:%d:%d,volume=%d,f_ver=%08X\n",
			sv,hv,year,month,day,hour,minute,second,volume,f_ver);
	}
}

char MAC[18];
#define CMD_MAC             "fw_printenv ethaddr -n"
int _System(const char * cmd, char *pRetMsg, int msg_len){
	FILE * fp;
	int res = -1;
	int ret = 0;
	
	if (cmd == NULL || pRetMsg == NULL || msg_len < 0)
	{
		printf("Param Error!\n");
		return -1;
	}
	
	if ((fp = popen(cmd, "r") ) == NULL)
	{
		printf("Popen Error!\n");
		return -2;
		
	}else{
	    int i = 0;
	    char c = 0;
		memset(pRetMsg, 0, msg_len);
		//while(fgets(pRetMsg, msg_len, fp) != NULL)
		while(fread(&c,1,1,fp),!feof(fp))
		{
			//printf("%s, i=%d\n",pRetMsg, i); 
			pRetMsg[i++]=c;
			if (i >= msg_len -1){
			    break;
			}

		}
        //printf("end %s \n",pRetMsg); 
        
		if ((res = pclose(fp)) == -1)
		{
			printf("close popenerror!\n");
			return -3;
		}
		
		if (pRetMsg[strlen(pRetMsg)-1] == '\n'){
            pRetMsg[strlen(pRetMsg)-1] = '\0';
		}
		return ret;
	}
}

char* getMac(){
    char tmp[128] = {0};
    int ret = 0;

    if (strlen(MAC) > 0){
        return MAC;
    }
    ret = _System(CMD_MAC, tmp, sizeof(tmp));
    if (ret == 0 && strlen(tmp) > 0){
        memset(MAC, 0x00, sizeof(MAC));
        strncpy(MAC, tmp, sizeof(MAC));
        MAC[sizeof(MAC) - 1] = 0;
        return MAC;
    }else{
        printf("==== get mac error, exit sys_ota!!!!!! \n");
        return NULL;
    }
}
static char convert_byte(char temp)
{
	char data = 0;
	if ((temp >= '0') && (temp <= '9'))
	{
		data = (temp - '0');
	}
	else if ((temp >= 'a') && (temp <= 'f'))
	{
		data = (temp - 'a' + 10);
	}
	else if ((temp >= 'A') && (temp <= 'F'))
	{
		data = (temp - 'A' + 10);
	}
	return data;
}

static void kk_vp_get_snapshoot_handle(pro_data_t *pro_data)
{
	uint8_t data[12]={0};
	uint8_t i;

	uint8_t err = 0;
	uint8_t mac[8] ={0};
	uint16_t nodeId = 0;
	uint8_t netStatus = 0x02;

	char* pMac = getMac();

	if(pro_data->args_len!=1||pMac==NULL){
		return ;
	}
	
	for(int j =0;j<6;j++){
		mac[j] = (convert_byte(pMac[3*j])<<4)|convert_byte(pMac[3*j+1]);
	}
	
	//todo:
	data[0] = err;
	for(i=0;i<8;i++){
		data[1+i] = mac[i];
	}
	data[9] = (nodeId>>8)&0xff;
	data[10] = nodeId&0xff;
	data[11] = netStatus;

	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_SNAPSHOOT,sizeof(data),data);
}

static void kk_vp_scene_trigger_handle(pro_data_t *pro_data)
{
	cJSON *msg = NULL;

	uint8_t data[1024]={0};
	uint8_t off = 0;
	
	uint16_t *sceneAry;
	uint8_t sceneNum = 0;
	uint8_t i;
	int sceneId = 0;

	if(pro_data->args_len<3 &&
		pro_data->args_len%2!=0){
		return ;
	}

	sceneNum = pro_data->arg[0];
	sceneAry = malloc(sizeof(uint16_t)*sceneNum);

	debug_log(LOG_CRIT_LEVEL,"execute scene\n");
	debug_log(LOG_CRIT_LEVEL,"sceneNum=%d\n",sceneNum);

	for(i=0;i<sceneNum;i++){
		sceneAry[i] = MK_UINT16(&pro_data->arg[1+2*i]);
		debug_log(LOG_INFO_LEVEL,"scene-%d:%d\n",i,sceneAry[i]);
	}

	for(i=0;i<sceneNum;i++){
		if((sceneId = vp_scene_id_get_scene_id(sceneAry[i]))!=-1){

			char buff[32] = {0};
			memset(buff,0,32);
			snprintf(buff,32,"%d",sceneId);
			msg=scene_execute(buff);
			kk_ipc_send_json(msg);
			data[1+2*off] = (sceneAry[i]>>8)&0xff;
			data[2+2*off] = sceneAry[i]&0xff;
			off+=1;
		}
	}

	if(off!=0){
		data[0] = 0x00;
	}else{
		data[0] = 1;
	}

	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_SCENE_ID_NOTIFY,1+2*off+1,data);
	free(sceneAry);
}
static void kk_vp_set_8009_system_time_handle(pro_data_t *pro_data)
{
	uint8_t data[8]={0};
	uint8_t err;
	uint16_t year;
	uint8_t month,day,hour,minute,sec;

	if(pro_data->args_len==0){
		return ;
	}

	if((err = pro_data->arg[0])==0){
		if(pro_data->args_len!=8){
			return ;
		}
	}
	
	year = MK_UINT16(&pro_data->arg[1]);
	month = pro_data->arg[3];
	day = pro_data->arg[4];
	hour= pro_data->arg[5];
	minute = pro_data->arg[6];
	sec = pro_data->arg[7];

	kk_voice_set_time_flag();

	debug_log(LOG_INFO_LEVEL,"\n%d-%d-%d %d:%d:%d\n",year,month,day,hour,minute,sec);
}

static void kk_vp_get_system_time_handle(pro_data_t *pro_data)
{
	uint8_t data[8]={0};
	uint8_t err;
	uint16_t year;
	uint8_t month,day,hour,minute,sec;

	if(pro_data->args_len!=1){
		return ;
	}

	time_t curTime = time(NULL);
	struct tm *c = localtime(&curTime);

	data[0] = 0;
	data[1] = ((c->tm_year+1900)>>8)&0Xff;
	data[2] =(c->tm_year+1900)&0Xff;
	data[3] = (c->tm_mon+1);
	data[4] = c->tm_mday;
	data[5] = c->tm_hour;
	data[6] = c->tm_min;
	data[7] = c->tm_sec;
	
	debug_log(LOG_INFO_LEVEL,"\n%d-%d-%d %d:%d:%d\n",(c->tm_year+1900),(c->tm_mon+1),c->tm_mday,c->tm_hour,c->tm_min,c->tm_sec);

	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_SYSTEM_TIME_GET,sizeof(data),data);

}
static void kk_vp_action_handle(pro_data_t *pro_data)
{
	uint8_t err = 0;
	uint8_t i=0;
	uint8_t devNum = 0;
	uint32_t *nodeIdAry = NULL;
	uint32_t *OperatorIdAry = NULL;
	uint8_t skillType;
	
	
	debug_log(LOG_CRIT_LEVEL,"\n\n****************************KK VOICE CONTROL****************************\n");
	if((devNum =  pro_data->arg[0])!=0){
		nodeIdAry = malloc(sizeof(uint32_t)*devNum);
		OperatorIdAry = malloc(sizeof(uint32_t)*devNum);
		debug_log(LOG_DEBUG_LEVEL,"devNum=%d\n",devNum);

		for(i=0;i<devNum;i++){
			nodeIdAry[i] =(pro_data->arg[1+8*i]<<24) | (pro_data->arg[2+8*i]<<16) | (pro_data->arg[3+8*i]<<8) | pro_data->arg[4+8*i];
			OperatorIdAry[i] = (pro_data->arg[5+8*i]<<24) | (pro_data->arg[6+8*i]<<16) | (pro_data->arg[7+8*i]<<8) | pro_data->arg[8+8*i];
			debug_log(LOG_DEBUG_LEVEL,"[%d]Node Id=0x%08x,Operator Id=0x%08x\n",i,nodeIdAry[i],OperatorIdAry[i]);
		}

		skillType = pro_data->arg[1+8*i];
		debug_log(LOG_DEBUG_LEVEL,"skill type=0x%02x,arg len=%d\n",skillType,pro_data->args_len-1-8*devNum);

		err = kk_lan_vp_control(devNum,nodeIdAry,&pro_data->arg[1+8*i],pro_data->args_len-1-8*devNum);

		if(err==0){
			uint8_t data[256]={0};
			memset(data,0,sizeof(data));
			data[0] = err;
			data[1] = devNum;
		
			for(i=0;i<devNum;i++){
				data[2+8*i] = (nodeIdAry[i]>>24)&0xff;
				data[3+8*i] = (nodeIdAry[i]>>16)&0xff;
				data[4+8*i] = (nodeIdAry[i]>>8)&0xff;
				data[5+8*i] = nodeIdAry[i]&0xff;
			
				data[6+8*i] = (OperatorIdAry[i]>>24)&0xff;
				data[7+8*i] = (OperatorIdAry[i]>>16)&0xff;
				data[8+8*i] = (OperatorIdAry[i]>>8)&0xff;
				data[9+8*i] = OperatorIdAry[i]&0xff;
			}
			data[2+8*i] = skillType;
			data[3+8*i] = 0x20;
			data[4+8*i] = devNum;
			int off =5+8*i;
			for(i=0;i<devNum;i++){
				data[off+i] = 0;
			}
			
			vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_ACTION_NOTIFY,off+i,data);
		}

		free(nodeIdAry);
		free(OperatorIdAry);
	}
}

static void kk_vp_config_file_update_notify_handle(pro_data_t *pro_data)
{
	uint8_t err;
	uint32_t f_ver,f_size,crc32;
	
	if(pro_data->args_len==0){
		return ;
	}
	if((err = pro_data->arg[0])==0){
		if(pro_data->args_len!=13){
			return ;
		}
		f_ver = MK_UINT32(&pro_data->arg[1]);
		f_size = MK_UINT32(&pro_data->arg[5]);
		crc32 = MK_UINT32(&pro_data->arg[9]);

		kk_vp_config_file_info_check(f_ver,f_size,crc32);
		
		debug_log(LOG_DEBUG_LEVEL,"File Version=%08x,File Size=%d,CRC32 Value=%08X\n",
			f_ver,f_size,crc32);
	}else {
		printf("\n");
	}
}

static void kk_vp_config_file_update_data_req_handle(pro_data_t *pro_data)
{
	int err = 0;
	uint32_t f_ver,offset;
	uint16_t req_size;

	uint8_t data[1024] = {0};
	uint16_t len = 0;
	uint16_t r_len = 0;
	uint16_t t_len = 0;
	uint8_t *pCrc = NULL;

	uint32_t crc;

	if(pro_data->args_len!=10){
		return ;
	}
	f_ver = MK_UINT32(&pro_data->arg[0]);
	offset = MK_UINT32(&pro_data->arg[4]);
	req_size =  MK_UINT16(&pro_data->arg[8]);
	
	debug_log(LOG_DEBUG_LEVEL,"\nf_ver=%d,offset=%d,req_size=%d\n",f_ver,offset,req_size);
	if(update_fp==NULL){
		debug_log(LOG_ERROR_LEVEL,"[update_fp] NULL!\n");
		err = 1;
	}
	/*
	if(f_ver!=kk_vp_get_config_file_version()){
		printf("[file version] not match!%d,%d\n",f_ver,kk_vp_get_config_file_version());
		err = 2;
	}*/
	
	data[len++] = err;
	
	data[len++] = (offset>>24)&0xff;
	data[len++] = (offset>>16)&0xff;
	data[len++] = (offset>>8)&0xff;
	data[len++] = offset&0xff;

	
	data[len++] = (req_size>>8)&0xff;
	data[len++] = req_size&0xff;

	pCrc = &data[len];

	if(err==0){

		if(update_fp!=NULL){
			err = fseek(update_fp, offset, SEEK_SET);
		}

		
	
		if(err==0){
			while(req_size>t_len){
				r_len = fread(&data[len], 1, req_size, update_fp);
				debug_log(LOG_ERROR_LEVEL,"r_len=%d\n",r_len);
			
				if(update_fp==NULL){
					debug_log(LOG_ERROR_LEVEL,"NULL\n");
				}

				if(r_len<req_size){
					debug_log(LOG_ERROR_LEVEL,"r_len<req_size\n");
					if(feof(update_fp)!=0){
						debug_log(LOG_ERROR_LEVEL,"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@eof\n");
						break;
					}else if(ferror(update_fp)!=0){
						debug_log(LOG_ERROR_LEVEL,"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@err:%d,%d\n",ferror(update_fp),errno);
						break;
					}
				}
				
				if(r_len>0){
					t_len+=r_len;
					len += r_len;
				}else if(r_len==0){
					if(errno!=EINTR){
						break;
					}
				}else{
					break;
				}
			}
		}else{
			debug_log(LOG_ERROR_LEVEL,"[fseek fail]offset=%d\n",offset);
		}
	}
	
	crc = CreateCrc32(pCrc, req_size);
	data[len++] = (crc>>24)&0xff;
	data[len++] = (crc>>16)&0xff;
	data[len++] = (crc>>8)&0xff;
	data[len++] = crc&0xff;
	debug_log(LOG_DEBUG_LEVEL,"crc32=%x\n",crc);
	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_CONFIG_DATA_REQUEST,len,data);
	//usleep(100*1000);


}


static void kk_vp_config_file_update_stop_handle(pro_data_t *pro_data)
{
	uint8_t err,status;
	uint32_t ver;

	if(pro_data->args_len==0){
		return ;
	}

	if((err = pro_data->arg[0])==0){
		if(pro_data->args_len!=5){
			return ;
		}
		ver = MK_VERSION(&pro_data->arg[1]);
		debug_log(LOG_DEBUG_LEVEL,"\n version=%d\n",ver);
	}else{
		printf("err=%d\n",err);
	}

	ver = (pro_data->arg[0]<<24) | (pro_data->arg[1]<<16) | (pro_data->arg[2]<<8) | pro_data->arg[3];
	status = pro_data->arg[4];
}

static void kk_vp_config_file_update_status_handle(pro_data_t *pro_data)
{
	int err = 0;
	int ver;
	unsigned char status;
	
	if(pro_data->args_len!=5){
		return ;
	}
	
	ver = MK_UINT32(&pro_data->arg[0]);
	status = pro_data->arg[4];


	
	
	debug_log(LOG_DEBUG_LEVEL,"\nver=%d,status=%d\n",ver,status);


	uint8_t data[6] = {0};
	data[0] = err;
	data[1] = (ver>>24)&0xff;
	data[2] = (ver>>16)&0xff;
	data[3] = (ver>>8)&0xff;
	data[4] = ver&0xff;
	data[5] = status;

	

	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_CONFIG_FILE_UPDATE_STATUS,sizeof(data),data);

	kk_vp_update_result_check(status,ver);

}



static void kk_vp_voice_control_notify(uint8_t status)
{
	if(status!=1&&status!=2){
		return ;
	}
	
	cJSON *root = cJSON_CreateObject();
	cJSON_AddStringToObject(root,"node","*");
	cJSON_AddStringToObject(root,"opcode","VOICE_CTRL");
	
	if(status==1){
		debug_log(LOG_DEBUG_LEVEL,"[VP]wake up.\n\n");
		cJSON_AddStringToObject(root,"arg","ON");
	}else if(status==2){
		debug_log(LOG_DEBUG_LEVEL,"[VP]sleep.\n\n");
		cJSON_AddStringToObject(root,"arg","OFF");
	}
	
	cJSON_AddStringToObject(root,"status","success");

	send_msg_to_module(root);
	cJSON_Delete(root);
}

static void kk_vp_voice_control_handle(pro_data_t *pro_data)
{
	if(pro_data->args_len!=1) {
		return ;
	}

	kk_vp_voice_control_notify(pro_data->arg[0]);
}

static void kk_vp_config_file_info_query_handle(pro_data_t *pro_data)
{
	uint8_t err;
	uint32_t f_ver,f_size,crc32;
	

	if(pro_data->args_len==0) {
		return ;
	}

	if((err = pro_data->arg[0])==0) {
		if(pro_data->args_len!=13){
			return ;
		}
		f_ver = MK_UINT32(&pro_data->arg[1]); 

		f_size = MK_UINT32(&pro_data->arg[5]);
		crc32 = MK_UINT32(&pro_data->arg[9]);
		debug_log(LOG_DEBUG_LEVEL,"File Version=%08x,File Size=%08x,CRC32=%08x\n",f_ver,f_size,crc32);

		kk_vp_cfg_info_check(f_ver,f_size,crc32);
	}

}

///////////////////////////////////////////

void kk_voice_control(int val)
{
	uint8_t res[1] = {0};

	if(val>100){
		val = 100;
	}else if(val<0){
		val = 0;
	}
	
	res[0] = val;
	debug_log(LOG_DEBUG_LEVEL,"sound control\n");
	vp_send_data_build_ex(OPCODE_VOICE_CONTROL,sizeof(res),res);
}

void kk_voice_switch(int val)
{
	uint8_t res[3] = {0};

	if(val==0||val==1){
		res[0] = val;
		res[1] = 0xff;
		res[2] = 0xff;
		debug_log(LOG_DEBUG_LEVEL,"voice switch\n");
		vp_send_data_build(OPCODE_VOICE_SWITCH,sizeof(res),res);
	}
}




void kk_voice_cfg_init(void)
{
	uint8_t res[3] = {0};

	res[0] = 0xff;
	res[1] = (KK_VOICE_OTA_MTU>>8)&0xff;
	res[2] = KK_VOICE_OTA_MTU&0xff;
	debug_log(LOG_DEBUG_LEVEL,"@@@@@@@@@@@@@@@@@@@@@@@\n");
	vp_send_data_build(OPCODE_VOICE_SWITCH,sizeof(res),res);
}


void kk_voice_test(void)
{
	uint8_t res[1] = {1};
	vp_send_data_build(0XEDB4,sizeof(res),res);
}


void kk_vp_get_8009_snapshoot(void)
{
	uint8_t res[1] = {0};


	
	debug_log(LOG_DEBUG_LEVEL,"get snapshoot\n");

	vp_send_data_build(OPCODE_8009_SNAPSHOOT,sizeof(res),res);
}

void kk_vp_set_8009_system_time(void)
{
	uint8_t data[7] = {0};

	time_t curTime = time(NULL);
	struct tm *c = localtime(&curTime);



	data[0] = ((c->tm_year+1900)>>8)&0Xff;
	data[1] =(c->tm_year+1900)&0Xff;
	data[2] = (c->tm_mon+1);
	data[3] = c->tm_mday;
	data[4] = c->tm_hour;
	data[5] = c->tm_min;
	data[6] = c->tm_sec;

	debug_log(LOG_DEBUG_LEVEL,"set system (%d-%d-%d %d:%d:%d)\n",(c->tm_year+1900),(c->tm_mon+1),c->tm_mday,c->tm_hour,c->tm_min,c->tm_sec);
	vp_send_data_build(OPCODE_SYSTEM_TIME_SET,sizeof(data),data);
}




void kk_vp_config_file_update_start(uint32_t ver)
{
	uint8_t data[12] = {0};

	uint32_t f_ver,f_size,crc32;

	f_ver = ver;
	f_size = _vp_get_cfg_file_size();
	printf("f_size=%d\n",f_size);
	if(f_size==0){
		debug_log(LOG_EMERG_LEVEL,"[err]!!!!!!!!!!!!!!\n");
		return ;
	}
	crc32 = _vp_get_cfg_file_crc32();
	
	data[0] = (f_ver>>24)&0xff;
	data[1] = (f_ver>>16)&0xff;
	data[2] = (f_ver>>8)&0xff;
	data[3] = f_ver&0xff;

	data[4] = (f_size>>24)&0xff;
	data[5] = (f_size>>16)&0xff;
	data[6] = (f_size>>8)&0xff;
	data[7] = f_size&0xff;

	data[8] = (crc32>>24)&0xff;
	data[9] = (crc32>>16)&0xff;
	data[10] = (crc32>>8)&0xff;
	data[11] = crc32&0xff;

	kk_vp_cfg_info_set(f_ver,f_size,crc32);
	
	debug_log(LOG_DEBUG_LEVEL,"[LAN->VP]config file update start,OPCODE=%04X\n",OPCODE_CONFIG_FILE_UPDATE_NOTIFY);
	debug_log(LOG_DEBUG_LEVEL,"File Version=%08x,File Size=%d,CRC32 Value=%08X\n",
		f_ver,f_size,crc32);
	
	vp_send_data_build(OPCODE_CONFIG_FILE_UPDATE_NOTIFY,sizeof(data),data);
	

	vp_open_fd();

	
}

void kk_vp_config_file_update_stop(uint32_t ver)
{
	uint8_t f_ver[4];
	f_ver[0] = (ver>>24)&0xff;
	f_ver[1] = (ver>>16)&0xff;
	f_ver[2] = (ver>>8)&0xff;
	f_ver[3] = ver&0xff;
	
	debug_log(LOG_DEBUG_LEVEL,"[LAN->VP]config file update stop,OPCODE=%04X\n",OPCODE_CONFIG_FILE_UPDATE_STOP);
	vp_send_data_build(OPCODE_CONFIG_FILE_UPDATE_STOP,sizeof(f_ver),f_ver);
}

void kk_vp_get_config_file_info(void)
{
	uint8_t res[1] = {0};
	debug_log(LOG_DEBUG_LEVEL,"[LAN->VP]config file info get,OPCODE=%04X\n",OPCODE_CONFIG_FILE_INFO_GET);
	vp_send_data_build(OPCODE_CONFIG_FILE_INFO_GET,sizeof(res),res);
}





void kk_vp_get_ota_file_info(void)
{
	uint8_t res[1] = {0};
	debug_log(LOG_DEBUG_LEVEL,"[LAN->VP]OTA info get,OPCODE=%04X\n",OPCODE_VOICE_OTA_INFO_GET);
	vp_send_data_build(OPCODE_VOICE_OTA_INFO_GET,sizeof(res),res);
}



static int _vp_get_ota_file_crc32(char *file)
{
	char *buff = NULL;
	char *pRead = NULL;
	int t_len = 0;
	int remain = 0;
	int r_len = 0;
	uint32_t crc32 = 0;
	FILE *fp = NULL;
	int size = 0;
	char filePath[218] = {0};
	sprintf(filePath,"/data/OTA/%s",file);
	fp = fopen (filePath,"r");
	if(fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",filePath);
		printf("open err.\n");
		return -1;
	}

	fseek (fp, 0, SEEK_END);
	size=ftell(fp);

	fseek (fp, 0, SEEK_SET);

	buff = malloc(size+1);
	memset(buff,0,size+1);
	pRead = buff;
	remain = size;
	
	
	while(remain>0){
		r_len = fread(pRead, 1, size, fp);
		
		if(remain>=r_len ){
			remain -= r_len;
			pRead+=r_len;
			printf("[remain]r_len=%d,remain=%d\n",r_len,remain);
		}else{
			remain = 0;
			
			pRead[size] = '\0';
		}
	}
	crc32 = CreateCrc32((uint8_t *)buff, size);
	printf("crc32=%x\n",crc32);
	
	free(buff);
	fclose(fp);

	return crc32;
}

static int get_ota_file_version(char *file)
{
	char s[128];
	char *ota_file = NULL;
	char *pstart = NULL;
	if(file == NULL){
		return -1;
	}
	pstart = strstr(file,"_");
	if(pstart != NULL){
		ota_file = pstart + 1;
	}else{
		ota_file = file;
	}

	snprintf(s,sizeof(s),"%s",ota_file);
	debug_log(LOG_NOTICE_LEVEL,"ota file ver=%s\n",s);
	char *d = ".";
	char *p;
	p = strtok(s, d);

	int vBuff[3] = {0};
	int off = 0;
	while (p)
	{
		if (isdigit(*p)) {
			vBuff[off++] = atoi(p);
			if(off==3){
				break;
			}
		}
		p = strtok(NULL, d);
	}

	return ((vBuff[0]&0xff)<<16)|((vBuff[1]&0xff)<<8)|(vBuff[2]&0xff);
}
static int _vp_get_ota_file_size(char* file)
{
	int size = 0;
	FILE *fp = NULL;
	char filePath[218] = {0};
	sprintf(filePath,"/data/OTA/%s",file);

	fp = fopen (filePath,"r");
	if(fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",filePath);
		return 0;
	}
	fseek (fp, 0, SEEK_END);
	size=ftell(fp);
	fclose(fp);
	return size;
}
static void open_ota_fd(char* file)
{
	char filePath[218] = {0};

	sprintf(filePath,"/data/OTA/%s",file);	
	if(ota_fp!=NULL){
		fclose (ota_fp);
	}
	ota_fp = fopen (filePath,"rb");
	if(ota_fp==NULL){
		debug_log(LOG_WARNING_LEVEL,"[%s]fopen err!\n",filePath);
	}
	debug_log(LOG_WARNING_LEVEL,"open %s\n",filePath);
}
void kk_vp_ota_file_update_start(char* file)
{
	if(file == NULL){
		return;
	}
	debug_log(LOG_WARNING_LEVEL,"file=%s\n",file);

	uint8_t data[11] = {0};

	uint32_t f_ver,f_size,crc32;

	f_ver = get_ota_file_version(file);
	f_size = _vp_get_ota_file_size(file);
	crc32 = _vp_get_ota_file_crc32(file);
	
	data[0] = (f_ver>>16)&0xff;
	data[1] = (f_ver>>8)&0xff;
	data[2] = f_ver&0xff;

	data[3] = (f_size>>24)&0xff;
	data[4] = (f_size>>16)&0xff;
	data[5] = (f_size>>8)&0xff;
	data[6] = f_size&0xff;

	data[7] = (crc32>>24)&0xff;
	data[8] = (crc32>>16)&0xff;
	data[9] = (crc32>>8)&0xff;
	data[10] = crc32&0xff;

	kk_vp_cfg_info_set(f_ver,f_size,crc32);
	
	debug_log(LOG_DEBUG_LEVEL,"[LAN->VP]ota file update start,OPCODE=%04X\n",OPCODE_VOICE_OTA_UPGRADE_STATR);
	debug_log(LOG_DEBUG_LEVEL,"File Version=%d.%d.%d,File Size=%d,CRC32 Value=%08X\n",
		(f_ver>>16)&0xff,(f_ver>>8&0xff),f_ver&0xff,f_size,crc32);
	
	vp_send_data_build(OPCODE_VOICE_OTA_UPGRADE_STATR,sizeof(data),data);
	

	open_ota_fd(file);
}
void kk_vp_ota_file_update_stop(uint32_t ver)
{
	uint8_t f_ver[3];
	f_ver[0] = (ver>>16)&0xff;
	f_ver[1] = (ver>>8)&0xff;
	f_ver[2] = ver&0xff;
	
	debug_log(LOG_DEBUG_LEVEL,"[LAN->VP]config file update stop,OPCODE=%04X\n",OPCODE_VOICE_OTA_UPGRADE_STOP);
	vp_send_data_build(OPCODE_VOICE_OTA_UPGRADE_STOP,sizeof(f_ver),f_ver);
}




/////////////////////////////////////////////////////
int kk_vp_opcode_handle(_IN pro_data_t *pro_data)
{
	int i;
	VP_OPCODE_HANDLE *pFunc;

	if(pro_data==NULL){
		return 0;
	}

	pFunc = vp_opcode_table;
	for(i=0;i<sizeof(vp_opcode_table)/sizeof(VP_OPCODE_HANDLE);i++,pFunc++){
		if(pFunc->opcode==pro_data->opcode){
			if(pFunc->func!=NULL){
				debug_log(LOG_DEBUG_LEVEL,"[handle Opcode]%04X\n",pro_data->opcode);
				pFunc->func(pro_data);
				return 1;
			}
		}
	}
	debug_log(LOG_WARNING_LEVEL,"[unknow Opcode]%04X\n",pro_data->opcode);

	return 0;
}





static int kk_vp_config_file_save(_IN cJSON *json)
{
	char *pStr = NULL;
	char *pWrite = NULL;
	FILE *fp = NULL;

	int w_len = 0,length = 0;

	pStr = cJSON_Print(json);
	printf("[%s][%d][vp config file]%s\n",__FUNCTION__,__LINE__,pStr);
	cJSON_Minify(pStr);
	
	length = strlen(pStr);
	pWrite = pStr;

	if((fp= fopen(VP_CONFIG_FILE, "w"))==NULL) {
		debug_log(LOG_WARNING_LEVEL,"[%s] fopen fail\n",VP_CONFIG_FILE);
		return 0;
	}
	
	
	
	while(length>0){
		w_len = fwrite(pWrite, 1, length, fp);
		pWrite+=w_len;
		length -= w_len;
	}

	free(pStr);
	fclose(fp);

	system("sync");
	
	return 1;
}

static _OUT int kk_vp_config_file_update_check(void)
{
	const char *md5_create = "md5sum %s > %s";
	const char *md5_check = "md5sum -c %s";
	const char *tar_cmd = "tar -Pzcvf %s %s";

	char cmd[256] = {0};

	FILE *fp = NULL;
	int ret = 0;
	int updateFlag = 0;
	
	char buf[64] = {0};

	
	if(access(VP_CONFIG_FILE_MD5,F_OK)!=0){
		memset(cmd,0,sizeof(cmd));
		snprintf(cmd,sizeof(cmd),md5_create,VP_CONFIG_FILE,VP_CONFIG_FILE_MD5);
		debug_log(LOG_CRIT_LEVEL,"%s\n",cmd);
		system(cmd);

		updateFlag = 1;
	}else{
		memset(cmd,0,sizeof(cmd));
		snprintf(cmd,sizeof(cmd),md5_check,VP_CONFIG_FILE_MD5);
		debug_log(LOG_CRIT_LEVEL,"%s\n",cmd);
		fp = popen(cmd, "r");

		fread(buf, 1, sizeof(buf), fp);
		printf("execte result:%s",buf);
		pclose(fp);
		
		if(strstr(buf,"OK")==NULL){
			printf("buf:%s\n",buf);
			updateFlag = 1;
			memset(cmd,0,sizeof(cmd));
			snprintf(cmd,sizeof(cmd),md5_create,VP_CONFIG_FILE,VP_CONFIG_FILE_MD5);
			debug_log(LOG_CRIT_LEVEL,"%s\n",cmd);
			system(cmd);
		}
	}

	if(updateFlag!=0){
		memset(cmd,0,sizeof(cmd));
		snprintf(cmd,sizeof(cmd),tar_cmd,VP_CONFIG_FILE_TAR_GZ,VP_CONFIG_FILE);
		debug_log(LOG_CRIT_LEVEL,"%s\n",cmd);
		system(cmd);
	}
	
	return updateFlag;
}


void kk_vp_syncinfo_handle(_IN cJSON *payload)
{
	cJSON *root = NULL;
	int err = 0;

	if((err = kk_vp_syncinfo(payload,kk_vp_get_config_file_version(),&root))!=0){
		printf("[%s][%d]SYNC fail,err=%d\n",__FUNCTION__,__LINE__,err);
	}

	if(kk_vp_config_file_save(root)!=0){
		printf("[%s][%d][vp config file] save.\n",__FUNCTION__,__LINE__);
	}

	if(kk_vp_config_file_update_check()!=0){

		debug_log(LOG_EMERG_LEVEL,"-------------------->start update config file<------------------\n");

		kk_voice_update_config_file();
	}
	
	if(root!=NULL){
		cJSON_Delete(root);
	}
}


static void kk_vp_ota_file_update_start_handle(pro_data_t *pro_data)
{
	uint8_t err;
	uint32_t f_size,crc32;
	
	if(pro_data->args_len==0){
		return ;
	}
	if((err = pro_data->arg[0])==0){
		if(pro_data->args_len!=12){
			return ;
		}
		
		f_size = MK_UINT32(&pro_data->arg[4]);
		crc32 = MK_UINT32(&pro_data->arg[8]);

		//kk_vp_config_file_info_check(f_ver,f_size,crc32);
		
		debug_log(LOG_DEBUG_LEVEL,"[VP->LAN] File Version=%d.%d.%d,File Size=%d,CRC32 Value=%08X\n",
			pro_data->arg[1],pro_data->arg[2],pro_data->arg[3],f_size,crc32);
	}
}

static void kk_vp_ota_file_update_data_req_handle(pro_data_t *pro_data)
{
	int err = 0;
	uint32_t offset;
	uint16_t req_size;

	uint8_t data[1024] = {0};
	uint16_t len = 0;
	uint16_t r_len = 0;
	uint16_t t_len = 0;
	uint8_t *pCrc = NULL;

	uint32_t crc;

	if(pro_data->args_len!=9){
		return ;
	}

	offset = MK_UINT32(&pro_data->arg[3]);
	req_size =  MK_UINT16(&pro_data->arg[7]);
	
	debug_log(LOG_DEBUG_LEVEL,"[VP->LAN]f_ver=%d.%d.%d,offset=%d,req_size=%d\n",pro_data->arg[0],pro_data->arg[1],pro_data->arg[2],offset,req_size);
	if(ota_fp==NULL){
		debug_log(LOG_ERROR_LEVEL,"[ota_fp] NULL!\n");
		err = 1;
	}
	/*
	if(f_ver!=kk_vp_get_config_file_version()){
		printf("[file version] not match!%d,%d\n",f_ver,kk_vp_get_config_file_version());
		err = 2;
	}*/
	
	
	data[len++] = err;
	
	data[len++] = (offset>>24)&0xff;
	data[len++] = (offset>>16)&0xff;
	data[len++] = (offset>>8)&0xff;
	data[len++] = offset&0xff;

	
	data[len++] = (req_size>>8)&0xff;
	data[len++] = req_size&0xff;

	pCrc = &data[len];

	if(err==0){
		int err = fseek(ota_fp, offset, SEEK_SET);
		if(err==0){
			while(req_size>t_len){
				r_len = fread(&data[len], 1, req_size, ota_fp);
				if(r_len>0){
					t_len+=r_len;
					len += r_len;
				}else{
					break;
				}
			}
		}else{
			debug_log(LOG_ERROR_LEVEL,"[fseek fail]offset=%d\n",offset);
		}
	}
	
	crc = CreateCrc32(pCrc, req_size);
	data[len++] = (crc>>24)&0xff;
	data[len++] = (crc>>16)&0xff;
	data[len++] = (crc>>8)&0xff;
	data[len++] = crc&0xff;

	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_VOICE_OTA_REQUEST,len,data);
	usleep(100*1000);
}


static void kk_vp_ota_file_update_stop_handle(pro_data_t *pro_data)
{
	uint8_t err,status;
	uint32_t ver;

	if(pro_data->args_len==0){
		return ;
	}

	if((err = pro_data->arg[0])==0){
		if(pro_data->args_len!=4){
			return ;
		}
		ver = MK_VERSION(&pro_data->arg[1]);
		debug_log(LOG_DEBUG_LEVEL,"[VP OTA STOP] ver=%d.%d.%d\n",pro_data->arg[1],pro_data->arg[2],pro_data->arg[3]);
	}
}
static int kk_voice_ota_finish_notify(char *ver)
{
	cJSON * root=cJSON_CreateObject();
	cJSON_AddStringToObject(root, "nodeid", "*");
	cJSON_AddStringToObject(root, "opcode", VOICE_OTA_FINISH);
	cJSON_AddStringToObject(root, "status", "success");
	cJSON_AddStringToObject(root, "arg", ver);
	send_msg_to_module(root);	
	cJSON_Delete(root);	
	return 0;
}
static void kk_vp_ota_file_update_status_handle(pro_data_t *pro_data)
{
	int err = 0;
	int ver;
	char verBuf[16] = {0};
	unsigned char status;

	if(pro_data->args_len!=4){
		return ;
	}
	
	ver = MK_UINT24(&pro_data->arg[0]);
	status = pro_data->arg[3];

	if(status==0x00){
		
		sprintf(verBuf,"%d.%d.%d",pro_data->arg[0],pro_data->arg[1],pro_data->arg[2]);
		kk_vp_voice_version_set(verBuf,strlen(verBuf));
		kk_voice_ota_finish_notify(verBuf);
		debug_log(LOG_NOTICE_LEVEL,"\n*********************OTA SUCCESS******************\n");
		kk_voice_reset_ver_flag();
	}

	debug_log(LOG_DEBUG_LEVEL,"\nver=%d.%d.%d,status=%d\n",pro_data->arg[0],pro_data->arg[1],pro_data->arg[2],status);


	uint8_t data[5] = {0};
	data[0] = err;
	data[1] = (ver>>16)&0xff;
	data[2] = (ver>>8)&0xff;
	data[3] = ver&0xff;
	data[4] = status;

	vp_reply_data_build(pro_data->seq,pro_data->ch,OPCODE_VOICE_OTA_STATUS_NOTIFY,sizeof(data),data);

	//kk_vp_update_result_check(status,ver);

}

static void kk_vp_ota_info_query_handle(pro_data_t *pro_data)
{
	uint8_t err;
	uint32_t f_ver;
	

	if(pro_data->args_len!=4) {
		return ;
	}

	if((err = pro_data->arg[0])==0) {
		
		f_ver = MK_UINT24(&pro_data->arg[1]); 

		debug_log(LOG_DEBUG_LEVEL,"[VP->LAN] OTA File Version=%d.%d.%d\n",pro_data->arg[0],pro_data->arg[1],pro_data->arg[2]);

		//kk_vp_cfg_info_check(f_ver,f_size,crc32);
	}

}

static void kk_voice_switch_handle(pro_data_t *pro_data)
{
	int err = 0;
	int ver;
	unsigned char status;
	
	if((err = pro_data->arg[0])==0) {
		debug_log(LOG_DEBUG_LEVEL,"switch=%d\n",pro_data->arg[1]);
	}

}

static void kk_voice_volume_handle(pro_data_t *pro_data)
{
	int err = 0;
	int ver;
	unsigned char status;
	char vol[8] = {0};

	if((err = pro_data->arg[0])==0) {
		debug_log(LOG_DEBUG_LEVEL,"volume=%d\n",pro_data->arg[1]);
		sprintf(vol,"%d",pro_data->arg[1]);
		cJSON *root = cJSON_CreateObject();
		cJSON_AddStringToObject(root,"node","*");
		cJSON_AddStringToObject(root,"opcode","VOLUME_CTRL");
		cJSON_AddStringToObject(root,"arg",vol);
		cJSON_AddStringToObject(root,"status","success");
		send_msg_to_module(root);
		cJSON_Delete(root);
	}
}
#endif


