/*
 * UnitProtocol.c
 *
 *  Created on: 2019年11月28日
 *      Author: yt
 */


#include <time.h>
#include <sys/time.h>
#include <string.h>

bool set_systime(int year, int mon, int day, int hour, int min, int sec)
{
	int i;
	time_t t;
	struct tm _tm;
	struct timeval tv;
	_tm.tm_year = year-1900;
	_tm.tm_mon = mon-1;
	_tm.tm_mday = day;
	_tm.tm_hour = hour;
	_tm.tm_min = min;
	_tm.tm_sec = sec;
	t = mktime(&_tm);
	tv.tv_sec = t;
	tv.tv_usec = 0;
	if(settimeofday(&tv,(struct timezone *)0)<0){
		return false;
	}
	system("hwclock -w");
	chk_time();
	for(i=0;i<16;i++){
		if(unitShm->ThreadEnabled[i]==0x01)
			unitShm->ThreadUpdatetime[i] = unitShm->dataTime.Time_C;
	}
	return true;
}

bool chk_frame(unsigned char *data, int len)
{
	int i,crc = 0;
	unsigned short dataLen;
	if((len>=14)&&((data[0]&0xff)==0x7e)&&((data[1]&0xff)==0x10)
			&&((data[len-1]&0xff)==0xe7)){
		for(i=1;i<(len-2);i++)
			crc += (data[i]&0xff);
//		printf("chkframe: crc %02x-%02x\n",(crc&0xff),data[len-2]&0xff);
		if((data[len-2]&0xff)==(crc&0xff)){
			dataLen = ((data[2]&0x00ff)<<8)|(data[3]&0x00ff);
			if(len==(dataLen+14))
				return true;
		}
	}
	return false;
}

void mkCommCmd(unsigned char *cmd, unsigned char *data, unsigned char cmdCode, int dataLen)
{
	int cur=0,crc=0;
	int i;
	cmd[cur++] = 0x7e;
	cmd[cur++] = 0x10;
	cmd[cur++] = ((dataLen>>8)&0xff);
	cmd[cur++] = dataLen&0xff;
	cmd[cur++] = cmdCode;
	cmd[cur++] = (((unitShm->dataTime.Year/1000)&0x0f)<<4)
			|(((unitShm->dataTime.Year%1000)/100)&0x0f);
	cmd[cur++] = ((((unitShm->dataTime.Year%100)/10)&0x0f)<<4)
			|((unitShm->dataTime.Year%10)&0x0f);
	cmd[cur++] = (((unitShm->dataTime.Month/10)&0x0f)<<4)
			|((unitShm->dataTime.Month%10)&0x0f);
	cmd[cur++] = (((unitShm->dataTime.Day/10)&0x0f)<<4)
			|((unitShm->dataTime.Day%10)&0x0f);
	cmd[cur++] = (((unitShm->dataTime.Hour/10)&0x0f)<<4)
			|((unitShm->dataTime.Hour%10)&0x0f);
	cmd[cur++] = (((unitShm->dataTime.Minute/10)&0x0f)<<4)
			|((unitShm->dataTime.Minute%10)&0x0f);
	cmd[cur++] = (((unitShm->dataTime.Second/10)&0x0f)<<4)
			|((unitShm->dataTime.Second%10)&0x0f);
	for(i=0;i<dataLen;i++)
		cmd[cur++] = data[i];
	cmd[cur] = 0x00;
	cmd[cur+1] = 0xe7;
	for(i=1;i<cur;i++)
		crc += cmd[i];
	cmd[cur] = crc&0xff;
}

int mkHeartBeatCmd(unsigned char *cmd)
{
	int datalen = 0;
	unsigned char data[256];
	unsigned char CMD = 0x01;
	mkCommCmd(cmd,data,CMD,datalen);
	return datalen+14;
}

int mkDeviceIDQryRtn(unsigned char *cmd)
{
	int i,cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x83;

	int devidLen = (int)(strlen(unitShm->UnitId));
	int datalen = devidLen+4;
	data[cur++] = 0x01;
	data[cur++] = (devidLen>>8)&0xff;
	data[cur++] = devidLen&0xff;
	for(i=0;i<devidLen;i++)
		data[cur++] = unitShm->UnitId[i];
	data[cur] = 0x00;
	mkCommCmd(cmd,data,CMD,datalen);
	return datalen+14;
}

int mkDeviceIDSetRtn(unsigned char *inData, int inLen, unsigned char *cmd)
{
	int i=0;
	unsigned char data[256];
	unsigned char CMD = 0x83;
	int datalen = 1;
	unsigned short devidLen = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
	if((inLen>=(devidLen+18))&&(devidLen<=32)){
		for(i=0;i<devidLen;i++)
			unitShm->UnitId[i] = inData[15+i];
		if(devidLen<32)
			unitShm->UnitId[devidLen] = 0x00;
		unitShm->UnSavedFalg[OFFSET_UNITID] = 0x01;
		data[0] = 0x01;
		mkCommCmd(cmd,data,CMD,datalen);
		return datalen+14;
	}
	return 0;
}

int mkTimeSetRtn(unsigned char *inData, int inLen, unsigned char *cmd)
{
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x83;
	int datalen = 0;
	bool idchk = true;
	unsigned short devidLen = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
	if((inLen==(devidLen+25))&&(devidLen>0)&&(devidLen<=32)){
		for(i=0;i<devidLen;i++){
			if(unitShm->UnitId[i]!=inData[15+i]){
				idchk = false;
				break;
			}
		}
		if(idchk){
			int year = ((inData[16+devidLen]>>4)&0x0f)*1000
					+(inData[16+devidLen]&0x0f)*100
					+((inData[17+devidLen]>>4)&0x0f)*10
					+(inData[17+devidLen]&0x0f);
			int mon = ((inData[18+devidLen]>>4)&0x0f)*10
					+(inData[18+devidLen]&0x0f);
			int day = ((inData[19+devidLen]>>4)&0x0f)*10
					+(inData[19+devidLen]&0x0f);
			int hour = ((inData[20+devidLen]>>4)&0x0f)*10
					+(inData[20+devidLen]&0x0f);
			int min = ((inData[21+devidLen]>>4)&0x0f)*10
					+(inData[21+devidLen]&0x0f);
			int sec = ((inData[22+devidLen]>>4)&0x0f)*10
					+(inData[22+devidLen]&0x0f);
			if(set_systime(year,mon,day,hour,min,sec)){
				datalen = devidLen+4;
				data[cur++] = 0x0b;
				data[cur++] = inData[13];
				data[cur++] = inData[14];
				for(i=0;i<devidLen;i++)
					data[cur++] = inData[15+i];
				data[cur] = 0x00;
				mkCommCmd(cmd,data,CMD,datalen);
				return datalen+14;
			}
		}
	}
	return 0;
}

int mkDevResetRtn(unsigned char *inData, int inLen, unsigned char *cmd)
{
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x83;
	int datalen = 0;
	bool idchk = true;
	unsigned short devidLen = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
	if((inLen==(devidLen+19))&&(devidLen>0)&&(devidLen<=32)){
		for(i=0;i<devidLen;i++){
			if(unitShm->UnitId[i]!=inData[15+i]){
				idchk = false;
				break;
			}
		}
		if(idchk){
			if((inData[17+devidLen]==0x01)||(inData[17+devidLen]==0x00)){
				datalen = devidLen+4;
				data[cur++] = 0x0b;
				data[cur++] = inData[13];
				data[cur++] = inData[14];
				for(i=0;i<devidLen;i++)
					data[cur++] = inData[15+i];
				data[cur] = 0x00;
				mkCommCmd(cmd,data,CMD,datalen);
				if(inData[17+devidLen]==0x01)
					unitShm->UnSavedFalg[65535] = 0x01;
				else
					unitShm->UnSavedFalg[65534] = 0x01;
				return datalen+14;
			}
		}
	}
	return 0;
}

