def whPPValue(self, whAdr=0, HiB='00', LoB='00'): """Method is intended for reading value of power profile by given record address Sends command to read the value of power profile by given record address Args: whAdr (int): the metering device address, for Mercury 230 from 1 to 240, 0 corresponds to the address of any device on the bus. HiB (str): high byte records addres, default value - 00. LoB (str): low byte records addres, default value - 00. Returns: dict: with key: (type) value. HiB :(str) high byte records addres. LoB :(str) low byte records addres. Status: (str) binary representation of records status (check protocol), e.g. 11001. H: (str) records Hour fixation. m: (str) records Minute fixation. d: (str) records Day fixation. m: (str) records Month fixation. y: (str) records Year fixation. Period: (int) power discreteness. A :(float) active energy value. R :(float) reactive energy value. Examples: >>> PPVal = merc.whPPValue(whAdr=145, HiB='48', LoB='E0') >>> print 'Record Status: %s, Period: %s, A: %s, R: %s, DateTime: %s-%s-%s %s:%s' % \ (PPVal['Status'], PPVal['Period'], PPVal['A'], PPVal['R'], PPVal['d'], PPVal['m'], PPVal['y'], PPVal['H'], PPVal['M']) Last Record Status: 1001, Period: 30, A: 0.0, R: 0.0, DateTime: 16-06-15 12:30 """ chByte = lambda x: chr(int(x, 16)) whPPValCmd = chr(whAdr) + '\x06\x03' + chByte(HiB) + chByte(LoB) + '\x0F' ans = self.cmdWR(whPPValCmd) if ans and self._whAnsCheck(whAdr, ans): try: PPV = { 'Status':bin(int(ans[1], 16))[2:], 'H':chSim(ans[2]), 'M':chSim(ans[3]), 'd':chSim(ans[4]), 'm':chSim(ans[5]), 'y':chSim(ans[6]), 'Period':int(ans[7], 16), 'A':int(ans[9]+ans[8], 16)*0.001, 'R':int(ans[13]+ans[12], 16)*0.001 } except Exception, e: logging.error(u'Не удалось выполнить чтение записи профиля мощности по адресу 0x%s%s! Причина: %s' % (HiB,LoB,e)) PPV = False
def whPPLastRecord(self, whAdr=0): """Method is intended for reading last record values of power profile Sends command to read the last record values of power profile Args: whAdr (int): the metering device address, for Mercury 230 from 1 to 240, 0 corresponds to the address of any device on the bus. Returns: dict: with key: (type) value. HiB :(str) high byte records addres. LoB :(str) low byte records addres. Status: (str) binary representation of records status (check protocol), e.g. 11001 H: (str) records Hour fixation m: (str) records Minute fixation d: (str) records Day fixation m: (str) records Month fixation y: (str) records Year fixation Period: (int) power discreteness Examples: >>> PPLR = merc.whPPLastRecord(whAdr=145) >>> print 'Last Record Status: %s, Period: %s, High Byte: %s, Low Byte: %s, DateTime: %s-%s-%s %s:%s' % \ (PPLR['Status'], PPLR['Period'], PPLR['HiB'], PPLR['LoB'], PPLR['d'], PPLR['m'], PPLR['y'], PPLR['H'], PPLR['M']) Last Record Status: 11001, Period: 30, High Byte: 49, Low Byte: 30, DateTime: 16-06-15 12:30 """ PPLR = False whPPLRCmd = chr(whAdr) + '\x08\x13' ans = self.cmdWR(whPPLRCmd) if ans and self._whAnsCheck(whAdr, ans): try: PPLR = { 'HiB':ans[1], 'LoB':ans[2], 'Status':bin(int(ans[3], 16))[2:], 'H':chSim(ans[4]), 'M':chSim(ans[5]), 'd':chSim(ans[6]), 'm':chSim(ans[7]), 'y':chSim(ans[8]), 'Period':int(ans[9], 16), } except Exception, e: logging.error(u'Не удалось выполнить чтение последней записи профиля мощности! Причина: %s' % e) PPLR = False
def TXRX(self, cmd): answer = [] ansHex = [] ansChr='' attempts = self.attempt timeO=0 while attempts>0: cmdTX = self.TX(cmd + self.CRC.calculate(cmd)) logging.debug(u'TX >>> %s [%s]' % (" ".join(cmdTX[0]), str(cmdTX[1]))) while timeO < self.whTimeout: time.sleep(0.1) ansChr += self.RX() ansHex += [chSim(hex(ord(x))[2:]) for x in ansChr] if self.CRC.check(ansChr): timeO = self.whTimeout cmdRX = [ansHex, len(ansHex)] logging.debug(u'RX <<< %s [%s]' % (" ".join(cmdRX[0]), str(cmdRX[1]))) else: timeO += 0.1 if self.CRC.check(ansChr): attempts = 0 answer = ansHex else: attempts -= 1 timeO = 0 answer = u'Нет ответа от устройства!' logging.error(answer) return answer
def whNum(self, whAdr=0): """Method is intended to read the serial number of the metering device Sends command to read the serial number of the metering device Args: whAdr (int): the metering device address, for Mercury 230 from 1 to 240, 0 corresponds to the address of any device on the bus. Returns: str: device serial number as a string. Examples: >>> m230.whNum (whAdr = 145) 11199145 """ whNum = False whNumCmd = chr(whAdr) + '\x08\x00' logging.info(u'Чтение серийного номера прибора учета: %s' % str(whAdr)) ans = self.cmdWR(whNumCmd) if ans and self._whAnsCheck(whAdr, ans): try: whN = [chSim(str(int(x, 16))) for x in ans[1:5]] whNum = "".join(whN) except Exception, e: logging.error(u'Не удалось выполнить чтение серийного номера прибора учета! Причина: %s' % e) whNum = False
def TXRX(self, cmd, crcString, crcCheck, getRX, ansChLine): answer = [] ansHex = [] ansHex1 = [] ansChr='' ansBuf = '' attempts = self.attempt cmdTX = self.TX(cmd + self.CRC.calculate(crcString)) logging.debug(u'TX >>> %s <<<>>> %s [%d]' % (" ".join(cmdTX[0]), cmdTX[1], cmdTX[2])) if getRX: while True and attempts>0: time.sleep(self.whRXTimeout) ansChr += self.RX() ansBuf += ansChr if self.RX_check(ansBuf, crcCheck, ansChLine): attempts = 0 ansHex += [chSim(hex(ord(x))[2:]) for x in ansBuf] # answer = ansHex #! cmdRX = [ansHex, ansBuf, len(ansHex)] # logging.debug(u'RX <<< %s <<<>>> %s [%s]' % (" ".join(cmdRX[0]), cmdRX[1], str(cmdRX[2]))) else: attempts -= 1 ansHex += [chSim(hex(ord(x))[2:]) for x in ansChr] # cmdRX = [ansHex, ansChr, len(ansHex)] logging.debug(u'RX <<< %s <<<>>> %s [%s]' % (" ".join(cmdRX[0]), cmdRX[1], str(cmdRX[2]))) ansChr=''#!!!!!!!!!!!!! if attempts>0: logging.error(u'Осталось попыток запроса: %d' % attempts) else: logging.error(u'Количество попыток запроса исчерпано!') ''' if self.RX_check(ansChr, crcCheck, ansChLine): attempts = 0 answer = ansHex else: attempts -= 1 timeO = 0 answer = False ''' else: attempts = 0 answer = True return answer
def _whAnsCheck(self, whAdr=0, ansCmd=[]): whAnsDict = { '00':u'Все нормально', '01':u'Недопустимая команда или параметр', '02':u'Внутренняя ошибка счетчика', '03':u'Не достаточен уровень доступа для удовлетворения запроса', '04':u'Внутренние часы счетчика уже корректировались в течение текущих су¬ток', '05':u'Не открыт канал связи', } if not ansCmd: logging.error(u'Для анализа ответа дана пустая строка!') return False else: if (ansCmd[0]==chSim(hex(whAdr)[2:]) and len(ansCmd)>4) or ansCmd[0:2] == [chSim(hex(whAdr)[2:]), '00']: return True else: logging.error(whAnsDict[ansCmd[1]]) return False
def TX(self, cmd): totalsent = 0 while totalsent < len(cmd): #print len(cmd) sent = self.sock.send(cmd[totalsent:]) if sent == 0: raise RuntimeError("socket connection broken") totalsent = totalsent + sent cmdsend = [chSim(hex(ord(x))[2:]) for x in cmd] cmdTX = [cmdsend, cmd, len(cmdsend)] return cmdTX
def TX(self, cmd): """ Метод предназначен для отправки данных в порт Принимает в качестве параметров команду Возвращает список: cmdTX[0] - список, отправленная команда в 16-м представлении cmdTX[1] - количество отправленных байт """ self.ser.write(cmd) cmdsend = [chSim(hex(ord(x))[2:]) for x in cmd] cmdTX = [cmdsend, len(cmdsend)] return cmdTX
def modemTXRX(self, cmd, modemTimeout=5): ansHex = [] answer = [] ansChr='' cmdTX = self.modemTX(cmd) logging.debug(u'TX >>> ' + " ".join(cmdTX[0]) + ' <<<>>> ' + cmdTX[1] + ' [' + str(cmdTX[2]) +'] ') time.sleep(modemTimeout) ansChr += self.modemRX() ansHex += [chSim(hex(ord(x))[2:]) for x in ansChr] cmdRX = [ansHex, ansChr, len(ansHex)] logging.debug(u'RX <<< ' + " ".join(cmdRX[0]) + ' <<<>>> ' + cmdRX[1] + ' [' + str(cmdRX[2]) +'] ') answer = [ansHex, ansChr] return answer
def TXRX(self, cmd, byteExpected=0): answer = [] ansHex = [] answer = [] ansChr='' timeO=0 attempts = self.attempt while attempts>0: cmdTX = self.TX(cmd + self.CRC.calculate(cmd)) logging.debug(u'TX >>> ' + " ".join(cmdTX[0]) + ' [' + str(cmdTX[1]) +'] ') ansChr += self.RX() ansHex += [chSim(hex(ord(x))[2:]) for x in ansChr] """" while timeO < self.whTimeout: print timeO time.sleep(0.1) ansChr += self.RX() ansHex += [chSim(hex(ord(x))[2:]) for x in ansChr] if self.CRC.check(ansChr): timeO = self.whTimeout cmdRX = [ansHex, len(ansHex)] logging.debug(u'RX <<< ' + " ".join(cmdRX[0]) + ' [' + str(cmdRX[1]) +'] ') else: timeO += 0.1 """ if self.CRC.check(ansChr): attempts = 0 answer = ansHex ####### cmdRX = [ansHex, len(ansHex)] logging.debug(u'RX <<< ' + " ".join(cmdRX[0]) + ' [' + str(cmdRX[1]) +'] ') ####### else: attempts -= 1 timeO = 0 answer = False if attempts>0: logging.error(u'Осталось попыток запроса: %d' % attempts) else: logging.error(u'Количество попыток запроса исчерпано!') return answer
def TX(self, cmd): """ Метод предназначен для отправки данных в порт Принимает в качестве параметров команду Возвращает список: cmdTX[0] - список, отправленная команда в 16-м представлении cmdTX[1] - количество отправленных байт """ totalsent = 0 while totalsent < len(cmd): #print len(cmd) sent = self.sock.send(cmd[totalsent:]) if sent == 0: raise RuntimeError("socket connection broken") totalsent = totalsent + sent cmdsend = [chSim(hex(ord(x))[2:]) for x in cmd] cmdTX = [cmdsend, len(cmdsend)] return cmdTX """