#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"

#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 uint16_t _g_seq;
static FILE *update_fp = NULL;


#define VP_CH			0
#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 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}
};




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 
{
	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;

	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;
	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++;

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

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

	return pScene->map_id;
}

int vp_scene_id_item_load(int scene_id,uint16_t map_id)
{
	VP_SCENE_MAP *ptr = 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;

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

	
	if(vp_scene_map == NULL){
		vp_scene_map = pScene;
	}else{
		vp_scene_map->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"
#define VP_SCENE_ID_FILE						"scene_id_map.json"

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);
	printf("[%s][%d][vp scene id file]%s\n",__FUNCTION__,__LINE__,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){
		printf("open err.\n");
		return ;
	}

	printf("vp_scene_id_map_load\n");

	fseek (fp, 0, SEEK_END);
	size=ftell(fp);
	printf("size=%d\n",size);

	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(uint16_t opCode,uint8_t len,uint8_t *data)
{
	uint8_t data_buf[256] = {0};
	uint8_t 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);

	printf("\n*********************************\n");
	printf("[send] len=%d\n",data_len);
	for(int i=0;i<data_len;i++){
		printf("%02X ",data_buf[i]);
	}
	printf("\n");
	eSerial_WriteBuffer(data_buf, data_len);
}

void vp_reply_data_build(uint16_t seq,uint8_t ch,uint16_t opCode,uint8_t len,uint8_t *data)
{
	uint8_t data_buf[256] = {0};
	uint8_t 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);

	printf("\n*********************************\n");
	printf("[reply] len=%d\n",data_len);
	for(int i=0;i<data_len;i++){
		printf("%02X ",data_buf[i]);
	}
	printf("\n\n");
	eSerial_WriteBuffer(data_buf, data_len);
}




























int _vp_get_cfg_file_size(void)
{
	int size = 0;
	FILE *fp = NULL;
	
	fp = fopen (VP_CONFIG_FILE_TAR_GZ,"r");
	if(fp==NULL){
		perror ("open err");
		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){
		printf("open err.\n");
		return ;
	}

	fseek (fp, 0, SEEK_END);
	size=ftell(fp);
	printf("size=%d\n",size);

	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;
			printf("[remain] 0 \n",remain);
			pRead[size] = '\0';
		}
	}
	crc32 = CreateCrc32(buff, size);
	printf("crc32=%x\n",crc32);
	
	free(buff);
	fclose(fp);

	return crc32;
}

