zoukankan      html  css  js  c++  java
  • COMTRADE(IEEE标准电力系统暂态数据交换通用格式STD C37.1111991/1999)文件格式解析

    comtrade_format.h

       1: /*
       2:  * 分析解析COMTRADE(IEEE标准电力系统暂态数据交换通用格式)文件格式。
       3:  *
       4:  * (一)IEEE的COMTRADE数据格式
       5:  *
       6:  * COMTRADE是IEEE标准电力系统暂态数据交换通用格式。标准为电力系统或电力系统模型采集到的暂态波形和事故数据的文件定义了一种格式。
       7:  * 该格式意欲提供一种易于说明的数据交换通用格式。IEEE于1991年提出,并于1999进行了修订和完善。每个COMTRADE记录都有一组最多4个与
       8:  * 其相关的文件,4个文件中的每一个都具有一个不同的信息等级。4个文件如下:
       9:  *
      10:  * (1)、标题文件(xxxxxxxx.HDR)
      11:  * 标题文件是由COMTRADE数据的原创者建立的一种可选的ASCII文本文件,标题文件的创建者可以以任何需要的顺序创建任何信息。标题文件的
      12:  * 格式为ASCII。
      13:  *
      14:  * (2)、 配置文件(xxxxxxxx.CFG)
      15:  * 配置文件为一种ASCII文本文件,用于正确地说明数据(.DAT)文件的格式,因此必须以一种具体的格式保存。该文件诠释了数据(.DAT)文
      16:  * 件所包含信息,其中包括诸如采样速率、通道数量、频率、通道信息等项。配置文件第一行中的一个字段识别文件所依照的 COMTRADE标准版
      17:  * 本的年份(例如1991、1999等)。如果该字段不存在或是空的,则假设文件则遵照标准的最初发行日期(1991)。配置文件还包含识别伴随
      18:  * 的数据文件是以ASCII格式还是以二进制格式存储的字段。 配置文件有下列信息:
      19:  * (a)站名,记录装置的特征,COMTRADE 标准的修改年份
      20:  * (b)通道的数量和类型
      21:  * (c)通道名称、单位和转换系数
      22:  * (d)线路频率
      23:  * (e)采样速率和每一速率下的采样数量
      24:  * (f)第一数据点的日期和时间
      25:  * (g)触发点和日期和时间
      26:  * (h)数据文件类型
      27:  * (i)时间标记倍乘系数
      28:  *
      29:  * (3)、 数据文件(xxxxxxxx.DAT)
      30:  * 数据文件包含记录中每个采样所有输入通道的值。数据文件包含一个顺序号和每次采样的时间标志。这些采样值除记录模拟输入的数据之外,
      31:  * 也记录状态,即表示开/关信号的输入。
      32:  *
      33:  * (4)、 信息文件(xxxxxxxx.INF)
      34:  * 信息文件是一种文件创建者希望使之对用户有用的信息之外的特别信息。信息文件是可选文件。
      35:  *
      36:  * COMTRADE定义的所有文件,都在IEEE 标准电力系统暂态数据交换通用格式Std C37.111-1991或IEEE Std C37.111-1999版本中进行了诠释。
      37:  *
      38:  * (二) 电力系统故障动态记录技术准则
      39:  *
      40:  * 电力行业标准《220kV~500kV电力系统故障动态记录技术准则》(DL/T 553-94),是故障录波装置研制和开发中必须依据的标准。标准在3.6.5
      41:  * 条中规定了,输出的动态过程记录数据应符合的标准格式与ANSI/IEEE Std C37.111-1991 COMTRADE兼容。同时,标准规定了电力系统发生故障
      42:  * 的整个过程中,模拟量采集方式的数据记录按时段顺序进行。
      43:  * A时段:系统在扰动开始前的状态数据,直接输出原始采集波形,记录时间≥0.04S
      44:  * B时段:系统大扰动初期的状态数据,直接输出原始采集波形,记录时间≥0.1S
      45:  * C时段:系统大扰动后的中期状态数据,可输出连续工频有效值,记录时间≥1.0S
      46:  * D时段:系统动态过程数据,每0.1S输出一个工频有效值,记录时间≥20S
      47:  * E时段:系统长过程的动态数据,每0.1S输出一个工频有效值,记录时间≥10min
      48:  * 这里,技术标准的数据记录有两个主要特点,一是分段记录,二是记录的数据不仅可以有按某一采样率的采样数据,而且可按一定间隔记录有效
      49:  * 值以代替采样值。
      50:  *
      51:  *(三) 微机故障录波装置和COMTRADE文件
      52:  *
      53:  * 微机故障录波装置,基本配置分为一台采集站和一台分析站,采集站和分析站之间通过高速以太网连接。采集站负责采集、记录故障数据;采集
      54:  * 站采集的原始数据或记录的原始故障数据,除了存入采集站的硬盘保存外,还将通过网络把数据上传到分析站。分析站程序采用VC 6.0编制,完
      55:  * 成对数据处理、波形显示、自动分析、与远方通信功能。数据处理中,自动生成符合COMTRADE格式的文件。装置接收故障采样数据后,直接将数
      56:  * 据处理成COMTRADE数据格式的文件。故障录波装置模拟量采样频率为5000次/秒,采样时段根据电力系统故障动态记录技术准则,做了相应调整,
      57:  * 将C时段调整为直接输出原始采集波形,记录时间≥1.0S,这样ABC时段采样频率为5000次/秒,存实时的模拟数据;而DE时段采样频率为10次/秒,
      58:  * 用存最大值数据来代替有效值,这样便于产生包络线波形。我们省略了标题文件和信息文件,并且根据不同的批次和故障次数,定义文件名,生
      59:  * 成的配置文件( DIR00.CFG )和数据文件( DIR00.DAT ),并同时存放于同一批次文件夹DIR00内。文件示例如下列所示。
      60:  *
      61:  * (1)、配置文件( DIR00.CFG )
      62:  * 城东变电所,03                                                                                     【注:变电站名称 录波器编号】
      63:  * 12, 8A, 4D                                                                           【注:12格通道,8个模拟通道,4个数字通道】
      64:  * 1, 1 Ia, A, mx1, A, 8.46830338, 0.00000000, 0, -2048, 2047   【注:模拟量依次为:通道编号,通道名称,通道相,XX,单位,fCoefA[变
      65:  *              换因子A],fCoefB[变换因子B],fTime[时间偏移],fMin[此模拟量采样记录数据最小值], fMax[此模拟量采样记录数据最大值],
      66:  *              其中:实际值y与采样记录数据X的关系:y = fCoefA * X + fCoefB, 所以实际的最值:
      67:  *                      Min = fCoefA * fMin + fCoefB;    Max = fCoefA * fMax~ + fCoefB;                                         】
      68:  * 2, 1 Ib, B, mx1, A, 8.46830338, 0.00000000, 0, -2048, 2047
      69:  * 3, 1 Ic, C, mx1, A, 8.46830338, 0.00000000, 0, -2048, 2047
      70:  * 4, 1 IN, N, mx1, A, 8.46830338, 0.00000000, 0, -2048, 2047
      71:  * 5, mx1 Ua, A, , kV, 0.15540126, 0.00000000, 0, -2048, 2047
      72:  * 6, mx1 Ub, B, , kV, 0.15540126, 0.00000000, 0, -2048, 2047
      73:  * 7, mx1 Uc, C, , kV, 0.15540126, 0.00000000, 0, -2048, 2047
      74:  * 8, mx1 UN, N, , kV, 0.15540126, 0.00000000, 0, -2048, 2047
      75:  * 1,开关1,0                                                                      【注:通道编号/序号、通道名称、数字量初始状态】
      76:  * 2,开关2,0
      77:  * 3,开关3,0
      78:  * 4,开关4,1
      79:  * 50                                                                                            【注:系统电流电压的频率为50Hz】
      80:  * 2                                                                                                       【注:有两个采样频率】
      81:  * 5000, 6300                                                              【注:第一个采样频率: 在采样率为5000Hz下采了6300个点】
      82:  * 10, 200                                                                    【注:第二个采样频率: 在采样率为10Hz下采了200个点】
      83:  * 03/07/03,14:46:48.850000                                                                                  【注:采样开始时间】
      84:  * 03/07/03,14:46:49.010000                                                                                  【注:采样结束时间】
      85:  * ASCII                                                           【注:dat文件记录格式为ASCII, 还有一种是BINARY(二进制格式)】
      86:  *
      87:  *(2)、 数据文件( DIR00.DAT )
      88:  * 1, 0, 46, -54, 10, 0, 1204, -734, -442, 60, 0, 1, 0, 1       【注:依次为:序号,采样时间,模拟采样记录值[按cfg文件的顺序],数
      89:  *              字采样记录值[按cfg文件的顺序],其中模拟量实际值算法:y = fCoefA * X + fCoefB, 同最值计算方法;如:
      90:  *              对于46表示的实际值y为:y = fCoefA(即8.46830338) * X(即46) + fCoefB(即0.00000000)
      91:  *              对于-54表示的实际值y为:y = fCoefA(即8.46830338) * X(即-54) + fCoefB(即0.00000000)
      92:  *              对于10表示的实际值y为:y = fCoefA(即8.46830338) * X(即10) + fCoefB(即0.00000000)
      93:  *              对于0表示的实际值y为:y = fCoefA(即0.15540126) * X(即0) + fCoefB(即0.00000000)
      94:  *              对于1024表示的实际值y为:y = fCoefA(即0.15540126) * X(即1024) + fCoefB(即0.00000000)                     】
      95:  * 2, 200, 48, -54, 6, 0, 1218, -682, -504, 60, 0, 1, 0, 1
      96:  * 3, 400, 50, -52, 4, -2, 1206, -616, -554, 58, 0, 1, 0, 1
      97:  * 4, 600, 52,-50, -2, 0, 1192, -542, -614, 56, 0, 1, 0, 1
      98:  *
      99:  * 注:以上说明文字部分来自网络。
     100:  *
     101:  * 另外,对于Binary保存方式的数据文件(dat文件),数据保存格式为:序号[4字节]、采样时间[4字节]、模拟量值[按cfg文件的顺序,两字节
     102:  * 表示一个模拟量采样值]、数字量组值[按cfg文件的顺序,16个数字量一组,一组用2字节表示,不够一组的空位(高位)补零构成一组,组内
     103:  * 从低位bit依次到高位bit与cfg文件里的数字量顺序对应]。
     104:  *
     105:  * 经验表明,目前大部分comtrade文件中的cfg文件中所表示的通道最值与dat中实际的最值都是不相符(出入很大),所以在读dat的接口中引入
     106:  * 了最值统计。
     107:  *
     108:  * 本代码支持win32平台和linux平台。
     109:  *
     110:  * Copyright,lizhi<ibox>
     111:  *
     112:  * 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created
     113:  *
     114:  */
     115:  
     116:  
     117: #ifndef __INCLUDE_COMTRADE_FORMAT_H
     118: #define __INCLUDE_COMTRADE_FORMAT_H
     119:  
     120:  
     121:  
     122: /*
     123:  * 头文件
     124:  */
     125: #include "base_type.h"
     126:  
     127:  
     128: #if defined (__cplusplus)
     129: extern "C" {
     130: #endif /* defined (__cplusplus) */
     131:  
     132:  
     133: /*
     134:  * 宏开关 定义为文件读写
     135:  */
     136: #define CMTR_IOFILE
     137:  
     138:  
     139:  
     140: /*
     141:  * 宏定义文件的读写操作,可以根据需要改写该接口,如重定义
     142:  * 为网口的recv\send、串口r\w等。
     143:  *
     144:  * _my_read_cmtr_bufn/_my_read_cmtr_bufn - cmtr的读写操作
     145:  * @pfd: 读写地址,可以为文件的fd、或者buffer地址等
     146:  * @buf: 缓冲区地址
     147:  * @count: 需要读写的字节数
     148:  *
     149:  */
     150: #if defined(CMTR_IOFILE)
     151: typedef int _my_cmtr_ioptr;
     152: #define _my_read_cmtr_bufn(pfd, buf, count)             \
     153:         do {                                            \
     154:                 if (read((pfd), (buf), (count)) <= 0) { \
     155:                         (pfd) = -1;                     \
     156:                 }                                       \
     157:         } while(0);
     158: #define _my_write_cmtr_bufn(pfd, buf, count)            \
     159:         do {                                            \
     160:                 if (write((pfd), (buf), (count)) <= 0) {\
     161:                         (pfd) = -1;                     \
     162:                 }                                       \
     163:         } while(0);
     164: #define _my_check_cmtr_ptr(pfd)                            \
     165:         (((pfd) != -1) && ((pfd) != 0))
     166: #elif defined(CMTR_IOBUFFER)
     167: typedef u8* _my_cmtr_ioptr;
     168: #define _my_read_cmtr_bufn(pfd, buf, count)             \
     169:         do {                                            \
     170:                 memcpy((buf), (pfd), (count));          \
     171:                 (pfd) += (count);                       \
     172:         } while(0);
     173: #define _my_write_cmtr_bufn(pfd, buf, count)            \
     174:         do {                                            \
     175:                 memcpy((pfd), (buf), (count));          \
     176:                 (pfd) += (count);                       \
     177:         } while(0);
     178: #define _my_check_cmtr_ptr(pfd)                            \
     179:         (((pfd) != -1) && ((pfd) != 0))
     180: #endif
     181:  
     182:  
     183:  
     184: /*
     185:  * 关于comtrade文件配置文件的宏定义。
     186:  * 在此采用预定义最大个数方法,避免动态内存管理的问题。
     187:  *
     188:  * 相关字符串最大字符个数,一般不会超过16个;
     189:  * 模拟量端口最大个数,一般不会超过64个;
     190:  * 数字量量端口最大个数,一般不会超过64个;
     191:  * 采样率最大个数,一般不会超过8个;
     192:  *
     193:  */
     194: #define  CMTR_STRING_MAX_LENGTH         64
     195: #define  CMTR_ANALOG_MAX_COUNT          255
     196: #define  CMTR_DIGIT_MAX_COUNT           255
     197: #define  CMTR_SMPRATE_MAX_COUNT         255
     198:  
     199:  
     200:  
     201: /*
     202:  * cmtr_cfg_analog - 配置文件模拟量信息
     203:  * @index: 模拟量端口序号(只是编号,解析时不做序号用);
     204:  * @name: 模拟量端口名称;
     205:  * @phase: 模拟量端口相标识,值如(A、B、C、N等);
     206:  * @element:标识(还未知,待补充),一般为空;
     207:  * @unit: 模拟量端口数值的单位,该单位常用来区分该端口是电流还是电流,值如:kV、V、A、mA等;
     208:  * @factor_a: 系数a,一般为整数,可以是浮点数;
     209:  * @factor_b: 系数b,一般为整数,可以是浮点数;
     210:  * @offset_time: 时间偏移,指第一个点的时间偏移量,一般为0;
     211:  * @smp_min: 通道的最小采用值,一般为整数,国内有些变态的仪器会生成浮点数(在次不支持);
     212:  * @smp_max: 通道的最大采用值,一般为整数,国内有些变态的仪器会生成浮点数(在次不支持);
     213:  *
     214:  * 通道采样的实际值计算方法:实际值 = factor_a * smp_value + factor_b;所以根据该公式,可以计算
     215:  * 通道的最小值为:factor_a * smp_min + factor_b,最大值为:factor_a * smp_max + factor_b。
     216:  *
     217:  * 注:本来smp_min、smp_max为两个字节的一个数据(即最大为65535),但不同厂家会生成很大的四字节数据,
     218:  *    所以采用s32类型;factor_a、factor_b用double类型,用float可能会丢精度;为了提供解析程序的适
     219:  *    应性,以适应国内各种变态的有标准不遵循的厂家的仪器生成的cmtr文件。
     220:  *
     221:  */
     222: struct cmtr_cfg_analog {
     223:         s32 index;
     224:         u8 name[CMTR_STRING_MAX_LENGTH];
     225:         u8 phase[CMTR_STRING_MAX_LENGTH];
     226:         u8 element[CMTR_STRING_MAX_LENGTH];
     227:         u8 unit[CMTR_STRING_MAX_LENGTH];
     228:         f64 factor_a;
     229:         f64 factor_b;
     230:         s32 offset_time;
     231:         s32 smp_min;
     232:         s32 smp_max;
     233: };
     234:  
     235:  
     236: /*
     237:  * cmtr_cfg_digit - 配置文件数字量信息
     238:  * @index: 数字量端口序号(只是编号,解析时不做序号用);
     239:  * @name: 数字量端口名称;
     240:  * @state: 数字量起始状态值,一般为1或者0,很少情况下会为2;
     241:  *
     242:  */
     243: struct cmtr_cfg_digit {
     244:         s32 index;
     245:         u8 name[CMTR_STRING_MAX_LENGTH];
     246:         s8 state;
     247: };
     248:  
     249: /*
     250:  * cmtr_cfg_smprate_info - 配置文件采样点信息
     251:  * @rate: 采样率,一般为整数,也有小数表示的;
     252:  * @point: 该采样率下采样的点数,为整数;
     253:  *
     254:  */
     255: struct cmtr_cfg_smprate {
     256:         f32 rate;
     257:         s32 point;
     258: };
     259:  
     260: /*
     261:  * cmtr_cfg_info - 配置文件信息。
     262:  * @station_name: 厂站名称;
     263:  * @kymograph_id: 录波器编号;
     264:  * @analog_count: 模拟量个数;
     265:  * @digit_count: 数字量个数;
     266:  * @analogs: 模拟量信息;
     267:  * @digits: 数字量信息;
     268:  * @frequency: 基本频率,一般为额定频率,指的是电网频率;
     269:  * @smprate_count: 采样率个数;
     270:  * @smprates: 采样率信息;
     271:  * @begin_time: 录波开始时间;
     272:  * @end_time: 录波结束时间;
     273:  * @file_type: 数据文件类型,可以“ASCII”和“Binary”,ASCII类型为dat文件可以用记事本打开看详
     274:  *             细的采样信息;binary格式的只能用特殊的工具查看,为二进制数据文件;
     275:  *
     276:  */
     277: typedef struct cmtr_cfg_info {
     278:         u8 station_name[CMTR_STRING_MAX_LENGTH];
     279:         u8 kymograph_id[CMTR_STRING_MAX_LENGTH];
     280:         s32 analog_count;
     281:         s32 digit_count;
     282:         struct cmtr_cfg_analog analogs[CMTR_ANALOG_MAX_COUNT];
     283:         struct cmtr_cfg_digit digits[CMTR_DIGIT_MAX_COUNT];
     284:         f32 frequency;
     285:         s32 smprate_count;
     286:         struct cmtr_cfg_smprate smprates[CMTR_SMPRATE_MAX_COUNT];
     287:         u8 begin_time[CMTR_STRING_MAX_LENGTH];
     288:         u8 end_time[CMTR_STRING_MAX_LENGTH];
     289:         u8 file_type[CMTR_STRING_MAX_LENGTH];
     290: };
     291:  
     292:  
     293:  
     294: /*
     295:  * cmtr_dat_smpdot - 数据文件中的采样点数据信息.
     296:  * @index: 端口序号(只是编号,解析时不做序号用);
     297:  * @time: 采样点采样时间偏移量,单位微妙;
     298:  * @analogs: 模拟量信息,一般为有符号整数,国内有些变态的仪器会生成浮点数(在此不支持);
     299:  * @digits: 数字量信息,为有符号整数;
     300:  *
     301:  */
     302: struct cmtr_dat_smpdot{
     303:         s32 index;
     304:         s32 time;
     305:         s32 analogs[CMTR_ANALOG_MAX_COUNT];
     306:         s8 digits[CMTR_DIGIT_MAX_COUNT];
     307: };
     308:  
     309:  
     310:  
     311:  
     312:  
     313: /*
     314:  * write_cmtr_cfg_info - 写cmtr配置文件.
     315:  * @pfd:  输入输出参数,地址
     316:  * @cfg:输入参数,cmtr(cfg文件)结构体
     317:  * @counter:  输出参数,写入的字节计数器;
     318:  *
     319:  * 返回当前pfd指针,写失败返回NULL
     320:  *
     321:  */
     322: _my_cmtr_ioptr write_cmtr_cfg_info(_my_cmtr_ioptr pfd,
     323:                                    struct cmtr_cfg_info *cfg,
     324:                                    int *counter);
     325:  
     326:  
     327: /*
     328:  * write_cmtr_dat_smpdot_ascii - 写cmtr采样点数据信息(ascii格式).
     329:  * @pfd:  输入输出参数,地址
     330:  * @analog_count: 输入参数,模拟量个数;
     331:  * @digit_count: 输入参数,数字量个数;
     332:  * @dot:  输入参数,采样点信息;
     333:  * @counter:  输出参数,写入的字节计数器;
     334:  *
     335:  * 返回当前pfd指针,写失败返回NULL
     336:  *
     337:  */
     338: _my_cmtr_ioptr write_cmtr_dat_smpdot_ascii(_my_cmtr_ioptr pfd,
     339:                                            int analog_count, int digit_count,
     340:                                            struct cmtr_dat_smpdot *dot,
     341:                                            int* counter);
     342:  
     343: /*
     344:  * write_cmtr_dat_smpdot_binary - 写cmtr采样点数据信息(binary格式).
     345:  * @pfd:  输入输出参数,地址
     346:  * @big_endian_tag: 输入参数,标识文件中数据的字节顺序,为FALSE按照小端写(默认值),True按照大端写;
     347:  * @analog_count: 输入参数,模拟量个数;
     348:  * @digit_count: 输入参数,数字量个数;
     349:  * @dot:  输入参数,采样点信息;
     350:  * @counter:  输出参数,写入的字节计数器;
     351:  *
     352:  * 返回当前pfd指针,写失败返回NULL
     353:  *
     354:  */
     355: _my_cmtr_ioptr write_cmtr_dat_smpdot_binary(_my_cmtr_ioptr pfd,
     356:                                             u8 big_endian_tag,
     357:                                             int analog_count, int digit_count,
     358:                                             struct cmtr_dat_smpdot *dot,
     359:                                             int* counter);
     360:  
     361:  
     362: /*
     363:  * read_cmtr_cfg_info - 读cmtr配置文件.
     364:  * @pfd:  输入输出参数,地址
     365:  * @cfg:输出参数,cmtr(cfg文件)结构体
     366:  * @counter:  输出参数,读取的字节计数器;
     367:  *
     368:  * 返回当前pfd指针,读失败返回NULL
     369:  *
     370:  */
     371: _my_cmtr_ioptr read_cmtr_cfg_info(_my_cmtr_ioptr pfd,
     372:                                   struct cmtr_cfg_info *cfg,
     373:                                   int* counter);
     374:  
     375:  
     376: /*
     377:  * read_cmtr_dat_smpdot_ascii - 读ascii格式cmtr采样点数据信息.
     378:  * @pfd:  输入输出参数,地址
     379:  * @read_buf: 输入参数,读缓冲,在外部申请内存,避免在内部频繁申请、释放内存;
     380:  * @buf_size: 输入参数,读缓冲区的大小;
     381:  * @analog_count: 输入参数,模拟量个数;
     382:  * @digit_count: 输入参数,数字量个数;
     383:  * @dot:  输出参数,采样点信息;
     384:  * @the_smp_mins: 输出参数,统计最小值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     385:  * @the_smp_maxs: 输出参数,统计最大值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     386:  * @counter:  输出参数,读取的字节计数器;
     387:  *
     388:  * 返回当前pfd指针,读失败返回NULL
     389:  *
     390:  */
     391: _my_cmtr_ioptr read_cmtr_dat_smpdot_ascii(_my_cmtr_ioptr pfd,
     392:                                           u8 *read_buf, int buf_size,
     393:                                           int analog_count, int digit_count,
     394:                                           struct cmtr_dat_smpdot *dot,
     395:                                           u16* the_smp_mins, u16* the_smp_maxs,
     396:                                           int* counter);
     397:  
     398: /*
     399:  * read_cmtr_dat_smpdot_binary - 读bin格式cmtr采样点数据信息.
     400:  * @pfd:  输入输出参数,地址
     401:  * @big_endian_tag: 输入参数,标识文件中数据的字节顺序,为FALSE按照小端读(默认值),True按照大端读;
     402:  * @analog_count: 输入参数,模拟量个数;
     403:  * @digit_count: 输入参数,数字量个数;
     404:  * @dot:  输出参数,采样点信息;
     405:  * @the_smp_mins: 输出参数,统计最小值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     406:  * @the_smp_maxs: 输出参数,统计最大值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     407:  * @counter:  输出参数,读取的字节计数器;
     408:  *
     409:  * 返回当前pfd指针,读失败返回NULL
     410:  *
     411:  */
     412: _my_cmtr_ioptr read_cmtr_dat_smpdot_binary(_my_cmtr_ioptr pfd, u8 big_endian_tag,
     413:                                            int analog_count, int digit_count,
     414:                                            struct cmtr_dat_smpdot *dot,
     415:                                            u32* the_smp_mins, u32* the_smp_maxs,
     416:                                            int* counter);
     417:  
     418: /*
     419:  * print_cmtr_cfg_info - 打印cmtr文件配置数.
     420:  * @cfg:  输入参数,cmtr文件配置数据;
     421:  *
     422:  */
     423: void print_cmtr_cfg_info(struct cmtr_cfg_info *cfg);
     424:  
     425: /*
     426:  * print_cmtr_dat_smpdot - 打印cmtr数据文件采样点.
     427:  * @cfg:  输入参数,cmtr文件配置数据;
     428:  * @analog_count: 输入参数,模拟量个数;
     429:  * @digit_count: 输入参数,数字量个数;
     430:  * @dot:  输入参数,采样点信息;
     431:  *
     432:  */
     433: void print_cmtr_dat_smpdot(int analog_count, int digit_count,
     434:                            struct cmtr_dat_smpdot *dot);
     435:  
     436:  
     437:  
     438: #if defined (__cplusplus)
     439: }
     440: #endif /* defined (__cplusplus) */
     441:  
     442:  
     443: #endif /* __INCLUDE_COMTRADE_FORMAT_H */

    comtrade_format.c

       1: /*
       2:  * 分析解析COMTRADE(IEEE标准电力系统暂态数据交换通用格式)文件格式。
       3:  *
       4:  *
       5:  * 本代码支持win32平台和linux平台。
       6:  *
       7:  * Copyright,lizhi<ibox>
       8:  *
       9:  * 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created
      10:  *
      11:  */
      12:  
      13: /*
      14:  * 头文件
      15:  */
      16: #include "base_type.h"
      17: #include "base_include.h"
      18: #include "base_debug.h"
      19: #include "base_endian.h"
      20: #include "base_function.h"
      21: #include "comtrade_format.h"
      22:  
      23:  
      24: /*
      25:  * 测试宏开关
      26:  */
      27: ///*
      28: #define CMTR_CONSOLE_DEMO
      29: //*/
      30:  
      31:  
      32: /*
      33:  * _my_read_cmtr_data/_my_write_cmtr_data - 读取/写入并且转换cmtr数据。
      34:  * @src: 读写地址,为buffer地址;
      35:  * @data:  读取/写入的数据;
      36:  * @count: 需要读取/写入的字节个数;
      37:  * @counter:  读取/写入的字节计数器;
      38:  *
      39:  */
      40: #define _my_read_cmtr_data(src, data, count, counter)                   \
      41:         do {                                                            \
      42:                 if (_my_check_cmtr_ptr(src)) {                          \
      43:                         _my_read_cmtr_bufn((src), (data), (count));     \
      44:                         (counter) += (count);                           \
      45:                 }                                                       \
      46:         } while(0);
      47: #define _my_write_cmtr_data(src, data, count, counter)                  \
      48:         do {                                                            \
      49:                 if (_my_check_cmtr_ptr(src)) {                          \
      50:                         _my_write_cmtr_bufn((src), (data), (count));    \
      51:                         (counter) +=(count);                            \
      52:                 }                                                       \
      53:         } while(0);
      54:  
      55: /*
      56:  * write_cmtr_cfg_info - 写cmtr配置文件.
      57:  * @pfd:  输入输出参数,地址
      58:  * @cfg:输入参数,cmtr(cfg文件)结构体
      59:  * @counter:  输出参数,写入的字节计数器;
      60:  *
      61:  * 返回当前pfd指针,写失败返回NULL
      62:  *
      63:  */
      64: _my_cmtr_ioptr write_cmtr_cfg_info(_my_cmtr_ioptr pfd, struct cmtr_cfg_info *cfg, int *counter)
      65: {
      66:         u32 strlenr = 0;
      67:         u32 strmaxl = CMTR_STRING_MAX_LENGTH * 10;
      68:         u8* strline = (u8 *)_my_buf_malloc((size_t)(strmaxl));
      69:         u32 index = 0;
      70:  
      71:         _my_cmtr_ioptr curr_pfd = pfd;
      72:  
      73:         memset(strline, '\0', strmaxl);
      74:         strlenr = sprintf(strline, "%s,%s\n", cfg->station_name, cfg->kymograph_id);
      75:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
      76:  
      77:         memset(strline, '\0', strmaxl);
      78:         strlenr = sprintf(strline, "%d,%dA,%dD\n", cfg->analog_count + cfg->digit_count, cfg->analog_count, cfg->digit_count);
      79:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
      80:  
      81:         for (index = 0; index < cfg->analog_count; index++) {
      82:                 memset(strline, '\0', strmaxl);
      83:                 strlenr = sprintf(strline, "%d,%s,%s,%s,%s,%lf,%lf,%d,%d,%d\n",
      84:                                   cfg->analogs[index].index,
      85:                                   cfg->analogs[index].name,
      86:                                   cfg->analogs[index].phase,
      87:                                   cfg->analogs[index].element,
      88:                                   cfg->analogs[index].unit,
      89:                                   cfg->analogs[index].factor_a,
      90:                                   cfg->analogs[index].factor_b,
      91:                                   cfg->analogs[index].offset_time,
      92:                                   cfg->analogs[index].smp_min,
      93:                                   cfg->analogs[index].smp_max);
      94:                 _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
      95:         }
      96:  
      97:         for (index = 0; index < cfg->digit_count; index++) {
      98:                 memset(strline, '\0', strmaxl);
      99:                 strlenr = sprintf(strline, "%d,%s,%d\n",
     100:                                   cfg->digits[index].index,
     101:                                   cfg->digits[index].name,
     102:                                   cfg->digits[index].state);
     103:                 _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     104:         }
     105:  
     106:         memset(strline, '\0', strmaxl);
     107:         strlenr = sprintf(strline, "%f\n", cfg->frequency);
     108:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     109:  
     110:         memset(strline, '\0', strmaxl);
     111:         strlenr = sprintf(strline, "%d\n", cfg->smprate_count);
     112:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     113:         for (index = 0; index < cfg->smprate_count; index++) {
     114:                 memset(strline, '\0', strmaxl);
     115:                 strlenr = sprintf(strline, "%f,%d\n", cfg->smprates[index].rate, cfg->smprates[index].point);
     116:                 _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     117:         }
     118:  
     119:         memset(strline, '\0', strmaxl);
     120:         strlenr = sprintf(strline, "%s\n", cfg->begin_time);
     121:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     122:         memset(strline, '\0', strmaxl);
     123:         strlenr = sprintf(strline, "%s\n", cfg->end_time);
     124:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     125:         strlenr = sprintf(strline, "%s\n", cfg->file_type);
     126:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     127:  
     128:         _my_buf_free(strline);
     129:  
     130:         return curr_pfd;
     131: }
     132:  
     133:  
     134: /*
     135:  * write_cmtr_dat_smpdot_ascii - 写cmtr采样点数据信息(ascii格式).
     136:  * @pfd:  输入输出参数,地址
     137:  * @analog_count: 输入参数,模拟量个数;
     138:  * @digit_count: 输入参数,数字量个数;
     139:  * @dot:  输入参数,采样点信息;
     140:  * @counter:  输出参数,写入的字节计数器;
     141:  *
     142:  * 返回当前pfd指针,写失败返回NULL
     143:  *
     144:  */
     145: _my_cmtr_ioptr write_cmtr_dat_smpdot_ascii(_my_cmtr_ioptr pfd, int analog_count, int digit_count, struct cmtr_dat_smpdot *dot, int* counter)
     146: {
     147:         u32 strlenr = 0;
     148:         u32 strmaxl = CMTR_STRING_MAX_LENGTH;
     149:         u8* strline = (u8 *)_my_buf_malloc((size_t)(strmaxl));
     150:         int index = 0;
     151:  
     152:         _my_cmtr_ioptr curr_pfd = pfd;
     153:  
     154:         _my_assert(pfd && dot);
     155:  
     156:         memset(strline, '\0', strmaxl);
     157:         strlenr = sprintf(strline, "%d,%d", dot->index, dot->time);
     158:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     159:         for (index = 0; index < analog_count; index++) {
     160:                 memset(strline, '\0', strmaxl);
     161:                 strlenr = sprintf(strline, ",%d", dot->analogs[index]);
     162:                 _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     163:         }
     164:         for (index = 0; index < digit_count; index++) {
     165:                 memset(strline, '\0', strmaxl);
     166:                 strlenr = sprintf(strline, ",%d", dot->digits[index]);
     167:                 _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     168:         }
     169:         memset(strline, '\0', strmaxl);
     170:         strlenr = sprintf(strline, "\n");
     171:         _my_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
     172:  
     173:         _my_buf_free(strline);
     174:  
     175:         return curr_pfd;
     176: }
     177:  
     178:  
     179: /*
     180:  * write_cmtr_dat_smpdot_binary - 写cmtr采样点数据信息(binary格式).
     181:  * @pfd:  输入输出参数,地址
     182:  * @big_endian_tag: 输入参数,标识文件中数据的字节顺序,为FALSE按照小端写(默认值),True按照大端写;
     183:  * @analog_count: 输入参数,模拟量个数;
     184:  * @digit_count: 输入参数,数字量个数;
     185:  * @dot:  输入参数,采样点信息;
     186:  * @counter:  输出参数,写入的字节计数器;
     187:  *
     188:  * 返回当前pfd指针,写失败返回NULL
     189:  *
     190:  */
     191: _my_cmtr_ioptr write_cmtr_dat_smpdot_binary(_my_cmtr_ioptr pfd, u8 big_endian_tag, int analog_count, int digit_count, struct cmtr_dat_smpdot *dot, int* counter)
     192: {
     193:         s16 data16 = 0x00;
     194:         s32 data32 = 0x00;
     195:         int oldnum = 0;
     196:  
     197:         s16 datatp = 0x00;
     198:  
     199:         int index = 0;
     200:  
     201:         _my_cmtr_ioptr curr_pfd = pfd;
     202:  
     203:         oldnum = (*counter);
     204:         data32 = big_endian_tag ? _my_htob32(dot->index) : _my_htol32(dot->index);
     205:         _my_write_cmtr_data(curr_pfd, &data32, 4, *counter);
     206:         if ((*counter) <= oldnum) {
     207:                 return NULL;
     208:         }
     209:         oldnum = (*counter);
     210:         data32 = big_endian_tag ? _my_htob32(dot->time) : _my_htol32(dot->time);
     211:         _my_write_cmtr_data(curr_pfd, &data32, 4, *counter);
     212:         if ((*counter) <= oldnum) {
     213:                 return NULL;
     214:         }
     215:         for (index = 0; index < analog_count; index++) {
     216:                 oldnum = (*counter);
     217:                 datatp = (s16)(dot->analogs[index]);
     218:                 data16 = big_endian_tag ? _my_htob16(datatp) : _my_htol16(datatp);
     219:                 _my_write_cmtr_data(curr_pfd, &data16, 2, *counter);
     220:                 if ((*counter) <= oldnum) {
     221:                         return NULL;
     222:                 }
     223:         }
     224:  
     225:         data16 = 0x0000;
     226:         for (index = 0; index < digit_count; index++) {
     227:                 if (dot->digits[index]) {
     228:                         data16 |= (0x0001 << (index % 16));
     229:                 }
     230:                 if (((index % 16) == 0) && (index != 0)) {
     231:                         oldnum = (*counter);
     232:                         data16 = big_endian_tag ? _my_htob16(data16) : _my_htol16(data16);
     233:                         _my_write_cmtr_data(curr_pfd, &data16, 2, *counter);
     234:                         if ((*counter) <= oldnum) {
     235:                                 return NULL;
     236:                         }
     237:                 }
     238:         }
     239:         if (((index % 16) != 1) && (index != 0)) {
     240:                 oldnum = (*counter);
     241:                 data16 = big_endian_tag ? _my_htob16(data16) : _my_htol16(data16);
     242:                 _my_write_cmtr_data(curr_pfd, &data16, 2, *counter);
     243:                 if ((*counter) <= oldnum) {
     244:                         return NULL;
     245:                 }
     246:         }
     247:  
     248:         return curr_pfd;
     249: }
     250:  
     251:  
     252: /*
     253:  * read_cmtr_cfg_line - 读cmtr配置文件一行,跳过空行.
     254:  * @pfd:  输入输出参数,地址;
     255:  * @strline:输出参数,内容缓冲区;
     256:  * @size:输入参数,缓冲区大小;
     257:  * @strlend: 输出参数,读取的line的结束字符指针;
     258:  * @counter:  输出参数,读取的字节计数器;
     259:  *
     260:  * 返回当前pfd指针,读失败返回NULL。
     261:  *
     262:  */
     263: static _my_cmtr_ioptr read_cmtr_cfg_line(_my_cmtr_ioptr pfd, char *strline, int size, char **strlend,int *counter)
     264: {
     265:         int pos = 0;
     266:         int oldnum = 0;
     267:         u8 datard = 0;
     268:         _my_cmtr_ioptr curr_pfd = pfd;
     269:         (*strlend) = NULL;
     270:         if (size <= 0) {
     271:                 return NULL;
     272:         }
     273:         if ((!strline) || (!counter)) {
     274:                 return NULL;
     275:         }
     276:  
     277:         memset(strline, '\0', size);
     278:         while (_my_check_cmtr_ptr(curr_pfd)) {
     279:                 oldnum = (*counter);
     280:                 datard = '\0';
     281:                 _my_read_cmtr_data(curr_pfd, &datard, 1, *counter);
     282:                 if ((*counter) > oldnum) {
     283:                         if (( datard != '\0') && ( datard != '\r') && ( datard != '\n')) {
     284:                                 if ((*strlend) < (strline + size)) {
     285:                                         (*(strline + pos)) = datard;
     286:                                         (*strlend) = strline + pos;
     287:                                 }
     288:                                 pos += 1;
     289:                                 continue;
     290:                         } else {
     291:                                 break;
     292:                         }
     293:                 }
     294:         }
     295:         if (pos == 0) {
     296:                 if (_my_check_cmtr_ptr(curr_pfd)) {
     297:                         return read_cmtr_cfg_line(curr_pfd, strline, size, strlend, counter);
     298:                 } else {
     299:                         return NULL;
     300:                 }
     301:         }
     302:  
     303:         return curr_pfd;
     304: }
     305:  
     306: /*
     307:  * read_cmtr_cfg_one_analog - 分析一行模拟量信息.
     308:  * @analog:  输出参数,模拟量信息;
     309:  * @strline:输入参数,内容缓冲区;
     310:  * @size:输入参数,缓冲区大小;
     311:  * @strlend: 输入参数,读取的line结束指针;
     312:  *
     313:  * 返回TRUE成功,失败返回FALSE。
     314:  *
     315:  */
     316: static u8 read_cmtr_cfg_one_analog(struct cmtr_cfg_analog *analog, char *strline, int size, char *strlend)
     317: {
     318:         int dataint = 0;
     319:         f64 dataflt = 0;
     320:         char* ptrpos = 0;
     321:         char* strlcur = strline;
     322:  
     323:         ptrpos = strchr(strlcur, ',');
     324:         if ((!ptrpos) || (ptrpos >= strlend)) {
     325:                 return FALSE;
     326:         }
     327:         if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
     328:                 return FALSE;
     329:         }
     330:         analog->index = dataint;
     331:  
     332:         strlcur = ptrpos += 1;
     333:         ptrpos = strchr(strlcur, ',');
     334:         if ((!ptrpos) || (ptrpos >= strlend)) {
     335:                 return FALSE;
     336:         }
     337:         memset(analog->name, '\0', CMTR_STRING_MAX_LENGTH);
     338:         memcpy(analog->name, strlcur, ptrpos-strlcur);
     339:  
     340:         strlcur = ptrpos += 1;
     341:         ptrpos = strchr(strlcur, ',');
     342:         if ((!ptrpos) || (ptrpos >= strlend)) {
     343:                 return FALSE;
     344:         }
     345:         memset(analog->phase, '\0', CMTR_STRING_MAX_LENGTH);
     346:         memcpy(analog->phase, strlcur, ptrpos-strlcur);
     347:  
     348:         strlcur = ptrpos += 1;
     349:         ptrpos = strchr(strlcur, ',');
     350:         if ((!ptrpos) || (ptrpos >= strlend)) {
     351:                 return FALSE;
     352:         }
     353:         memset(analog->element, '\0', CMTR_STRING_MAX_LENGTH);
     354:         memcpy(analog->element, strlcur, ptrpos-strlcur);
     355:  
     356:         strlcur = ptrpos += 1;
     357:         ptrpos = strchr(strlcur, ',');
     358:         if ((!ptrpos) || (ptrpos >= strlend)) {
     359:                 return FALSE;
     360:         }
     361:         memset(analog->unit, '\0', CMTR_STRING_MAX_LENGTH);
     362:         memcpy(analog->unit, strlcur, ptrpos-strlcur);
     363:  
     364:         strlcur = ptrpos += 1;
     365:         ptrpos = strchr(strlcur, ',');
     366:         if ((!ptrpos) || (ptrpos >= strlend)) {
     367:                 return FALSE;
     368:         }
     369:         if (sscanf(strlcur, "%lf%*s", &dataflt) <= 0) {
     370:                 return FALSE;
     371:         }
     372:         analog->factor_a = dataflt;
     373:  
     374:         strlcur = ptrpos += 1;
     375:         ptrpos = strchr(strlcur, ',');
     376:         if ((!ptrpos) || (ptrpos >= strlend)) {
     377:                 return FALSE;
     378:         }
     379:         if (sscanf(strlcur, "%lf%*s", &dataflt) <= 0) {
     380:                 return FALSE;
     381:         }
     382:         analog->factor_b = dataflt;
     383:  
     384:         strlcur = ptrpos += 1;
     385:         ptrpos = strchr(strlcur, ',');
     386:         if ((!ptrpos) || (ptrpos >= strlend)) {
     387:                 return FALSE;
     388:         }
     389:         if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
     390:                 return FALSE;
     391:         }
     392:         analog->offset_time = dataint;
     393:  
     394:         strlcur = ptrpos += 1;
     395:         ptrpos = strchr(strlcur, ',');
     396:         if ((!ptrpos) || (ptrpos >= strlend)) {
     397:                 return FALSE;
     398:         }
     399:         if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
     400:                 return FALSE;
     401:         }
     402:         analog->smp_min = dataint;
     403:  
     404:         strlcur = ptrpos += 1;
     405:         if (ptrpos > strlend) {
     406:                 return FALSE;
     407:         }
     408:         if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
     409:                 return FALSE;
     410:         }
     411:         analog->smp_max = dataint;
     412:  
     413:         return TRUE;
     414: }
     415:  
     416: /*
     417:  * read_cmtr_cfg_one_digit - 分析一行数字量信息.
     418:  * @analog:  输出参数,数字量信息;
     419:  * @strline:输入参数,内容缓冲区;
     420:  * @size:输入参数,缓冲区大小;
     421:  * @strlend: 输入参数,读取的line结束指针;
     422:  *
     423:  * 返回TRUE成功,失败返回FALSE。
     424:  *
     425:  */
     426: static u8 read_cmtr_cfg_one_digit(struct cmtr_cfg_digit *digit, char *strline, int size, char *strlend)
     427: {
     428:         int dataint = 0;
     429:         char* ptrpos = 0;
     430:         char* strlcur = strline;
     431:         ptrpos = strchr(strlcur, ',');
     432:         if ((!ptrpos) || (ptrpos >= strlend)) {
     433:                 return FALSE;
     434:         }
     435:         if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
     436:                 return FALSE;
     437:         }
     438:         digit->index = dataint;
     439:  
     440:         strlcur = ptrpos += 1;
     441:         ptrpos = strchr(strlcur, ',');
     442:         if ((!ptrpos) || (ptrpos >= strlend)) {
     443:                 return FALSE;
     444:         }
     445:         memset(digit->name, '\0', CMTR_STRING_MAX_LENGTH);
     446:         memcpy(digit->name, strlcur, ptrpos-strlcur);
     447:  
     448:         strlcur = ptrpos += 1;
     449:         if (ptrpos > strlend) {
     450:                 return FALSE;
     451:         }
     452:         if (sscanf(strlcur, "%d", &dataint) <= 0) {
     453:                 return FALSE;
     454:         }
     455:         digit->state = dataint;
     456:  
     457:         return TRUE;
     458: }
     459:  
     460: /*
     461:  * read_cmtr_cfg_info - 读cmtr配置文件.
     462:  * @pfd:  输入输出参数,地址
     463:  * @cfg:输出参数,cmtr(cfg文件)结构体
     464:  * @counter:  输出参数,读取的字节计数器;
     465:  *
     466:  * 返回当前pfd指针,读失败返回NULL
     467:  *
     468:  */
     469: _my_cmtr_ioptr read_cmtr_cfg_info(_my_cmtr_ioptr pfd, struct cmtr_cfg_info *cfg, int* counter)
     470: {
     471:         u8 returntag = FALSE;
     472:  
     473:         int strsize = 1024;
     474:         char* strline = NULL;
     475:         char* strlcur = NULL;
     476:         char* strlend = NULL;
     477:         _my_cmtr_ioptr curr_pfd = pfd;
     478:  
     479:         char* ptrpos = 0;
     480:  
     481:         int port1num = 0;
     482:         int port2num = 0;
     483:         char port1chr = '\0';
     484:         char port2chr = '\0';
     485:  
     486:         int index = 0;
     487:         int dataint = 0;
     488:         f32 dataflt = 0;
     489:  
     490:         _my_assert(pfd && cfg);
     491:  
     492:         strline = _my_buf_malloc(strsize);
     493:         memset(strline, '\0', strsize);
     494:  
     495:         /* read station name and  kymograph id */
     496:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     497:  
     498:         if (!curr_pfd) {
     499:                 goto RETURN_FINISH;
     500:         }
     501:         strlcur = strline;
     502:         ptrpos = strchr(strlcur, ',');
     503:         memset(cfg->station_name, '\0', CMTR_STRING_MAX_LENGTH);
     504:         memset(cfg->kymograph_id, '\0', CMTR_STRING_MAX_LENGTH);
     505:         if (ptrpos) {
     506:                 memcpy(cfg->station_name, strlcur, ptrpos - strlcur);
     507:                 if (ptrpos < strlend) {
     508:                         ptrpos += 1;
     509:                         memcpy(cfg->kymograph_id, ptrpos, strlen(ptrpos));
     510:                 }
     511:         } else {
     512:                 memcpy(cfg->station_name, strlcur, strlen(strlcur));
     513:         }
     514:  
     515:         /* read port count */
     516:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     517:         if (!curr_pfd) {
     518:                 goto RETURN_FINISH;
     519:         }
     520:         strlcur = strline;
     521:         ptrpos = strchr(strlcur, ',');
     522:         if ((!ptrpos) || (ptrpos >= strlend)) {
     523:                 goto RETURN_FINISH;
     524:         }
     525:         ptrpos += 1;
     526:         if (sscanf(ptrpos, "%d%c%*s", &port1num, &port1chr) <= 0) {
     527:                 goto RETURN_FINISH;
     528:         }
     529:         ptrpos = strchr(ptrpos, ',');
     530:         if ((!ptrpos) || (ptrpos >= strlend)) {
     531:                 goto RETURN_FINISH;
     532:         }
     533:         ptrpos += 1;
     534:         if (sscanf(ptrpos, "%d%c", &port2num, &port2chr) <= 0) {
     535:                 goto RETURN_FINISH;
     536:         }
     537:         if ((port1chr == 'A') || (port1chr == 'a')) {
     538:                 cfg->analog_count = port1num;
     539:                 cfg->digit_count = port2num;
     540:         } else if ((port1chr == 'D') || (port1chr == 'd')) {
     541:                 cfg->analog_count = port2num;
     542:                 cfg->digit_count = port1num;
     543:         } else {
     544:                 goto RETURN_FINISH;
     545:         }
     546:  
     547:         /* read analog port info */
     548:         for (index = 0; index < cfg->analog_count; index++) {
     549:                 curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     550:                 if (!curr_pfd) {
     551:                         goto RETURN_FINISH;
     552:                 }
     553:                 if (!read_cmtr_cfg_one_analog((cfg->analogs)+index, strline, strsize, strlend)) {
     554:                         goto RETURN_FINISH;
     555:                 }
     556:         }
     557:         /* read digit port info */
     558:         for (index = 0; index < cfg->digit_count; index++) {
     559:                 curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     560:                 if (!curr_pfd) {
     561:                         goto RETURN_FINISH;
     562:                 }
     563:                 if (!read_cmtr_cfg_one_digit((cfg->digits)+index, strline, strsize, strlend)) {
     564:                         goto RETURN_FINISH;
     565:                 }
     566:         }
     567:  
     568:         /* read Frequency info */
     569:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     570:         if (!curr_pfd) {
     571:                 goto RETURN_FINISH;
     572:         }
     573:         if (strline > strlend) {
     574:                 goto RETURN_FINISH;
     575:         }
     576:         if (sscanf(strline, "%f", &dataflt) <= 0) {
     577:                 goto RETURN_FINISH;
     578:         }
     579:         cfg->frequency = dataflt;
     580:  
     581:         /* read smprate count info */
     582:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     583:         if (!curr_pfd) {
     584:                 goto RETURN_FINISH;
     585:         }
     586:         if (strline > strlend) {
     587:                 goto RETURN_FINISH;
     588:         }
     589:         if (sscanf(strline, "%d", &dataint) <= 0) {
     590:                 goto RETURN_FINISH;
     591:         }
     592:         cfg->smprate_count = dataint;
     593:  
     594:         /* read smprate info */
     595:         for (index = 0; index < cfg->smprate_count; index ++) {
     596:                 curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     597:                 if (!curr_pfd) {
     598:                         goto RETURN_FINISH;
     599:                 }
     600:                 strlcur = strline;
     601:                 ptrpos = strchr(strlcur, ',');
     602:                 if ((!ptrpos) || (ptrpos >= strlend)) {
     603:                         goto RETURN_FINISH;
     604:                 }
     605:                 if (sscanf(strlcur, "%f%*s", &dataflt) <= 0) {
     606:                         goto RETURN_FINISH;
     607:                 }
     608:                 cfg->smprates[index].rate = dataflt;
     609:                 strlcur = ptrpos += 1;
     610:                 if (ptrpos > strlend) {
     611:                         goto RETURN_FINISH;
     612:                 }
     613:                 if (sscanf(strlcur, "%d", &dataint) <= 0) {
     614:                         goto RETURN_FINISH;
     615:                 }
     616:                 cfg->smprates[index].point = dataint;
     617:         }
     618:  
     619:         /* read time info */
     620:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     621:         if (!curr_pfd) {
     622:                 goto RETURN_FINISH;
     623:         }
     624:         memset(cfg->begin_time, '\0', CMTR_STRING_MAX_LENGTH);
     625:         if (strlend - strline >= 0) {
     626:                 memcpy(cfg->begin_time, strline, strlend - strline + 1);
     627:         }
     628:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     629:         if (!curr_pfd) {
     630:                 goto RETURN_FINISH;
     631:         }
     632:         memset(cfg->end_time, '\0', CMTR_STRING_MAX_LENGTH);
     633:         if (strlend - strline >= 0) {
     634:                 memcpy(cfg->end_time, strline, strlend - strline + 1);
     635:         }
     636:  
     637:         /* read dat type info */
     638:         curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
     639:         if (!curr_pfd) {
     640:                 goto RETURN_FINISH;
     641:         }
     642:         strlcur =_my_strupr(strline);
     643:         ptrpos = strstr(strlcur, "BIN");
     644:         memset(cfg->file_type, '\0', CMTR_STRING_MAX_LENGTH);
     645:         if (ptrpos > 0) {
     646:                 strcpy(cfg->file_type, "BINARY");
     647:         } else if (strstr(strlcur, "ASC") > 0) {
     648:                 strcpy(cfg->file_type, "ASCII");
     649:         }
     650:         else {
     651:                 goto RETURN_FINISH;
     652:         }
     653:  
     654:         returntag = TRUE;
     655:  
     656: RETURN_FINISH:
     657:         _my_buf_free(strline);
     658:         return returntag ? curr_pfd : NULL;
     659: }
     660:  
     661: /*
     662:  * read_cmtr_dat_smpdot_binary - 读bin格式cmtr采样点数据信息.
     663:  * @pfd:  输入输出参数,地址
     664:  * @big_endian_tag: 输入参数,标识文件中数据的字节顺序,为FALSE按照小端读(默认值),True按照大端读;
     665:  * @analog_count: 输入参数,模拟量个数;
     666:  * @digit_count: 输入参数,数字量个数;
     667:  * @dot:  输出参数,采样点信息;
     668:  * @the_smp_mins: 输出参数,统计最小值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     669:  * @the_smp_maxs: 输出参数,统计最大值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     670:  * @counter:  输出参数,读取的字节计数器;
     671:  *
     672:  * 返回当前pfd指针,读失败返回NULL
     673:  *
     674:  */
     675: _my_cmtr_ioptr read_cmtr_dat_smpdot_binary(_my_cmtr_ioptr pfd, u8 big_endian_tag,
     676:                                            int analog_count, int digit_count,
     677:                                            struct cmtr_dat_smpdot *dot,
     678:                                            u32* the_smp_mins, u32* the_smp_maxs,
     679:                                            int* counter)
     680: {
     681:         u16 data16 = 0x00;
     682:         u32 data32 = 0x00;
     683:         int oldnum = 0;
     684:  
     685:         int index = 0;
     686:         int bitpos = 0;
     687:  
     688:         _my_cmtr_ioptr curr_pfd = pfd;
     689:  
     690:         oldnum = (*counter);
     691:         data32 = 0x00;
     692:         _my_read_cmtr_data(curr_pfd, &data32, 4, *counter);
     693:         if ((*counter) <= oldnum) {
     694:                 return NULL;
     695:         }
     696:         dot->index =  big_endian_tag ? _my_btoh32(data32) : _my_ltoh32(data32);
     697:  
     698:         oldnum = (*counter);
     699:         data32 = 0x00;
     700:         _my_read_cmtr_data(curr_pfd, &data32, 4, *counter);
     701:         if ((*counter) <= oldnum) {
     702:                 return NULL;
     703:         }
     704:         dot->time =  big_endian_tag ? _my_btoh32(data32) : _my_ltoh32(data32);
     705:  
     706:         /* read analog port info */
     707:         for (index = 0; index < analog_count; index ++) {
     708:                 oldnum = (*counter);
     709:                 data16 = 0x00;
     710:                 _my_read_cmtr_data(curr_pfd, &data16, 2, *counter);
     711:                 if ((*counter) <= oldnum) {
     712:                         return NULL;
     713:                 }
     714:                 dot->analogs[index] =  big_endian_tag ? _my_btoh16(data16) : _my_ltoh16(data16);
     715:                 if (the_smp_mins) {
     716:                         if (the_smp_mins + index) {
     717:                                 the_smp_mins[index] = _my_min(the_smp_mins[index], dot->analogs[index]);
     718:                         }
     719:                 }
     720:                 if (the_smp_maxs) {
     721:                         if (the_smp_maxs + index) {
     722:                                 the_smp_maxs[index] = _my_min(the_smp_maxs[index], dot->analogs[index]);
     723:                         }
     724:                 }
     725:         }
     726:         /* read digit port info */
     727:         for (index = 0; index < digit_count; index ++) {
     728:                 oldnum = (*counter);
     729:                 data16 = 0x00;
     730:                 _my_read_cmtr_data(curr_pfd, &data16, 2, *counter);
     731:                 if ((*counter) <= oldnum) {
     732:                         return NULL;
     733:                 }
     734:                 data16 =  big_endian_tag ? _my_btoh16(data16) : _my_ltoh16(data16);
     735:                 for (bitpos = 0; bitpos < 16; bitpos++) {
     736:                         if ((index * 16 + bitpos) < digit_count) {
     737:                                 dot->digits[index * 16 + bitpos] = (data16 & (0x0001 << bitpos));
     738:                         } else {
     739:                                 break;
     740:                         }
     741:                 }
     742:         }
     743:  
     744:         return curr_pfd;
     745: }
     746:  
     747: /*
     748:  * read_cmtr_dat_smpdot_ascii - 读ascii格式cmtr采样点数据信息.
     749:  * @pfd:  输入输出参数,地址
     750:  * @read_buf: 输入参数,读缓冲,在外部申请内存,避免在内部频繁申请、释放内存;
     751:  * @buf_size: 输入参数,读缓冲区的大小;
     752:  * @analog_count: 输入参数,模拟量个数;
     753:  * @digit_count: 输入参数,数字量个数;
     754:  * @dot:  输出参数,采样点信息;
     755:  * @the_smp_mins: 输出参数,统计最小值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     756:  * @the_smp_maxs: 输出参数,统计最大值,为数组,个数至少为analog_count个,值为NULL时忽略统计;
     757:  * @counter:  输出参数,读取的字节计数器;
     758:  *
     759:  * 返回当前pfd指针,读失败返回NULL
     760:  *
     761:  */
     762: _my_cmtr_ioptr read_cmtr_dat_smpdot_ascii(_my_cmtr_ioptr pfd,
     763:                                           u8 *read_buf, int buf_size,
     764:                                           int analog_count, int digit_count,
     765:                                           struct cmtr_dat_smpdot *dot,
     766:                                           u16* the_smp_mins,u16* the_smp_maxs,
     767:                                           int* counter)
     768: {
     769:         char* ptrpos = 0;
     770:         char* strlend = 0;
     771:  
     772:         int index = 0;
     773:  
     774:         int dataint = 0;
     775:         float dataflt = 0;
     776:  
     777:         _my_cmtr_ioptr curr_pfd = pfd;
     778:  
     779:         memset(read_buf, '\0', buf_size);
     780:         curr_pfd = read_cmtr_cfg_line(curr_pfd, read_buf, buf_size, &strlend, counter);
     781:         if (!curr_pfd) {
     782:                 return NULL;
     783:         }
     784:  
     785:         ptrpos = read_buf;
     786:         if ((!ptrpos) || (ptrpos >= strlend)) {
     787:                 return NULL;
     788:         }
     789:         if (sscanf(ptrpos, "%d%*s", &dataint) <= 0) {
     790:                 return NULL;
     791:         }
     792:         dot->index = dataint;
     793:         ptrpos = strchr(ptrpos, ',');
     794:         if (!ptrpos) {
     795:                 return NULL;
     796:         }
     797:         ptrpos += 1;
     798:         if ((!ptrpos) || (ptrpos > strlend)) {
     799:                 return NULL;
     800:         }
     801:         if (sscanf(ptrpos, "%d%*s", &dataint) <= 0) {
     802:                 return NULL;
     803:         }
     804:         dot->time = dataint;
     805:  
     806:         /* read analog port info */
     807:         for (index = 0; index < analog_count; index ++) {
     808:                 ptrpos = strchr(ptrpos, ',');
     809:                 if (!ptrpos) {
     810:                         return NULL;
     811:                 }
     812:                 ptrpos += 1;
     813:                 if ((!ptrpos) || (ptrpos > strlend)) {
     814:                         return NULL;
     815:                 }
     816:                 if (sscanf(ptrpos, "%f%*s", &dataflt) <= 0) {
     817:                         return NULL;
     818:                 }
     819:                 dot->analogs[index] = dataflt;
     820:                 if (the_smp_mins) {
     821:                         if (the_smp_mins + index) {
     822:                                 the_smp_mins[index] = _my_min(the_smp_mins[index], dataflt);
     823:                         }
     824:                 }
     825:                 if (the_smp_maxs) {
     826:                         if (the_smp_maxs + index) {
     827:                                 the_smp_maxs[index] = _my_min(the_smp_maxs[index], dataflt);
     828:                         }
     829:                 }
     830:         }
     831:         /* read digit port info */
     832:         for (index = 0; index < digit_count; index ++) {
     833:                 ptrpos = strchr(ptrpos, ',');
     834:                 if (!ptrpos) {
     835:                         return NULL;
     836:                 }
     837:                 ptrpos += 1;
     838:                 if ((!ptrpos) || (ptrpos > strlend)) {
     839:                         return NULL;
     840:                 }
     841:                 if (sscanf(ptrpos, "%d%*s", &dataint) <= 0) {
     842:                         return NULL;
     843:                 }
     844:                 dot->digits[index] = dataint;
     845:         }
     846:  
     847:         return curr_pfd;
     848: }
     849:  
     850: /*
     851:  * print_cmtr_cfg_info - 打印cmtr文件配置数.
     852:  * @cfg:  输入参数,cmtr文件配置数据;
     853:  *
     854:  */
     855: void print_cmtr_cfg_info(struct cmtr_cfg_info *cfg)
     856: {
     857:         u32 index = 0;
     858:         if ( cfg ) {
     859:                 _my_printf("=====================\n");
     860:                 _my_printf("%s,%s\n", cfg->station_name, cfg->kymograph_id);
     861:                 _my_printf("%d,%dA,%dD\n", cfg->analog_count + cfg->digit_count, cfg->analog_count, cfg->digit_count);
     862:                 for (index = 0; index < cfg->analog_count; index++) {
     863:                         _my_printf("%d,%s,%s,%s,%s,%.6lf,%.6lf,%d,%d,%d\n",
     864:                                  cfg->analogs[index].index,
     865:                                  cfg->analogs[index].name,
     866:                                  cfg->analogs[index].phase,
     867:                                  cfg->analogs[index].element,
     868:                                  cfg->analogs[index].unit,
     869:                                  cfg->analogs[index].factor_a,
     870:                                  cfg->analogs[index].factor_b,
     871:                                  cfg->analogs[index].offset_time,
     872:                                  cfg->analogs[index].smp_min,
     873:                                  cfg->analogs[index].smp_max);
     874:                 }
     875:                 for (index = 0; index < cfg->digit_count; index++) {
     876:                         _my_printf("%d,%s,%d\n",
     877:                                  cfg->digits[index].index,
     878:                                  cfg->digits[index].name,
     879:                                  cfg->digits[index].state);
     880:                 }
     881:                 _my_printf("%.6f\n", cfg->frequency);
     882:                 for (index = 0; index < cfg->smprate_count; index++) {
     883:                         _my_printf("%f,%d\n", cfg->smprates[index].rate, cfg->smprates[index].point);
     884:                 }
     885:                 _my_printf("%s\n", cfg->begin_time);
     886:                 _my_printf("%s\n", cfg->end_time);
     887:                 _my_printf("%s\n", cfg->file_type);
     888:                 _my_printf("=====================\n");
     889:         }
     890: }
     891:  
     892: /*
     893:  * print_cmtr_dat_smpdot - 打印cmtr数据文件采样点.
     894:  * @cfg:  输入参数,cmtr文件配置数据;
     895:  * @analog_count: 输入参数,模拟量个数;
     896:  * @digit_count: 输入参数,数字量个数;
     897:  * @dot:  输入参数,采样点信息;
     898:  *
     899:  */
     900: void print_cmtr_dat_smpdot(int analog_count, int digit_count, struct cmtr_dat_smpdot *dot)
     901: {
     902:         int index = 0;
     903:         if ( dot ) {
     904:                 _my_printf("%u,%d", dot->index, dot->time);
     905:                 for (index = 0; index < analog_count; index++) {
     906:                         _my_printf(",%d", dot->analogs[index]);
     907:                 }
     908:                 for (index = 0; index < digit_count; index++) {
     909:                         _my_printf(",%d", dot->digits[index]);
     910:                 }
     911:                 _my_printf("\n");
     912:         }
     913: }
     914:  
     915:  
     916: #ifdef CMTR_CONSOLE_DEMO
     917:  
     918:  
     919: /*
     920:  * _my_cmtr_openrb/_my_cmtr_openwb/_my_cmtr_openab/_my_cmtr_close
     921:  *              - 可以根据需要改写该接口,如重定义为网口的recv\send、串口r\w等
     922:  * @pfd:  文件地址、缓冲区地址、或者socket地址等
     923:  * @str:  文件路径或者联机ip或者串口地址或者共享内存名称
     924:  *
     925:  */
     926: #define _my_cmtr_openrb(str)    (open((str), O_RDONLY, S_IWRITE | S_IREAD))
     927: #define _my_cmtr_openwb(str)    (open((str), O_CREAT | O_RDWR, S_IWRITE | S_IREAD))
     928: #define _my_cmtr_openab(str)    (open((str), O_CREAT | O_APPEND | O_RDWR, S_IWRITE | S_IREAD))
     929: #define _my_cmtr_close(pfd)     (close(pfd))
     930:  
     931:  
     932: /*
     933:  * cmtr_test_demo - 测试函数
     934:  *
     935:  */
     936:  
     937: void cmtr_test_demo()
     938: {
     939:         int counter1 = 0;
     940:         int counter2 = 0;
     941:         struct cmtr_dat_smpdot dot0;
     942:         struct cmtr_cfg_info cfg0;
     943:         _my_cmtr_ioptr fdcfg1 = 0;
     944:         _my_cmtr_ioptr fddat1 = 0;
     945:         _my_cmtr_ioptr fdcfg2 = 0;
     946:         _my_cmtr_ioptr fddat2 = 0;
     947:         int buf_size = 1024;
     948:         u8 *read_buf = _my_buf_malloc(buf_size);
     949:         int analog_count = 0;
     950:         int digit_count = 0;
     951:         u16 *the_smp_mins = 0;
     952:         u16 *the_smp_maxs = 0;
     953:  
     954:         fdcfg1 = _my_cmtr_openrb("E:/iec-61850/test_r.cfg");
     955:         fdcfg2 = _my_cmtr_openwb("E:/iec-61850/test_w.cfg");
     956:         _my_assert(fdcfg1);
     957:         _my_assert(fdcfg2);
     958:         read_cmtr_cfg_info(fdcfg1, &cfg0, &counter1);
     959:         print_cmtr_cfg_info(&cfg0);
     960:         write_cmtr_cfg_info(fdcfg2, &cfg0, &counter2);
     961:         _my_cmtr_close(fdcfg1);
     962:         _my_cmtr_close(fdcfg2);
     963:  
     964:  
     965:         fddat1 = _my_cmtr_openrb("E:/iec-61850/test_r.dat");
     966:         fddat2 = _my_cmtr_openwb("E:/iec-61850/test_w.dat");
     967:         while (_my_check_cmtr_ptr(fddat1)) {
     968:                 analog_count = cfg0.analog_count;
     969:                 digit_count = cfg0.digit_count;
     970:                 if (analog_count > 0) the_smp_mins = _my_buf_malloc(2*analog_count);
     971:                 if (analog_count > 0) the_smp_maxs = _my_buf_malloc(2*analog_count);
     972:                 fddat1 = read_cmtr_dat_smpdot_ascii(fddat1,
     973:                                            read_buf, buf_size,
     974:                                            analog_count, digit_count,
     975:                                            &dot0,
     976:                                            the_smp_mins, the_smp_maxs,
     977:                                            &counter1);
     978:                 if (_my_check_cmtr_ptr(fddat1)) {
     979:                         print_cmtr_dat_smpdot(analog_count, digit_count, &dot0);
     980:                         fddat2 = write_cmtr_dat_smpdot_ascii(fddat2, analog_count, digit_count, &dot0, &counter2);
     981:                 }
     982:         }
     983:         _my_cmtr_close(fddat1);
     984:         _my_cmtr_close(fddat2);
     985: }
     986:  
     987:  
     988: /*
     989:  * main - 测试main函数
     990:  *
     991:  */
     992: int main(int argc, char* argv[])
     993: {
     994:         cmtr_test_demo();
     995:         getchar();
     996:         return 0;
     997: }
     998:  
     999:  
    1000: #endif /* CMTR_CONSOLE_DEMO */
    1001:  
    1002:  
  • 相关阅读:
    ECharts之柱状图 饼状图 折线图
    Vue自定义指令(directive)
    HDU 1231 最大连续子序列
    POJ 2533 Longest Ordered Subsequence
    HDU 1163 Eddy's digital Roots
    HDU 2317 Nasty Hacks
    HDU 2571 命运
    HDU 4224 Enumeration?
    HDU 1257 最少拦截系统
    HDU 2740 Root of the Problem
  • 原文地址:https://www.cnblogs.com/lizhi0755/p/2756702.html
Copyright © 2011-2022 走看看