int mkServerQryRtn(unsigned char *inData, int inLen, unsigned char *cmd)
{
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x83;
	int datalen = 0;
	bool idchk = true;
	unsigned short devidLen = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
	if((inLen==(devidLen+18))&&(devidLen>0)&&(devidLen<=32)){
		for(i=0;i<devidLen;i++){
			if(unitShm->UnitId[i]!=inData[15+i]){
				idchk = false;
				break;
			}
		}
		if(idchk){
			datalen = devidLen+10;
			data[cur++] = 0x15;
			data[cur++] = (devidLen>>8)&0xff;
			data[cur++] = devidLen&0xff;
			for(i=0;i<devidLen;i++)
				data[cur++] = unitShm->UnitId[i];
			data[cur++] = 0x00;
			data[cur++] = (unitShm->ServerIP>>24)&0xff;
			data[cur++] = (unitShm->ServerIP>>16)&0xff;
			data[cur++] = (unitShm->ServerIP>>8)&0xff;
			data[cur++] = (unitShm->ServerIP&0xff);
			data[cur++] = (unitShm->ServerPort>>8)&0xff;
			data[cur++] = (unitShm->ServerPort&0xff);
			mkCommCmd(cmd,data,CMD,datalen);
			return datalen+14;
		}
	}
	return 0;
}

int mkServerSetRtn(unsigned char *inData, int inLen, unsigned char *cmd)
{
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x83;
	int datalen = 0;
	bool idchk = true;
	unsigned short devidLen = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
	if((inLen==(devidLen+24))&&(devidLen>0)&&(devidLen<=32)){
		for(i=0;i<devidLen;i++){
			if(unitShm->UnitId[i]!=inData[15+i]){
				idchk = false;
				break;
			}
		}
		if(idchk){
			unitShm->ServerIP = ((inData[17+devidLen]&0x000000ff)<<24)
					|((inData[18+devidLen]&0x000000ff)<<16)
					|((inData[19+devidLen]&0x000000ff)<<8)
					|(inData[20+devidLen]&0x000000ff);
			unitShm->ServerPort = ((inData[21+devidLen]&0x000000ff)<<8)
					|(inData[22+devidLen]&0x000000ff);
			unitShm->UnSavedFalg[OFFSET_SERVERSET] = 0x01;
			datalen = devidLen+4;
			data[cur++] = 0x16;
			data[cur++] = (devidLen>>8)&0xff;
			data[cur++] = devidLen&0xff;
			for(i=0;i<devidLen;i++)
				data[cur++] = unitShm->UnitId[i];
			data[cur++] = 0x00;
			mkCommCmd(cmd,data,CMD,datalen);
			return datalen+14;
		}
	}
	return 0;
}

int mk_ReportCmd(int idx, unsigned char *cmd)
{
	union FC fc;
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x03;
	struct tm *tm_time;
	int year,mon,day,hour,min,sec;
	int datalen = 0;
	int devidLen = 0;
	float x = 1.0;
	unsigned short pno = 0;
	if(idx>2047)
		return 0;
	pno = unitShm2->report[idx].Pno;
//	if(unitShm2->spoint[pno].SensorType=='L')
//		x = 0.001;
	printf("report: %s %d\n",unitShm2->spoint[pno].ServiceNo,unitShm2->report[idx].Port);
	devidLen = (int)(strlen(unitShm2->spoint[pno].ServiceNo))+1;
	if(devidLen==0)
		return 0;
	datalen = devidLen+20;
	data[cur++] = 0x41;
	data[cur++] = (idx>>8)&0xff;
	data[cur++] = idx&0xff;
	data[cur++] = (devidLen>>8)&0xff;
	data[cur++] = devidLen&0xff;
	for(i=0;i<(devidLen-1);i++)
		data[cur++] = unitShm2->spoint[pno].ServiceNo[i];
	data[cur++] = 0x30+unitShm2->report[idx].Port;
	data[cur++] = 0x00;
	data[cur++] = 0x00;
	data[cur++] = unitShm2->report[idx].Type;
	data[cur++] = unitShm2->report[idx].Status;
	fc.f = unitShm2->report[idx].RealtimeValue * x;
	data[cur++] = fc.c[3];
	data[cur++] = fc.c[2];
	data[cur++] = fc.c[1];
	data[cur++] = fc.c[0];
	tm_time = gmtime(&(unitShm2->report[idx].UpdateTime));
	year = 1900+tm_time->tm_year;
	mon = 1+tm_time->tm_mon;
	day = tm_time->tm_mday;
	hour = tm_time->tm_hour;
	min = tm_time->tm_min;
	sec = tm_time->tm_sec;
	data[cur++] = (((year/1000)&0x0f)<<4)|(((year%1000)/100)&0x0f);
	data[cur++] = ((((year%100)/10)&0x0f)<<4)|((year%10)&0x0f);
	data[cur++] = (((mon/10)&0x0f)<<4)|((mon%10)&0x0f);
	data[cur++] = (((day/10)&0x0f)<<4)|((day%10)&0x0f);
	data[cur++] = (((hour/10)&0x0f)<<4)|((hour%10)&0x0f);
	data[cur++] = (((min/10)&0x0f)<<4)|((min%10)&0x0f);
	data[cur++] = (((sec/10)&0x0f)<<4)|((sec%10)&0x0f);
	mkCommCmd(cmd,data,CMD,datalen);
	return datalen+14;
}

int mk_RealdataCmd(int idx, unsigned char *cmd)
{
	union FC fc;
	int i=0, cur=0;
	int year,mon,day,hour,min,sec;
	unsigned char data[256];
	unsigned char CMD = 0x03;
	int datalen = 0;
	int devidLen = 0;
	struct tm *tm_time;
	float x = 1.0;
//	if(((idx>=0)&&(idx<(int)unitShm->UnSavedFalg[OFFSET_MAXNUM+0]))
//			||((idx>=256)&&(idx<(256+(int)unitShm->UnSavedFalg[OFFSET_MAXNUM+1])))
//			||((idx>=512)&&(idx<(512+(int)unitShm->UnSavedFalg[OFFSET_MAXNUM+2])))
//			||((idx>=768)&&(idx<(768+(int)unitShm->UnSavedFalg[OFFSET_MAXNUM+3]))))
	{
//		if(unitShm2->spoint[idx].SensorType=='L')
//			x = 0.001;
		devidLen = (int)(strlen(unitShm2->spoint[idx].ServiceNo))+1;
		if(devidLen==0)
			return 0;
		datalen = devidLen+18;
		data[cur++] = 0x43;
		data[cur++] = (devidLen>>8)&0xff;
		data[cur++] = devidLen&0xff;
		for(i=0;i<(devidLen-1);i++)
			data[cur++] = unitShm2->spoint[idx].ServiceNo[i];
		data[cur++] = 0x31;
		data[cur++] = 0x00;
		data[cur++] = 0x00;
		data[cur++] = 0x00;
		data[cur++] = 0x00;
		fc.f = unitShm2->spoint[idx].CurrentLeak * x;
		data[cur++] = fc.c[3];
		data[cur++] = fc.c[2];
		data[cur++] = fc.c[1];
		data[cur++] = fc.c[0];
		tm_time = gmtime(&(unitShm2->spoint[idx].UpdateTime));
		year = 1900+tm_time->tm_year;
		mon = 1+tm_time->tm_mon;
		day = tm_time->tm_mday;
		hour = tm_time->tm_hour;
		min = tm_time->tm_min;
		sec = tm_time->tm_sec;
		data[cur++] = (((year/1000)&0x0f)<<4)|(((year%1000)/100)&0x0f);
		data[cur++] = ((((year%100)/10)&0x0f)<<4)|((year%10)&0x0f);
		data[cur++] = (((mon/10)&0x0f)<<4)|((mon%10)&0x0f);
		data[cur++] = (((day/10)&0x0f)<<4)|((day%10)&0x0f);
		data[cur++] = (((hour/10)&0x0f)<<4)|((hour%10)&0x0f);
		data[cur++] = (((min/10)&0x0f)<<4)|((min%10)&0x0f);
		data[cur++] = (((sec/10)&0x0f)<<4)|((sec%10)&0x0f);
		mkCommCmd(cmd,data,CMD,datalen);
		return datalen+14;
	}
	return 0;
}

int mk_RecordCmd(int d,int n,int m, unsigned char *cmd)
{
	union FC fc;
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x03;
	struct tm *tm_time;
	int year,mon,day,hour,min,sec;
	int datalen = 0;
	int devidLen = 0;
//	int d = (idx>>15)&0x01;
//	int n = (idx>>10)&0x1f;
//	int m = idx&0x03ff;
	float x = 1.0;
//	if(idx>65535)
//		return 0;
//	if(unitShm2->spoint[m].SensorType=='L')
//		x = 0.001;
	devidLen = (int)(strlen(unitShm2->spoint[m].ServiceNo))+1;
	if(devidLen==0)
		return 0;
	datalen = devidLen+46;
	data[cur++] = 0x42;
	data[cur++] = (m>>8)&0xff;
	data[cur++] = m&0xff;
	data[cur++] = (devidLen>>8)&0xff;
	data[cur++] = devidLen&0xff;
	for(i=0;i<(devidLen-1);i++)
		data[cur++] = unitShm2->spoint[m].ServiceNo[i];
	data[cur++] = 0x31;
	data[cur++] = 0x00;
	data[cur++] = 0x00;
	data[cur++] = unitShm2->record[d][n][m].Type;
	data[cur++] = unitShm2->record[d][n][m].IoValue;
	fc.f = unitShm2->record[d][n][m].RealtimeValue * x;
	data[cur++] = fc.c[3];
	data[cur++] = fc.c[2];
	data[cur++] = fc.c[1];
	data[cur++] = fc.c[0];
	fc.f = unitShm2->record[d][n][m].AveValue * x;
	data[cur++] = fc.c[3];
	data[cur++] = fc.c[2];
	data[cur++] = fc.c[1];
	data[cur++] = fc.c[0];
	tm_time = gmtime(&(unitShm2->record[d][n][m].UpdateTime));
	year = 1900+tm_time->tm_year;
	mon = 1+tm_time->tm_mon;
	day = tm_time->tm_mday;
	hour = tm_time->tm_hour;
	min = tm_time->tm_min;
	sec = tm_time->tm_sec;
//	if(hour!=n)
//		return 0;
	data[cur++] = (((year/1000)&0x0f)<<4)|(((year%1000)/100)&0x0f);
	data[cur++] = ((((year%100)/10)&0x0f)<<4)|((year%10)&0x0f);
	data[cur++] = (((mon/10)&0x0f)<<4)|((mon%10)&0x0f);
	data[cur++] = (((day/10)&0x0f)<<4)|((day%10)&0x0f);
	data[cur++] = (((hour/10)&0x0f)<<4)|((hour%10)&0x0f);
	data[cur++] = (((min/10)&0x0f)<<4)|((min%10)&0x0f);
	data[cur++] = (((sec/10)&0x0f)<<4)|((sec%10)&0x0f);
	fc.f = unitShm2->record[d][n][m].MaxValue * x;
	data[cur++] = fc.c[3];
	data[cur++] = fc.c[2];
	data[cur++] = fc.c[1];
	data[cur++] = fc.c[0];
	tm_time = gmtime(&(unitShm2->record[d][n][m].MaxTime));
	year = 1900+tm_time->tm_year;
	mon = 1+tm_time->tm_mon;
	day = tm_time->tm_mday;
	hour = tm_time->tm_hour;
	min = tm_time->tm_min;
	sec = tm_time->tm_sec;
	if(hour!=n)
		return 0;
	data[cur++] = (((year/1000)&0x0f)<<4)|(((year%1000)/100)&0x0f);
	data[cur++] = ((((year%100)/10)&0x0f)<<4)|((year%10)&0x0f);
	data[cur++] = (((mon/10)&0x0f)<<4)|((mon%10)&0x0f);
	data[cur++] = (((day/10)&0x0f)<<4)|((day%10)&0x0f);
	data[cur++] = (((hour/10)&0x0f)<<4)|((hour%10)&0x0f);
	data[cur++] = (((min/10)&0x0f)<<4)|((min%10)&0x0f);
	data[cur++] = (((sec/10)&0x0f)<<4)|((sec%10)&0x0f);
	fc.f = unitShm2->record[d][n][m].MinValue * x;
	data[cur++] = fc.c[3];
	data[cur++] = fc.c[2];
	data[cur++] = fc.c[1];
	data[cur++] = fc.c[0];
	tm_time = gmtime(&(unitShm2->record[d][n][m].MinTime));
	year = 1900+tm_time->tm_year;
	mon = 1+tm_time->tm_mon;
	day = tm_time->tm_mday;
	hour = tm_time->tm_hour;
	min = tm_time->tm_min;
	sec = tm_time->tm_sec;
	if(hour!=n)
		return 0;
	data[cur++] = (((year/1000)&0x0f)<<4)|(((year%1000)/100)&0x0f);
	data[cur++] = ((((year%100)/10)&0x0f)<<4)|((year%10)&0x0f);
	data[cur++] = (((mon/10)&0x0f)<<4)|((mon%10)&0x0f);
	data[cur++] = (((day/10)&0x0f)<<4)|((day%10)&0x0f);
	data[cur++] = (((hour/10)&0x0f)<<4)|((hour%10)&0x0f);
	data[cur++] = (((min/10)&0x0f)<<4)|((min%10)&0x0f);
	data[cur++] = (((sec/10)&0x0f)<<4)|((sec%10)&0x0f);
	mkCommCmd(cmd,data,CMD,datalen);
	return datalen+14;
}