static void vp_open_fd()
{
	update_fp = fopen (VP_CONFIG_FILE_TAR_GZ,"rb");
	if(update_fp==NULL){
		printf("update_fp open err.\n");
	}
}
static void vp_close_fd()
{
	if(update_fp!=NULL){
		fclose (update_fp);
	}
}




























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_vp_set_state_machine(SET_8009_SYSTEM);
		kk_vp_set_config_file_version(f_ver);
		
		VP_RECV_PRINT("\n[VP->LAN]sv=%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);
	}
}

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;

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

	//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_RECV_PRINT("\n[vp snapshoot get]\n");
	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[256]={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);
	
	VP_RECV_PRINT("[VP]execute scene!",sceneNum);
	printf("sceneNum=%d\n",sceneNum);
	for(i=0;i<sceneNum;i++){
		sceneAry[i] = MK_UINT16(&pro_data->arg[1+2*i]);
		printf("scene %d:%d\n",i,sceneAry[i]);
	}
	
	VP_RECV_PRINT("\n[vp call scene]\n");

	for(i=0;i<sceneNum;i++){
		if((sceneId = vp_scene_id_get_scene_id(sceneAry[i]))!=-1){
			printf("1...\n");
			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;
		}
	}
	printf("2...\n");
	if(off!=0){
		data[0] = 0x00;
	}else{
		data[0] = 1;
	}
	printf("3...\n");
	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_vp_set_state_machine(GET_8009_CONFIG_FILE_INFO);
	VP_RECV_PRINT("\n[VP->LAN]%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 = gmtime(&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;
	
	VP_RECV_PRINT("\n[vp system time get reply]%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 i=0;
	uint8_t devNum = 0;
	uint32_t *nodeIdAry = NULL;
	uint32_t *OperatorIdAry = NULL;
	uint8_t skillType;
	VP_RECV_PRINT("\n\n******************0x010B***********************\n\n");
	if((devNum =  pro_data->arg[0])!=0){
		nodeIdAry = malloc(sizeof(uint32_t)*devNum);
		OperatorIdAry = malloc(sizeof(uint32_t)*devNum);
		printf("devNum=%d",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];
			VP_RECV_PRINT("[Node Id %d] %08x",i,nodeIdAry[i]);
			VP_RECV_PRINT("[Operator Id %d] %08x",i,OperatorIdAry[i]);
		}

		skillType = pro_data->arg[1+8*i];
		VP_RECV_PRINT("[skillType] %02x",skillType);

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



		uint8_t data[256]={0};
		memset(data,0,sizeof(data));
		data[0] = 0x00;
		data[1] = devNum;
		//todo:根据实际的执行
		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);
	}

	//OPCODE_ACTION_NOTIFY
}

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);
		
		VP_RECV_PRINT("\n[cfg file update notify ack]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)
{
	uint8_t err = 0;
	uint32_t f_ver,offset;
	uint16_t req_size;

	uint8_t data[256] = {0};
	uint8_t len = 0;
	uint8_t r_len = 0;
	uint8_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]);
	
	VP_RECV_PRINT("\n[vp config file req]f_ver=%d,offset=%d,req_size=%d\n",f_ver,offset,req_size);
	if(update_fp==NULL){
		printf("[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];
	printf("-------->=%d\n",len);
	if(err==0){
		int 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);
				printf("r_len=%d\n",r_len);
				if(r_len>=0){
					t_len+=r_len;
					len += r_len;
				}else{
					break;
				}
			}
		}else{
			printf("[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;
	printf("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]);
		VP_RECV_PRINT("\n[vp config file update stop ack] version=%d\n",ver);
	}else{
		printf("err=%d\n",ver);
	}

	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];


	
	
	VP_RECV_PRINT("\n[config file update status]ver=%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_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]);
		VP_RECV_PRINT("[VP->LAN]File Version=%08x,File Size=%08x,CRC32=%08x\n",f_ver,f_size,crc32);

		kk_vp_cfg_info_check(f_ver,f_size,crc32);
	}else{
		printf("");
	}

}

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

void kk_vp_get_8009_snapshoot(void)
{
	uint8_t res[1] = {0};
	VP_SEND_PRINT("[LAN->VP]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 = gmtime(&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;

	VP_SEND_PRINT("[LAN->VP]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);
	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);
	
	VP_SEND_PRINT("[cfg file update notify]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;
	
	VP_SEND_PRINT("[vp config file update stop] version=%d\n",ver);
	
	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};
	VP_SEND_PRINT("[config file info get]\n");
	vp_send_data_build(OPCODE_CONFIG_FILE_INFO_GET,sizeof(res),res);
}


/////////////////////////////////////////////////////
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){
				printf("[%s][%d][vp handle opcode]%04X\n",__FUNCTION__,__LINE__,pro_data->opcode);
				pFunc->func(pro_data);
				return 1;
			}
		}
	}
	printf("[%s][%d][vp unknow opcode]%04X\n",__FUNCTION__,__LINE__,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) {
		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);
		EXECUTE_CMD(cmd);
		system(cmd);

		updateFlag = 1;
	}else{
		memset(cmd,0,sizeof(cmd));
		snprintf(cmd,sizeof(cmd),md5_check,VP_CONFIG_FILE_MD5);
		EXECUTE_CMD(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);
			EXECUTE_CMD(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);
		EXECUTE_CMD(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){
		printf("[%s][%d][vp config file] update.\n",__FUNCTION__,__LINE__);
		kk_vp_set_updateFlag(1);
	}
	
	if(root!=NULL){
		cJSON_Delete(root);
	}
}







