def initializeConnection(self): print("Standard: " + str(self.client.standard)) if self.client.ciphering.security != Security.NONE: print("Security: " + str(self.client.ciphering.security)) print("System title: " + GXCommon.toHex(self.client.ciphering.systemTitle)) print("Authentication key: " + GXCommon.toHex(self.client.ciphering.authenticationKey)) print("Block cipher key: " + GXCommon.toHex(self.client.ciphering.blockCipherKey)) if self.client.ciphering.dedicatedKey: print("Dedicated key: " + GXCommon.toHex(self.client.ciphering.dedicatedKey)) self.updateFrameCounter() self.initializeOpticalHead() reply = GXReplyData() data = self.client.snrmRequest() if data: self.readDLMSPacket(data, reply) self.client.parseUAResponse(reply.data) size = self.client.limits.maxInfoTX + 40 self.replyBuff = bytearray(size) reply.clear() self.readDataBlock(self.client.aarqRequest(), reply) self.client.parseAareResponse(reply.data) reply.clear() if self.client.authentication > Authentication.LOW: try: for it in self.client.getApplicationAssociationRequest(): self.readDLMSPacket(it, reply) self.client.parseApplicationAssociationResponse(reply.data) except GXDLMSException as ex: #Invalid password. raise GXDLMSException(AssociationResult.PERMANENT_REJECTED, SourceDiagnostic.AUTHENTICATION_FAILURE)
def readDLMSPacket2(self, data, reply): if not data: return notify = GXReplyData() reply.error = 0 eop = 0x7E #In network connection terminator is not used. if self.client.interfaceType == InterfaceType.WRAPPER and isinstance( self.media, GXNet): eop = None p = ReceiveParameters() p.eop = eop p.waitTime = self.waitTime if eop is None: p.Count = 8 else: p.Count = 5 self.media.eop = eop rd = GXByteBuffer() with self.media.getSynchronous(): if not reply.isStreaming(): self.writeTrace( "TX: " + self.now() + "\t" + GXByteBuffer.hex(data), TraceLevel.VERBOSE) print("TX: " + self.now() + "\t" + GXByteBuffer.hex(data)) self.media.send(data) pos = 0 try: while not self.client.getData(rd, reply, notify): if notify.data.size != 0: if not notify.isMoreData(): t = GXDLMSTranslator() xml = t.dataToXml(notify.data) print(xml) notify.clear() continue elif not p.eop: p.count = self.client.getFrameSize(rd) while not self.media.receive(p): pos += 1 if pos == 3: raise TimeoutException( "Failed to receive reply from the device in given time." ) if rd.size == 0: print("Data send failed. Try to resend " + str(pos) + "/3") self.media.send(data, None) rd.set(p.reply) p.reply = None except Exception as e: self.writeTrace("RX: " + self.now() + "\t" + str(rd), TraceLevel.ERROR) print("RX: " + self.now() + "\t" + str(rd)) raise e self.writeTrace("RX: " + self.now() + "\t" + str(rd), TraceLevel.VERBOSE) print("RX: " + self.now() + "\t" + str(rd)) if reply.error != 0: raise GXDLMSException(reply.error)
def updateFrameCounter(self): if self.invocationCounter and self.client.ciphering is not None and self.client.ciphering.security != Security.NONE: self.initializeOpticalHead() self.client.proposedConformance |= Conformance.GENERAL_PROTECTION add = self.client.clientAddress auth = self.client.authentication security = self.client.ciphering.security challenge = self.client.ctoSChallenge try: self.client.clientAddress = 16 self.client.authentication = Authentication.NONE self.client.ciphering.security = Security.NONE reply = GXReplyData() data = self.client.snrmRequest() if data: self.readDLMSPacket(data, reply) self.client.parseUAResponse(reply.data) size = self.client.limits.maxInfoTX + 40 self.replyBuff = bytearray(size) reply.clear() self.readDataBlock(self.client.aarqRequest(), reply) self.client.parseAareResponse(reply.data) reply.clear() d = GXDLMSData(self.invocationCounter) self.read(d, 2) self.client.ciphering.invocationCounter = 1 + d.value print("Invocation counter: " + str(self.client.ciphering.invocationCounter)) self.disconnect() #except Exception as ex: finally: self.client.clientAddress = add self.client.authentication = auth self.client.ciphering.security = security self.client.ctoSChallenge = challenge
def initializeConnection(self): print("Standard: " + str(self.client.standard)) if self.client.ciphering.security != Security.NONE: print("Security: " + str(self.client.ciphering.security)) print("System title: " + GXCommon.toHex(self.client.ciphering.systemTitle)) print("Authentication key: " + GXCommon.toHex(self.client.ciphering.authenticationKey)) print("Block cipher key: " + GXCommon.toHex(self.client.ciphering.blockCipherKey)) if self.client.ciphering.dedicatedKey: print("Dedicated key: " + GXCommon.toHex(self.client.ciphering.dedicatedKey)) self.updateFrameCounter() self.initializeOpticalHead() reply = GXReplyData() data = self.client.snrmRequest() if data: self.readDLMSPacket(data, reply) self.client.parseUAResponse(reply.data) size = self.client.limits.maxInfoTX + 40 self.replyBuff = bytearray(size) reply.clear() self.readDataBlock(self.client.aarqRequest(), reply) self.client.parseAareResponse(reply.data) reply.clear() if self.client.authentication > Authentication.LOW: for it in self.client.getApplicationAssociationRequest(): self.readDLMSPacket(it, reply) self.client.parseApplicationAssociationResponse(reply.data)
def readDLMSPacket(self, data, reply=None): if not reply: reply = GXReplyData() if isinstance(data, bytearray): self.readDLMSPacket2(data, reply) elif data: for it in data: reply.clear() self.readDLMSPacket2(it, reply)
def readList(self, list_): if list_: data = self.client.readList(list_) reply = GXReplyData() values = list() for it in data: self.readDataBlock(it, reply) values.extend(reply.value) reply.clear() if len(values) != len(list_): raise ValueError("Invalid reply. Read items count do not match.") self.client.updateValues(list_, values)
def close(self): if self.media and self.media._closed: print("DisconnectRequest") reply = GXReplyData() try: self.readDataBlock(self.client.releaseRequest(), reply) except Exception as e: pass # All meters don't support release. reply.clear() self.readDLMSPacket(self.client.disconnectRequest(), reply) self.media.close()
def initializeConnection(self): reply = GXReplyData() data = self.client.snrmRequest() if data: self.readDLMSPacket(data, reply) self.client.parseUAResponse(reply.data) size = self.client.limits.maxInfoTX + 40 self.replyBuff = bytearray(size) reply.clear() self.readDataBlock(self.client.aarqRequest(), reply) self.client.parseAareResponse(reply.data) reply.clear() if self.client.authentication.value > Authentication.LOW.value: for it in self.client.getApplicationAssociationRequest(): self.readDLMSPacket(it, reply) self.client.parseApplicationAssociationResponse(reply.data)
def close(self): #pylint: disable=broad-except if self.media and self.media.isOpen(): print("DisconnectRequest") reply = GXReplyData() try: #Release is call only for secured connections. #All meters are not supporting Release and it's causing #problems. if self.client.interfaceType == InterfaceType.WRAPPER or self.client.ciphering.security != Security.NONE: self.readDataBlock(self.client.releaseRequest(), reply) except Exception: pass # All meters don't support release. reply.clear() self.readDLMSPacket(self.client.disconnectRequest(), reply) self.media.close()
def readDLMSPacket2(self, data, reply): if data == None or len(data) == 0: return notify = GXReplyData() reply.error = 0 succeeded = False rd = GXByteBuffer() if not reply.isStreaming(): self.writeTrace( "TX: " + self.now() + "\t" + GXByteBuffer.hex(data), TraceLevel.VERBOSE) self.media.sendall(data) msgPos = 0 count = 100 pos = 0 try: while not self.client.getData(rd, reply, notify): if notify.data.size != 0: if not notify.isMoreData(): t = GXDLMSTranslator() xml = t.dataToXml(notify.data) print(xml) notify.clear() msgPos = rd.position continue rd.position = msgPos rd.set(self.media.recv(100)) if pos == 3: raise ValueError( "Failed to receive reply from the device in given time.") if pos != 0: print("Data send failed. Try to resend " + str(pos) + "/3") ++pos except Exception as e: self.writeTrace("RX: " + self.now() + "\t" + rd.__str__(), TraceLevel.ERROR) raise e self.writeTrace("RX: " + self.now() + "\t" + rd.__str__(), TraceLevel.VERBOSE) if reply.error != 0: raise GXDLMSException(reply.error)
class MediaListener(IGXMediaListener): def __init__(self) -> None: super().__init__() self.notify = GXReplyData() self.client = GXDLMSSecureClient() self.client.interfaceType = InterfaceType.PDU self.client.ciphering.security = Security.ENCRYPTION self.client.ciphering.blockCipherKey = GXCommon.hexToBytes(key_hex) self.translator = GXDLMSTranslator() self.reply = GXByteBuffer() def onError(self, sender, ex): """ Represents the method that will handle the error event of a Gurux component. sender : The source of the event. ex : An Exception object that contains the event data. """ print("Error has occured. " + str(ex)) def onMediaStateChange(self, sender, e): """Media component sends notification, when its state changes. sender : The source of the event. e : Event arguments. """ print("Media state changed. " + str(e)) def onTrace(self, sender, e): """Called when the Media is sending or receiving data. sender : The source of the event. e : Event arguments. """ print("trace:" + str(e)) def onPropertyChanged(self, sender, e): """ Event is raised when a property is changed on a component. sender : The source of the event. e : Event arguments. """ print("Property {!r} has hanged.".format(str(e))) def onReceived(self, sender, e: ReceiveEventArgs): self.reply.set(e.data) data = GXReplyData() try: if not self.client.getData(self.reply, data, self.notify): self.reply.clear() #If all data is received. if self.notify.complete: if not self.notify.isMoreData(): #Show received data as XML. xml = self.translator.dataToXml(self.notify.data) print(xml) #Print received data. self.printData(self.notify.value, 0) #Example is sending list of push messages in first parameter. if isinstance(self.notify.value, list): objects = self.client.parsePushObjects( self.notify.value[0]) #Remove first item because it's not needed anymore. objects.pop(0) Valueindex = 1 for obj, index in objects: self.client.updateValue( obj, index, self.notify.value[Valueindex]) Valueindex += 1 #Print value print( str(obj.objectType) + " " + obj.logicalName + " " + str(index) + ": " + str(obj.getValues()[index - 1])) self.notify.clear() self.reply.clear() except Exception as ex: print(ex) self.notify.clear() self.reply.clear() @classmethod def printData(cls, value, offset): sb = ' ' * 2 * offset if isinstance(value, list): print(sb + "{") offset = offset + 1 #Print received data. for it in value: cls.printData(it, offset) print(sb + "}") offset = offset - 1 elif isinstance(value, bytearray): #Print value. print(sb + GXCommon.toHex(value)) else: #Print value. print(sb + str(value))
def initializeConnection(self): self.media.open() if self.iec and isinstance(self.media, GXSerial): p = ReceiveParameters() p.allData = False p.eop = '\n' p.waitTime = self.waitTime with self.media.getSynchronous(): data = "/?!\r\n" self.writeTrace("TX: " + self.now() + "\t" + data, TraceLevel.VERBOSE) self.media.send(data) if not self.media.receive(p): raise Exception("Failed to received reply from the media.") self.writeTrace("RX: " + self.now() + "\t" + str(p.reply), TraceLevel.VERBOSE) #If echo is used. replyStr = str(p.reply) if data == replyStr: p.reply = None if not self.media.receive(p): raise Exception( "Failed to received reply from the media.") self.writeTrace("RX: " + self.now() + "\t" + str(p.reply), TraceLevel.VERBOSE) replyStr = str(p.reply) if not replyStr or replyStr[0] != '/': raise Exception("Invalid responce : " + replyStr) baudrate = replyStr[4] if baudrate == '0': bitrate = 300 elif baudrate == '1': bitrate = 600 elif baudrate == '2': bitrate = 1200 elif baudrate == '3': bitrate = 2400 elif baudrate == '4': bitrate = 4800 elif baudrate == '5': bitrate = 9600 elif baudrate == '6': bitrate = 230400 else: raise Exception("Unknown baud rate.") print("Bitrate is : " + bitrate) #Send ACK #Send Protocol control character controlCharacter = '2'.encode() #"2" HDLC protocol procedure (Mode E) #Mode control character #"2" //(HDLC protocol procedure) (Binary mode) modeControlCharacter = '2'.encode() #Set mode E. tmp = bytearray([ 0x06, controlCharacter, baudrate, modeControlCharacter, 13, 10 ]) p.reply = None with self.media.getSynchronous(): self.media.send(tmp) self.writeTrace( "TX: " + self.now() + "\t" + GXCommon.toHex(tmp), TraceLevel.VERBOSE) p.waitTime = 200 if self.media.receive(p): self.writeTrace("RX: " + self.now() + "\t" + str(p.reply), TraceLevel.VERBOSE) self.media.close() self.media.dataBits = 8 self.media.parity = Parity.NONE self.media.stopBits = StopBits.ONE self.media.baudRate = bitrate self.media.open() #This sleep make sure that all meters can be read. time.sleep(1000) reply = GXReplyData() data = self.client.snrmRequest() if data: self.readDLMSPacket(data, reply) self.client.parseUAResponse(reply.data) size = self.client.limits.maxInfoTX + 40 self.replyBuff = bytearray(size) reply.clear() self.readDataBlock(self.client.aarqRequest(), reply) self.client.parseAareResponse(reply.data) reply.clear() if self.client.authentication > Authentication.LOW: for it in self.client.getApplicationAssociationRequest(): self.readDLMSPacket(it, reply) self.client.parseApplicationAssociationResponse(reply.data)
def send_keep_alive(self): reply = GXReplyData() data = self.settings.client.keepAlive() if data: self.reader.readDLMSPacket(data, reply) reply.clear()