def GenerateFakeV4BData(MeterId): Messages.ResponseMsg = GenerateV4AData(MeterId) Messages.ResponseMsg[ Messages.ResponseV4_respKind] = Messages.RequestMsgV4ReqTypeB Messages.ResponseMsg[Messages.CrcField] = a2b_hex( calc_crc16(Messages.ResponseMsg[Messages.CrcCalc])) return Messages.ResponseMsg
def GenerateV4BData(MeterId=bytearray( b'\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30')): if (minutesOffset > 0) or ((MeterId.decode('ascii') != myMeterId) and not anyMeterOk): return GenerateFakeV4BData(MeterId) else: Messages.ResponseMsg = GetDatabaseV4BData(MeterId) if Messages.ResponseMsg is None: return GenerateFakeV4BData(MeterId) Messages.ResponseMsg[Messages.ResponseV4_meterNo] = MeterId Messages.ResponseMsg[Messages.CrcField] = a2b_hex( calc_crc16(Messages.ResponseMsg[Messages.CrcCalc])) return Messages.ResponseMsg
def GenerateRandomDataTable(tableId=b'\x30\x30\x30\x30'): Messages.ResponseMsg = bytearray(255) Messages.ResponseMsg[Messages.RespondTable_STX] = Messages.STX Messages.ResponseMsg[Messages.RespondTable_tableId] = tableId Messages.ResponseMsg[ Messages.RespondTable_preamble] = Messages.RespondTablepreamble for i in range(len(Messages.ResponseMsg[Messages.RespondTable_body])): Messages.ResponseMsg[Messages.RespondTable_body][i] = random.randint( 0x30, 0x39) Messages.ResponseMsg[ Messages.RespondTable_postamble] = Messages.RespondTablepostamble Messages.ResponseMsg[Messages.CrcField] = a2b_hex( calc_crc16(Messages.ResponseMsg[Messages.CrcCalc])) return Messages.ResponseMsg
def GenerateV3Data(MeterId=bytearray( b'\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30')): Messages.ResponseMsg = bytearray(255) # Fill the message with random digits for i in range(len(Messages.ResponseMsg)): Messages.ResponseMsg[i] = random.randint(0x30, 0x39) # Put in known fields Messages.ResponseMsg[Messages.ResponseV3_STX] = Messages.STX Messages.ResponseMsg[Messages.ResponseV3_model] = Messages.ResponseV3model Messages.ResponseMsg[Messages.ResponseV3_FWver] = Messages.ResponseV3FWver Messages.ResponseMsg[Messages.ResponseV3_meterNo] = MeterId Messages.ResponseMsg[Messages.ResponseV3_time] = makeEkmDateTime() Messages.ResponseMsg[Messages.ResponseV3_reserved] = bytearray( len(Messages.ResponseMsg[Messages.ResponseV3_reserved])) Messages.ResponseMsg[ Messages.ResponseV3_postamble] = Messages.ResponseV3postamble Messages.ResponseMsg[Messages.CrcField] = a2b_hex( calc_crc16(Messages.ResponseMsg[Messages.CrcCalc])) return Messages.ResponseMsg
def GenerateFakeV4AData(MeterId): Messages.ResponseMsg = bytearray(255) # Fill the message with random digits for i in range(len(Messages.ResponseMsg)): Messages.ResponseMsg[i] = random.randint(0x30, 0x39) # Put in known fields Messages.ResponseMsg[Messages.ResponseV4_STX] = Messages.STX Messages.ResponseMsg[Messages.ResponseV4_model] = Messages.ResponseV4model Messages.ResponseMsg[Messages.ResponseV3_FWver] = Messages.ResponseV4FWver Messages.ResponseMsg[Messages.ResponseV4_meterNo] = MeterId Messages.ResponseMsg[ Messages.ResponseV4_postamble] = Messages.ResponseV4postamble Messages.ResponseMsg[Messages.ResponseV4_time] = makeEkmDateTime() Messages.ResponseMsg[ Messages.ResponseV4_respKind] = Messages.RequestMsgV4ReqTypeB Messages.ResponseMsg[Messages.ResponseV4AData_kwhDecimals] = b'\x32' Messages.ResponseMsg[Messages.CrcField] = a2b_hex( calc_crc16(Messages.ResponseMsg[Messages.CrcCalc])) return Messages.ResponseMsg
def handle(self): ''' result = conn.execute("SELECT MeterData, MeterTime FROM `"+schema+"`.`"+meterAtable + "` WHERE ComputerTime > timestampadd(minute, -12, now()) ORDER BY idRawMeterData LIMIT 2") for r in result: meterData = r[0] meterTime = r[1] logger.debug('Meter data record from time %s is %s bytes long of class %s.' % ( meterTime, len(meterData), meterData.__class__)) sp.write(meterData) logger.debug('Wrote meter data to serialPort.') Messages.ResponseMsg = sp.getResponse() logger.debug('Read %s bytes from serialPort' % len(Messages.ResponseMsg)) pass logger.debug('Write "close" string to EKM meter.') sp.write("0142300375") logger.debug('Read the close string back again.') Messages.ResponseMsg = sp.getResponse(maxBytes=5) logger.debug('The received close string is: %s' % Messages.ResponseMsg.encode().hex()) ''' cur_thread_name = threading.current_thread().name logger.debug('\n\nThread: %s begins.' % cur_thread_name) while True: data = self.request.recv(1024) logger.debug('%s: Handling received message: %s' % (cur_thread_name, data)) if len(data) == 0: logger.debug('Got empty message: close connection.') time.sleep(1) break response = Messages.ResponseNak #### default response to unknown or malformed messages is NAK if data[Messages. RequestMsg_fixedBegin] == Messages.RequestCmdHeader: # handle request messages logger.debug('Handling request message.') if (len(data) == len(Messages.RequestMsgV3)) and ( data[-3:] == Messages.RequestCmdEnding): logger.debug('Handling V3 request message.') response = GenerateV3Data( data[Messages.RequestMsgV3Def_meterId]) elif (len(data) == len(Messages.RequestMsgV4)) and ( data[-3:] == Messages.RequestCmdEnding): if data[Messages. RequestMsgV4Def_reqType] == Messages.RequestMsgV4ReqTypeA: logger.debug('Handling V4A request message.') response = GenerateV4AData( data[Messages.RequestMsgV4Def_meterId]) elif data[ Messages. RequestMsgV4Def_reqType] == Messages.RequestMsgV4ReqTypeB: logger.debug('Handling V4B request message.') response = GenerateV4BData( data[Messages.RequestMsgV4Def_meterId]) else: # Unknown data kind logger.critical('Got unknown V4 request message.') pass # send default ResponseNak else: # Ill formed request message logger.critical('Got unknown request message.') pass # send default ResponseNak elif data == Messages.CloseMsg: # CloseMsg doesn't have a valid CRC (looks like last byte is only part of a CRC) # received termination code logger.debug('Got Close message.') # If FakeEKM was a state machine, we would set the state back to beginning. continue # Don't respond; DON'T close connection elif data[Messages.CrcField] != a2b_hex( calc_crc16(data[Messages.CrcCalc]) ): # Crc must be correct for all other messages logger.warning('Got message with incorrect CRC.') logger.info('Message CRC: %s, calc CRC is: %s' % (data[Messages.CrcField], a2b_hex(calc_crc16(data[Messages.CrcCalc])))) pass # send default ResponseNak elif data[Messages. SendPasswordMsg_preamble] == Messages.SendPasswordMsg[ Messages.SendPasswordMsg_preamble]: logger.debug('Got Password message.') response = Messages.ResponseAck # Any password is ok elif data[Messages. SetCmdHeader_discriminator] == Messages.SetCmdHeader: logger.debug('Got Set command.') response = Messages.ResponseAck # swallow all set commands without doing anything elif data[Messages. ReadCmdHeader_discriminator] == Messages.ReadCmdHeader: logger.debug('Got Read request.') response = GenerateRandomDataTable( data[Messages.ReadTableMsg_tableId]) else: logger.warning('Got unrecognized message.') pass logger.debug('Sending response: %s' % response) self.request.sendall(response)