/* ***************************************************************************** Программа для снятия показаний счетчика ЦЭ6827М1 через преобразователь RS232-RS485 для роутера BR6104KP на базе процессора ADM5120 и Linux 2.4.32 V 0.15 05.05.2005 adm5120.narod.ru ***************************************************************************** Команды для счетчика: T1 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 80 40 04 86 03 T2 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 80 44 04 FA 03 T3 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 80 48 04 7E 03 T янв 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 C3 B0 04 CA 03 T Фев 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 C3 00 04 F2 03 T март 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 C3 10 04 B7 03 М.Мощн. 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 80 34 16 02 40 03 1/2 ч. 00 00 00 00 00 00 00 02 02 16 03 32 04 00 00 00 00 00 C2 6A 16 02 90 03 Ответы счётчика : */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #define BAUDRATE B2400 /* скорость порта 2400 бод */ #define MODEMDEVICE "/dev/ttyS1" /* порт обмена */ #define _POSIX_SOURCE 1 /* POSIX-совместимый источник */ #define ADD 26369.69 /* слагаемое для получения знач старого сч */ //#define debug 1 main(int argc, char *argv[]) { int fd,c,i,j,k,m,res; double t,t1,t2,t3; struct termios oldtio,newtio; /* Начальные байты блока передачи,содержащие адрес счётчика*/ unsigned char pre[18] = {0,0,0,0,0,0,0,2,2,0x16,3,0x32,4,0,0,0,0,0}; /* Длина,конечные байты блока передачи содержащие команду и контрольную сумму */ unsigned char cmd[5][10]= { {5, 0x80, 0x40, 0x04, 0x86, 0x03}, /* T1 */ {5, 0x80, 0x44, 0x04, 0xFA, 0x03}, /* T2 */ {5, 0x80, 0x48, 0x04, 0x7E, 0x03}, /* T3 */ {6, 0x80, 0x34, 0x16, 0x02, 0x40, 0x03}, /* M */ {6, 0xC2, 0x6A, 0x16, 0x02, 0x90, 0x03}, /* H */ }; /* смещение от конца до первой цифры, множитель, количество знаков */ unsigned char rec[7][10]= { {3, 1, 4}, /* T1 */ {3, 1, 4}, /* T2 */ {3, 1, 4}, /* T3 */ {4,60, 1}, /* M */ {3, 2, 2}, /* H */ {0, 0, 0}, /* OLD */ {0, 0, 0}, /* TS */ }; unsigned char argu[7][10]= { {"T1"}, {"T2"}, {"T3"}, {"M"}, {"H"}, {"OLD"}, {"TS"}, }; unsigned char bufr[255]; if ( argc == 1 ) { printf("program for CE6827M1\nversion 0.15\nCOM=%s\n",MODEMDEVICE); printf("ce [T1][T2][T3][OLD][M][H][TS]\n "); exit(-1); } fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); if (fd <0) { perror(MODEMDEVICE); printf ("error_open %s\n",MODEMDEVICE); exit(-1); } tcgetattr(fd,&oldtio); /* сохранение текущих установок порта */ bzero(&newtio, sizeof(newtio)); // 2400 bod, 8 bit data, 2-stop, no paritet newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD |CSTOPB ; newtio.c_iflag = IGNPAR | ICRNL; newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; /* посимвольный таймер не используется */ newtio.c_cc[VMIN] = 0; /* не блокированное чтение */ tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); for ( k = 1; k < argc; k++) for ( m = 0; m < 7; m++) { if (strcmp(argv[k],argu[m]) == 0) { printf("%3s ",argu[m]); t=0; switch (m) { case 5:t=ADD; case 6:t=t+t1+t2; printf("=%8.2f kW/h\n",t); break; default: write(fd,pre,18); write(fd,&cmd[m][1],cmd[m][0]); sleep(1); /* ждём секунду входных данных */ res = read(fd,bufr,255); /* считываем что есть в буфере */ #if debug printf("\nbyte=%d\n",res); for (i = 0;i < res; i++) { printf("%2X ",bufr[i]);} #endif if ( res < ( cmd[m][0]+19+rec[m][0]) ) { printf("timeout.. %d\n",res ); } else { j = res - rec[m][0]; t = 0; for ( i = 0; i < rec[m][2]; i++){ t = bufr[j-i]+t*100; switch (bufr[j-i]) { /*убираем лишний символ перед 2 и 3 */ case 2:case 3: --j ; } } t = t/100*rec[m][1]; switch (m) { case 0:t1 = t;break; case 1:t2 = t;break; case 2:t3 = t;break; } printf("=%8.2f kW/h\n",t); } } } } // востановить состояние порта tcsetattr(fd,TCSANOW,&oldtio); close(MODEMDEVICE); #if debug printf("\nclose\n"); #endif }