📄 mpgb.cpp
字号:
//#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "StdAfx.h"
#include "MPGB.h"
int CMPGB::FormReadDataFrame(BYTE *buff, int item , BYTE * addr){
int m_Item = CheckItem( item );//判断抄表项是否有效?无效返回0
if(m_Item == 0)//
return 0;
BYTE DI0 = m_Item & 0xFF;
BYTE DI1 = (m_Item >> 8) & 0xFF ;
buff[0] = 0xfe;
buff[1] = 0x68;
for(int i = 0;i < 6;i++)
buff[2 + i] = addr[ i ];
buff[8] = 0x68;
buff[9] = 0x01;//控制码
buff[10] = 0x02; //数据长度
buff[11] = DI0 + 0x33;
buff[12] = DI1 + 0x33;
buff[13] = GetCheckSum(buff+1, 12);
buff[14] = 0x16;
buff[15] = 0x00;
return 16;//数据帧长度
}
int CMPGB::FormCheckClock(BYTE *buff,time_t *m_time,BYTE *addr)//设置电表时钟
{
tm *pTime;
if(m_time == NULL)
{
time_t t;
time( &t );
pTime = localtime(&t);
}
else
{
pTime = localtime(m_time);
}
buff[0] = 0xfe;
buff[1] = 0x68;
for(int i = 2;i < 8; i++)
buff[ i ] = 0x99;//广播命令地址
buff[8] = 0x68;
buff[9] = 0x08;//控制码
buff[10] = 0x06; //数据长度
buff[11] = TranHexToBcd( pTime ->tm_sec ) + 0x33;//0~59
buff[12] = TranHexToBcd( pTime ->tm_min ) + 0x33;//0~59
buff[13] = TranHexToBcd( pTime ->tm_hour) + 0x33;//0~23
buff[14] = TranHexToBcd( pTime ->tm_mday) + 0x33;//1~31
buff[15] = TranHexToBcd( pTime ->tm_mon + 1) + 0x33;//0~11 + 1
buff[16] = TranHexToBcd( pTime ->tm_year - 100) + 0x33;//since 1900 year - 100 = since 2003
buff[17] = GetCheckSum(&buff[ 1 ], 16);
buff[18] = 0x16;
buff[19] = 0x00;
return 20;//// LEN数据帧长度
}
int CMPGB::FormSetAddress(BYTE *buff, BYTE *addr)//设置电表地址
{
buff[0] = 0xfe;
buff[1] = 0x68;
for(int i = 2;i < 8; i++)
buff[ i ] = 0x99;//广播命令地址
buff[8] = 0x68;
buff[9] = 0x0A;//控制码
buff[10] = 0x06; //数据长度
buff[11] = addr[ 0 ] + 0x33;//0~59
buff[12] = addr[ 1 ] + 0x33;//0~59
buff[13] = addr[ 2 ] + 0x33;//0~23
buff[14] = addr[ 3 ] + 0x33;//1~31
buff[15] = addr[ 4 ] + 0x33;//0~11 + 1
buff[16] = addr[ 5 ] + 0x33;//since 1900 year - 100 = since 2003
buff[17] = GetCheckSum(buff + 1, 16);
buff[18] = 0x16;
buff[19] = 0x00;
return 20;
}
int CMPGB::ProcReturnedFrame(BYTE *inbuff, int inLen,int item, BYTE *outbuff,int &outlen,BYTE *addr){
int i =0;
while( i < (inLen - 12))////2*0x68 + 6 * adr + 1 * 0x16 + 1 * crc + 1*Len + 1* control
{
if(inbuff[i] == 0x68 && inbuff[i + 7] == 0x68)//找到数据帧头部
{
break;
}
i++;
}
if(i >= (inLen - 14))//在有效数据长度内没有找到同步字
{
return 0x0100;//数据长度不正确
}
BYTE *pData = &inbuff[i];//数据起始
BYTE Len = pData[9] + 10 + 2;//2*0x68 + 6 * adr + 1 * 0x16 + 1 * crc + 1*Len + 1* control
if(Len > inLen - i)
{
return 0x0100;
}
if(pData[Len - 1] != 0x16)
{
return 0x0200;//没有结束标志
}
BYTE m_check = GetCheckSum(pData,Len - 2);
if(m_check != pData[Len - 2])
{
return 0x0300; //校验和不对
}
return ProcFullFrame(pData, item,outbuff, outlen, addr);//处理完整的数据返回
}
int CMPGB::CheckItem(int Item_data)
{
int data = Item_data & 0xFFFF;
char LoBYTE = Item_data & 0xFF;
char HiBYTE = ( Item_data & 0xFF00 ) >> 8;
char LoBCD = LoBYTE & 0x0F;
char HiBCD = (LoBYTE & 0xF0) >> 4;
switch(HiBYTE & 0xFF)
{
case 0x90://当前正向有功、反向有功总
case 0x94://上月正向有功、反向有功总
case 0x98://上上月正向有功、反向有功总
case 0xA0://当前正向有功、反向有功总最大需量
case 0xA4://上月正向有功、反向有功总最大需量
case 0xA8://上上月正向有功、反向有功总最大需量
case 0xB0://当前正向有功、反向有功总最大需量发生的时间
case 0xB4://上月正向有功、反向有功总最大需量发生的时间
case 0xB8://上上月正向有功、反向有功总最大需量发生的时间
if( LoBYTE >= 0x10 && LoBYTE <= 0x2F )
return data;
break;
case 0x91://当前正向无功、反向无功,及 一、二、三、四象限无功总
case 0x95://上月正向无功、反向无功,及 一、二、三、四象限无功总
case 0x99://上上月正向无功、反向无功,及 一、二、三、四象限无功总
case 0xA1://当前正向无功、反向无功,及 一、二、三、四象限无功总最大需量
case 0xA5://上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量
case 0xA9://上上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量
case 0xB1://当前正向无功、反向无功,及 一、二、三、四象限无功总最大需量发生的时间
case 0xB5://上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量发生的时间
case 0xB9://上上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量发生的时间
if( LoBYTE >= 0x10 && LoBYTE <= 0x6F)
return data;
break;
case 0xB2://最近一次编程时间,最近一次最大需量清零时间,编程次数,最大需量清零次数,电池工作时间
if(( LoBYTE >= 0x10 && LoBYTE <= 0x14) || LoBYTE == 0x1F)
return data;
break;
case 0xB3://A、B、C 断相记录
if( ( HiBCD >= 0x01 && HiBCD <= 0x04 ) && ( (LoBCD >= 0x00 && LoBCD <= 0x03) ||(LoBCD == 0x0F)))
return data;//
break;
case 0xB6://瞬时量
if( (HiBCD == 1 || HiBCD == 2 ) && ((LoBCD >= 1 && LoBCD <= 3) || LoBCD == 0x0F ))//电压、电流
return data;
if( (HiBCD == 3 ) && ((LoBCD >= 0 && LoBCD <= 5) || LoBCD == 0x0F ) )//有功功率
return data;
if( (HiBCD == 4 || HiBCD == 5 ) && ((LoBCD >= 0 && LoBCD <= 3) || LoBCD == 0x0F ))//无功功率、功率因数
return data;
break;
case 0xC0:
if( (HiBCD == 1 ) && ( (LoBCD >= 0 && LoBCD <= 1) || LoBCD == 0x0F ) )//日期、周次,时间
return data;
if( (HiBCD == 2 ) && ( (LoBCD >= 0 && LoBCD <= 2) || LoBCD == 0x0F ) )//状态字
return data;
if( (HiBCD == 3 ) && ( (LoBCD >= 0 && LoBCD <= 4) || LoBCD == 0x0F ) )//电表常数
return data;
break;
case 0xC1:
if(LoBYTE >= 0x11 && LoBYTE <=0x1A)
return data;
break;
case 0xC2:
if((LoBYTE == 0x11 || LoBYTE == 0x12))
return data;
break;
case 0xC3:
if( (HiBCD == 1) && (LoBCD >=0 && LoBCD <= 4) )
return data;
if(HiBCD == 0x02)
return data;
if(HiBCD == 0x03)
return data;
if(HiBCD == 0x04)
return data;
if(HiBCD == 0x0A)
return data;
break;
case 0xC4:
if(LoBYTE >= 0x10 && LoBYTE <= 0x1E)
return data;
break;
case 0xC5:
if(LoBYTE == 0x10 || LoBYTE ==0x11)
return data;
break;
default:
return 0;
}
return 0;
}
int CMPGB::ProcFullFrame(BYTE *data, int item,BYTE *outbuff,int &outlen, BYTE *addr)//处理完整的数据返回
{
int j;
if( strncmp((char*) addr, (char*)&data[1],6) != 0)//地址不一侄
{
outlen = 6;
for(int m = 0; m < 6; m++)
outbuff[m] = data[ m + 1 ];
return 0x0400;//地址不一样
}
switch(data[ 8 ])
{
case 0x81://读数据返回,无后续数据
case 0xA1://读数据返回,有后续数据
case 0x82://请求后续数据返回,无后续数据
case 0xA2://请求后续数据返回,有后续数据
case 0x83://重读数据,无后续
case 0xA4://重读数据,有后续
if(item != (( data[ 11 ] - 0x33) * 256 + data[ 10 ] - 0x33 ))
{
return 0x0500;//抄表项目不一样
}
for(j = 0; j < data[9]; j ++)
{
data[12 + j] -= 0x33;//数据域-0x33
}
for(j = 0; j < data[9];j++)
{
if(data[12 + j] == 0xBB)
{
return 0x0600;
}
}
outlen = (int) data[9] - 2;
memcpy( (void *)outbuff, (void *)&data[12], data[9] );
break;
case 0xC1://读数据返回异常
case 0xC2://读后续数据返回异常
case 0xC3://重读数据返回异常
case 0xC4://写数据,异常应答
return data[ 10 ] - 0x33; //电表返回错误码
break;
case 0x84://写数据,从站正常应答
break;
// errCode = data[ 10 ] - 0x33;//电表返回错误码
// return false;
// break;
case 0x8A://写设备地址,正常应答
break;//
case 0x8C:
break;//更改通讯速率,正常应答
default:
// errCode = 0x0600;
return 0x0700;//无效的控制字符
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -