2015-01-07 2 views
0

Linux 라이브러리 rtl_fm의 출력을 구문 분석하는 C 모듈을 변환하려고합니다. 그것은 DVB-T 동글C를 파이썬으로 변환

은 C 모듈이 잘 작동하지만 난 그것이 내가 상수를 넣어 가지고

내가 가진 다른 파이썬 모듈과 상호 작용하는 파이썬으로 작성합니다 throuh Efergy 미터에서 에너지 사용량을 잡기 위해 사용된다 constant.py

에서 나는 열 변환에 완전히 붙어 : cursamp = (int16_t) (는 fgetc (표준 입력) |는 fgetc (표준 입력) < < 8); 나는 많은 다른 방법으로 변환하려고 노력했다. 모든 시도는 오류로 끝납니다!

두 가지 유형의 문제 인 것 같습니다. 1. 입력 결과의 유형 변환 2. fgetc()를 파이썬으로 변환하는 방법.

또한 도움이 될 수 동안 (! 무엇이 일어 났는지를 결정하기 위해 feof (표준 입력)) 파이썬에

누구나 변환 문제가?

아래

C 코드 :

#include <stdio.h> 
#include <stdint.h> 
#include <time.h> 
#include <math.h> 

#include <stdlib.h> // For exit function 

#define VOLTAGE   240 /* Refernce Voltage */ 
#define CENTERSAMP  100 /* Number of samples needed to compute for the wave center */ 
#define PREAMBLE_COUNT  40 /* Number of high(1) samples for a valid preamble */ 
#define MINLOWBIT  3 /* Number of high(1) samples for a logic 0 */ 
#define MINHIGHBIT  8 /* Number of high(1) samples for a logic 1 */ 
#define E2BYTECOUNT  8 /* Efergy E2 Message Byte Count */ 
#define FRAMEBITCOUNT  64 /* Number of bits for the entire frame (not including preamble) */ 


#define LOGTYPE  1 // Allows changing line-endings - 0 is for Unix /n, 1 for Windows /r/n 
#define SAMPLES_TO_FLUSH 10 // Number of samples taken before writing to file. 
       // Setting this too low will cause excessive wear to flash due to updates to 
       // filesystem! You have been warned! Set to 10 samples for 6 seconds = every min. 

int loggingok; // Global var indicating logging on or off 
int samplecount; // Global var counter for samples taken since last flush 
FILE *fp; // Global var file handle 

int calculate_watts(char bytes[]) 
{ 

char tbyte; 
double current_adc; 
double result; 
int i; 

time_t ltime; 
struct tm *curtime; 
char buffer[80]; 

    /* add all captured bytes and mask lower 8 bits */ 

    tbyte = 0; 

    for(i=0;i<7;i++) 
     tbyte += bytes[i]; 

    tbyte &= 0xff; 

    /* if checksum matches get watt data */ 

    if (tbyte == bytes[7]) 
    { 
     time(&ltime); 
     curtime = localtime(&ltime); 
     strftime(buffer,80,"%x,%X", curtime); 

     current_adc = (bytes[4] * 256) + bytes[5]; 
     result = (VOLTAGE * current_adc)/((double) 32768/(double) pow(2,bytes[6])); 
     printf("%s,%f\n",buffer,result); 
     if(loggingok) { 
      if(LOGTYPE) { 
      fprintf(fp,"%s,%f\r\n",buffer,result); 
      } else { 
      fprintf(fp,"%s,%f\n",buffer,result); 
      } 
      samplecount++; 
      if(samplecount==SAMPLES_TO_FLUSH) { 
      samplecount=0; 
      fflush(fp); 
      } 
     } 
     fflush(stdout); 
     return 1; 
    } 
    //printf("Checksum Error \n"); 
    return 0; 
} 

void main (int argc, char**argv) 
{ 

char bytearray[9]; 
char bytedata; 

int prvsamp; 
int hctr; 
int cursamp; 
int bitpos; 
int bytecount; 

int i; 
int preamble; 
int frame; 
int dcenter; 
int dbit; 

long center; 

    if(argc==2) { 
     fp = fopen(argv[1], "a"); // Log file opened in append mode to avoid destroying data 
     samplecount=0; // Reset sample counter 
     loggingok=1; 
     if (fp == NULL) { 
      perror("Failed to open log file!"); // Exit if file open fails 
      exit(EXIT_FAILURE); 
     } 
    } else { 
     loggingok=0; 
    } 

    printf("Efergy E2 Classic decode \n\n"); 


    /* initialize variables */ 

    cursamp = 0; 
    prvsamp = 0; 

    bytedata = 0; 
    bytecount = 0; 
    hctr = 0; 
    bitpos = 0; 
    dbit = 0; 
    preamble = 0; 
    frame = 0; 

    dcenter = CENTERSAMP; 
    center = 0; 

    while(!feof(stdin)) 
    { 

     cursamp = (int16_t) (fgetc(stdin) | fgetc(stdin)<<8); 

     /* initially capture CENTERSAMP samples for wave center computation */ 

     if (dcenter > 0) 
     { 
      dcenter--; 
      center = center + cursamp; /* Accumulate FSK wave data */ 

      if (dcenter == 0) 
      { 
       /* compute for wave center and re-initialize frame variables */ 

       center = (long) (center/CENTERSAMP); 

       hctr = 0; 
       bytedata = 0; 
       bytecount = 0; 
       bitpos = 0; 
       dbit = 0; 
       preamble = 0; 
       frame = 0; 
      } 

     } 
     else 
     { 
      if ((cursamp > center) && (prvsamp < center))  /* Detect for positive edge of frame data */ 
       hctr = 0; 
      else 
       if ((cursamp > center) && (prvsamp > center))  /* count samples at high logic */ 
       { 
        hctr++; 
        if (hctr > PREAMBLE_COUNT) 
         preamble = 1; 
       } 
       else 
        if ((cursamp < center) && (prvsamp > center)) 
        { 
         /* at negative edge */ 

         if ((hctr > MINLOWBIT) && (frame == 1)) 
         { 
          dbit++; 
          bitpos++; 
          bytedata = bytedata << 1; 
          if (hctr > MINHIGHBIT) 
           bytedata = bytedata | 0x1; 

          if (bitpos > 7) 
          { 
           bytearray[bytecount] = bytedata; 
           bytedata = 0; 
           bitpos = 0; 

           bytecount++; 

           if (bytecount == E2BYTECOUNT) 
           { 

            /* at this point check for checksum and calculate watt data */ 
            /* if there is a checksum mismatch compute for a new wave center */ 

            if (calculate_watts(bytearray) == 0) 
             dcenter = CENTERSAMP; /* make dcenter non-zero to trigger center resampling */ 
           } 
          } 

          if (dbit > FRAMEBITCOUNT) 
          { 
           /* reset frame variables */ 

           bitpos = 0; 
           bytecount = 0; 
           dbit = 0; 
           frame = 0; 
           preamble = 0; 
           bytedata = 0; 
          } 
         } 

         hctr = 0; 

        } 
        else 
         hctr = 0; 

      if ((hctr == 0) && (preamble == 1)) 
      { 
       /* end of preamble, start of frame data */ 
       preamble = 0; 
       frame = 1; 
      } 

     } /* dcenter */ 

     prvsamp = cursamp; 

    } /* while */ 
    if(loggingok) { 
     fclose(fp); // If rtl-fm gives EOF and program terminates, close file gracefully. 
    } 
} 

그리고 파이썬 전환 (파일 로그인하지 않고 약간 단순화)

from datetime import date 
from datetime import time 
from datetime import datetime 
import cmath 
import constant 
import sys 
import logging 

logging.basicConfig(level=logging.DEBUG) 
logger = logging.getLogger(__name__) 


class _Getch: 
    """Gets a single character from standard input. Does not echo to the 
screen.""" 
    def __init__(self): 
     try: 
      self.impl = _GetchWindows() 
     except ImportError: 
      self.impl = _GetchUnix() 

    def __call__(self): return self.impl() 


class _GetchUnix: 
    def __init__(self): 
     import tty, sys 

    def __call__(self): 
     import sys, tty, termios 
     fd = sys.stdin.fileno() 
     old_settings = termios.tcgetattr(fd) 
     try: 
      tty.setraw(sys.stdin.fileno()) 
      ch = sys.stdin.read(1) 
     finally: 
      termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
     return ch 


class _GetchWindows: 
    def __init__(self): 
     import msvcrt 

    def __call__(self): 
     import msvcrt 
     return msvcrt.getch() 


getch = _Getch() 

def calculate_watts(*args): 
    logger.info('Start Calculation') 
    now = datetime.now() 

    tbyte = 0 

    for i in range(0,7): 
     tbyte += bytes[i] 

    tbyte = tbyte & 0xff 

    if (tbyte == bytes[7]): 
     current_adc = (bytes[4] * 256) + bytes[5] 
     result = (constant.VOLTAGE * current_adc)/(32768/pow(2,bytes[6])) 
     print "%s,%f\n" % (now,result) 
     exit(0) 
    else: 
     print "Checksum Error \n" 
     exit(1) 