int chk_protocol(unsigned char *inData, int inLen, unsigned char *outData)
{
	if(chk_frame(inData,inLen)){
		if(inData[4]==0x81)
			return 0;
		else if((inLen>=14)&&(inData[4]==0x83)){
			switch(inData[12]){
			case 0x01:
				return mkDeviceIDQryRtn(outData);
				break;
			case 0x02:
				return mkDeviceIDSetRtn(inData,inLen,outData);
				break;
			case 0x0b:
				return mkTimeSetRtn(inData,inLen,outData);
				break;
			case 0x0c:
				return mkDevResetRtn(inData,inLen,outData);
				break;
			case 0x15:
				return mkServerQryRtn(inData,inLen,outData);
				break;
			case 0x16:
				return mkServerSetRtn(inData,inLen,outData);
				break;
			case 0x40:
				return 0;
				break;
			case 0x41:
			{
				int idx = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
				unitShm2->report[idx].Send = 0x01;
				unitShm2->report[idx].UnSaved = 0x01;
				return 0;
			}
				break;
			case 0x42:
			{
				int idx = ((inData[13]&0x00ff)<<8)|(inData[14]&0x00ff);
				int d = (idx>>15)&0x01;
				int h = (idx>>10)&0x1f;
				int i = idx&0x03ff;
				unitShm2->record[d][h][i].Send = 0x01;
				unitShm2->record[d][h][i].UnSaved = 0x01;
				return 0;
			}
				break;
			default:break;
			}
		}
	}
	return 0;
}

int mkDeviceRegistCmd(unsigned char *cmd){
	int i=0, cur=0;
	unsigned char data[256];
	unsigned char CMD = 0x03;
	int datalen = 0;
	int IEMILen = strlen(unitShm->IMEI);
	int IMSILen = strlen(unitShm->IMSI);
	int DevLen = strlen(unitShm->UnitId);
	datalen = IEMILen+IMSILen+DevLen+11;
	data[cur++] = 0x40;
	data[cur++] = (IEMILen>>8)&0xff;
	data[cur++] = (IEMILen&0xff);
	for(i=0;i<IEMILen;i++)
		data[cur++] = unitShm->IMEI[i]&0xff;
	data[cur++] = 0x00;
	data[cur++] = (IMSILen>>8)&0xff;
	data[cur++] = (IMSILen&0xff);
	for(i=0;i<IMSILen;i++)
		data[cur++] = unitShm->IMSI[i]&0xff;
	data[cur++] = 0x00;
	data[cur++] = (DevLen>>8)&0xff;
	data[cur++] = (DevLen&0xff);
	for(i=0;i<DevLen;i++)
		data[cur++] = unitShm->UnitId[i]&0xff;
	data[cur++] = 0x00;
	data[cur++] = unitShm->UnSavedFalg[OFFSET_CSQ];
	mkCommCmd(cmd,data,CMD,datalen);
	return datalen+14;
}