def main(*argv): 
    logger.info('Starting Main') 

    print "Efergy E2 Python decode \n\n" 

    cursamp = 0 
    prvsamp = 0 

    bytedata = 0 
    bytecount = 0 
    hctr = 0 
    bitpos = 0 
    dbit = 0 
    preamble = 0 
    frame = 0 

    dcenter = constant.CENTERSAMP 
    center = 0 

    while (1): 

     cursamp = (int)((int)(_Getch()) | (int)(_Getch())<<8) 
     logger.debug('cursamp: %f',cursamp) 

     if (dcenter > 0): 
      dcenter -= 1 
      center = center + cursamp #/* Accumulate FSK wave data */ 
      if (dcenter == 0): 

       center = (center/constant.CENTERSAMP) 
       hctr = 0 
       bytedata = 0 
       bytecount = 0 
       bitpos = 0 
       dbit = 0 
       preamble = 0 
       frame = 0 
     else: 
      if ((cursamp > center) and (prvsamp < center)):  #/* Detect for positive edge of frame data */ 
       hctr = 0 
      else: 
       if ((cursamp > center) and (prvsamp > center)):  #/* count samples at high logic */ 
        hctr += 1 
        if (hctr > constant.PREAMBLE_COUNT):  
         preamble = 1 
       else: 
        if ((cursamp < center) and (prvsamp > center)): 
         #/* at negative edge */ 
         if ((hctr > constant.MINLOWBIT) and (frame == 1)): 
          dbit += 1 
          bitpos += 1  
          bytedata = bytedata << 1 
          if (hctr > constant.MINHIGHBIT): 
           bytedata = bytedata | 0x1 
          if (bitpos > 7): 
           bytearray[bytecount] = bytedata 
           bytedata = 0 
           bitpos = 0 

           bytecount += 1 

           if (bytecount == constant.E2BYTECOUNT): 

            # /* at this point check for checksum and calculate watt data */ 
            # /* if there is a checksum mismatch compute for a new wave center */ 

            if (calculate_watts(bytearray) == 0): 
             dcenter = constant.CENTERSAMP #/* make dcenter non-zero to trigger center resampling */ 

          if (dbit > constant.FRAMEBITCOUNT): 
           #/* reset frame variables */ 

           bitpos = 0 
           bytecount = 0 
           dbit = 0 
           frame = 0 
           preamble = 0 
           bytedata = 0 

         hctr = 0 

        else: 
         hctr = 0 

      if ((hctr == 0) and (preamble == 1)): 

       #/* end of preamble, start of frame data */ 
       preamble = 0 
       frame = 1 

     #/* dcenter */ 

     prvsamp = cursamp 

if __name__ == "__main__": 
    main() 

답변

3

C의 fgetc(stdin) 2의 ord(sys.stdin.read(1)[0]) 파이썬 변환 -로부터 숫자 값을 반환 다음 바이트는 stdin입니다. (파이썬 3에서는 이것을 달성하기 위해 sys.stdin을 바이너리로 다시 열어야합니다. 그렇지 않으면 .read(1)은 바이트가 아닌 유니 코드 문자를 갖게됩니다).

|<< 연산자는 C와 마찬가지로 Python에서 동일하게 작동하므로 문제는 없습니다.

EOF에서 sys.stdin.read(1)은 빈 목록을 반환합니다 (따라서 [0]은 실패하지만 위 식을 "분해"하여 확인할 수 있음). 까다로운 문제 WRT의 엔디안 (바이트 순서) 및 문자의 부호의 (C와 파이썬에 대한 일반적인 문제)의

ateof = False 

def getabyte(): 
    data = sys.stdin.read(1) 
    if data: return False, ord(data) 
    else: return True, 0 

def getanint(): 
    global ateof 
    ateof, byte1 = getabyte() 
    if not ateof: 
     ateof, byte2 = getabyte() 
    if ateof: return True, 0 
    else: return False, byte1 | (byte2<<8) 

그물 예를 들면 다음과 같습니다.

+0

감사합니다 @Alex, 제대로 작동하는 것 같습니다. 그러나 나는 다른 부분에 갇혀있다. 'tbyte = 0 # (i = 0; i <7; i ++) # tbyte + = bytes [i]; 범위 내 (0,7)에 대해 : 오류를 렌더링하는 tbyte + = bytes [i] 'TypeError :'type '객체에'__getitem__ '속성이 없습니다. –

+0

@MikaelLjunggren, 기꺼이 도와주세요 ** ** 도움이되는 답변을 받아들이십시오. 그냥 고마워하지 마세요. -) –

+0

@MikaelLjunggren 괜찮습니다. 우리는 모두 언젠가 초보자였습니다 :-) 대답의 왼쪽에있는 체크 표시를 클릭하십시오. 당신이 대답을 받아들이는 방법이며, 도움이되는 대답이 받아 들여 지도록 SO가 기능하는 것이 중요합니다. –