Before commenting read Forum rules
Don't comment the topic if you have a new question.
You can create a new topic selecting correct category from Gurux Forum and then create a new topic selecting "New Topic" from the top left.
Before commenting read Forum rules
Don't comment the topic if you have a new question.
You can create a new topic selecting correct category from Gurux Forum and then create a new topic selecting "New Topic" from the top left.
Hi there dear GuruX community,
I wrote a script with the python library to loop through meters which are connected via an RS485 bus to multiple electricity meters from Ensor. I was able to use the example script to read out the meter, so I went on and did some adaption to read through a bunch of meters with a loop.
First I initialize the client and the serial connection:
#Initialize Client
secClient = GXDLMSSecureClient(True)
secClient.useLogicalNameReferencing = True
secClient.password = 12345678
secClient.authentication = Authentication.LOW
secClient.ciphering.security = Security.NONE
secClient.standard = Standard.DLMS
secClient.ciphering.security = Security.NONE
secClient.clientAddress = int(1)
# secClient.ctoSChallenge = challenge
if os.path.exists(outputFile):
c = GXDLMSObjectCollection.load(outputFile)
secClient.objects.extend(c)
#Initialize Serial connection
media=GXSerial(None)
media.port = device_add
media.baudrate = BaudRate.BAUD_RATE_9600
media.bytesize = 8
media.parity = Parity.NONE
media.stopbits = StopBits.ONE
trace=TraceLevel.OFF
invocationCounter=None
iec=False
Then I have a loop which checks looks the serial number of the meter up in a json:
for Group in jsonConfig.EnsorGroup:
for meter in Group.Serial:
ser=meter.split("!")
secClient.serverAddress = GXDLMSClient.getServerAddress(int(ser[2]))
reader = GXDLMSReader(secClient, media, trace, invocationCounter, iec)
reader.initializeConnection()
That's the point where it fails and I get the following error message:
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/BlockBox.Microservice.EnsorRS485.py", line 211, in <module>
reader.initializeConnection()
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/GXDLMSReader.py", line 305, in initializeConnection
self.readDLMSPacket(data, reply)
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/GXDLMSReader.py", line 117, in readDLMSPacket
self.readDLMSPacket2(data, reply)
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/GXDLMSReader.py", line 144, in readDLMSPacket2
self.media.send(data)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_serial/GXSerial.py", line 170, in send
self.__h.write(data)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_serial/_handlers/GXLinuxHandler.py", line 407, in write
ret = os.write(self.h, data)
TypeError: an integer is required (got type NoneType)
it seems to me that GXDMLSReader during the execution of reader.initializeConnection() some data is lost, i dont know how?!
I had some progress since my initial post.
I forgot to put
-->media.open()
to start the serial connection
now i get the following error message:
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/BlockBox.Microservice.EnsorRS485.py", line 213, in <module>
reader.initializeConnection()
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/GXDLMSReader.py", line 310, in initializeConnection
self.readDataBlock(self.client.aarqRequest(), reply)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_dlms/GXDLMSClient.py", line 516, in aarqRequest
_GXAPDU.generateAarq(self.settings, self.settings.cipher, None, buff)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_dlms/_GXAPDU.py", line 287, in generateAarq
cls.getAuthenticationString(settings, data, encryptedData)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_dlms/_GXAPDU.py", line 93, in getAuthenticationString
len_ = len(callingAuthenticationValue)
TypeError: object of type 'int' has no len()
Had some additional progress in the meantime. My password was handed over as int instead of string. so I changed that, now it gets stuck with the following message:
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/BlockBox.Microservice.EnsorRS485.py", line 213, in <module>
reader.initializeConnection()
File "/home/pi/Repos/BlockBox.Microservice.EnsorRS485/GXDLMSReader.py", line 311, in initializeConnection
self.client.parseAareResponse(reply.data)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_dlms/GXDLMSClient.py", line 547, in parseAareResponse
self.isAuthenticationRequired = _GXAPDU.parsePDU(self.settings, self.settings.cipher, reply, None) == SourceDiagnostic.AUTHENTICATION_REQUIRED
File "/home/pi/.local/lib/python3.7/site-packages/gurux_dlms/_GXAPDU.py", line 650, in parsePDU
ret = _GXAPDU.parsePDU2(settings, cipher, buff, xml)
File "/home/pi/.local/lib/python3.7/site-packages/gurux_dlms/_GXAPDU.py", line 816, in parsePDU2
raise GXDLMSException(resultComponent, resultDiagnosticValue)
gurux_dlms.GXDLMSException.GXDLMSException: Access Error : Device reports a hardware fault.
Which is wrong, because i can read out the meter with the example main script without any problems
Hi,
Hi,
Can you share hex string from the bytes send and received so I can check this.
BR,
Mikko
Hi Mikko,
Hi Mikko,
I get the following in verbose mode:
TX: 08:25:52 7E A0 0A 00 02 16 39 03 93 4F 1F 7E
RX: 08:25:52 7E A0 21 03 00 02 16 39 73 D6 44 81 80 12 05 01 80 06 01 80 07 04 00 00 00 01 08 04 00 00 00 01 53 3B 7E
TX: 08:25:52 7E A0 2E 00 02 16 39 03 10 29 A5 E6 E6 00 60 1D A1 09 06 07 60 85 74 05 08 01 01 BE 10 04 0E 01 00 00 00 06 5F 1F 04 00 00 1E 1D FF FF C5 E4 7E
RX: 08:25:52 7E A0 3A 03 00 02 16 39 30 02 F7 E6 E7 00 61 29 A1 09 06 07 60 85 74 05 08 01 01 A2 03 02 01 01 A3 05 A1 03 02 01 0E BE 10 04 0E 08 00 06 5F 1F 04 00 00 00 00 01 80 00 07 A4 73 7E
BR,
Oli
Hi,
Hi,
Create own GXDLMSSecureClient for each read or then update settings when you are looping the meters. Now the authentication level is none for some reason and that is causing this problem.
BR,
Mikko
Hi Mikko,
Hi Mikko,
Thank you for your help!
I also don't understand why it is none, I couldn't trace it back.
I get the same problem with the GXDLMSClient. I think the client setting is somewhere wrong.
How can I change the authentication level?
Even if I try the test without the loop, so only one single client I run into the same problem.
Best regards,
Oli
Hi Oli,
Hi Oli,
What Python version you are using? Have you imported the Authentication?
from gurux_dlms.enums import Authentication
Are you sure that you don't define Authentication anywhere else in the code?
BR,
Mikko
Hi Mikko,
Hi Mikko,
I'm using 3.7.3, I could go higher but I think that won't change much.
I import the following at the beginning of the script:
# from gurux
from gurux_net import GXNet
from gurux_dlms.enums import ObjectType
from gurux_dlms.objects.GXDLMSObjectCollection import GXDLMSObjectCollection
from GXDLMSReader import GXDLMSReader
from gurux_common.GXCommon import GXCommon
from gurux_dlms.enums.DataType import DataType
import locale
from gurux_dlms.GXDateTime import GXDateTime
from gurux_dlms.internal._GXCommon import _GXCommon
from gurux_dlms import GXDLMSException, GXDLMSExceptionResponse, GXDLMSConfirmedServiceError
from gurux_dlms import GXByteBuffer, GXReplyData, GXDLMSTranslator, GXDLMSException
from gurux_dlms.enums import InterfaceType, Authentication, Security, Standard
from gurux_dlms import GXDLMSClient
from gurux_dlms.secure import GXDLMSSecureClient
from gurux_dlms.objects import GXDLMSObject
from gurux_common.enums import TraceLevel
from gurux_common.io import Parity, StopBits, BaudRate
from gurux_net.enums import NetworkType
from gurux_net import GXNet
from gurux_serial.GXSerial import GXSerial
Which contains authentication and I define like this:
#Initialize Client
secClient = GXDLMSSecureClient(True)
secClient.useLogicalNameReferencing = True
secClient.forAuthentication = Authentication.LOW
secClient.password = str(int(12345678))
secClient.ciphering.security = Security.NONE
secClient.standard = Standard.DLMS
secClient.clientAddress = int(1)
secClient.interfaceType=InterfaceType.HDLC
What I wasnt sure about is:
secClient.forAuthentication = Authentication.LOW
in GXDLMSSecureClient the vaiable is defined as forAuthentication, see here:
def __init__(self, useLogicalNameReferencing=False, clientAddress=16, serverAddress=1, forAuthentication=Authentication.NONE, password=None, interfaceType=InterfaceType.HDLC):
GXDLMSClient.__init__(self, useLogicalNameReferencing, clientAddress, serverAddress, forAuthentication, password, interfaceType)
and in the example code GXSettings.py it is defined as self.client.authentication:
self.client.authentication = Authentication.LOW
could that be the problem?
Hi,
Hi,
self.client.authentication = Authentication.LOW is the correct. forAuthentication is constructor parameter don't use it.
BR,
Mikko
Hi Mikko,
Hi Mikko,
Still doesnt work, its so strange, same settings on my Windows PC with GXDMLSDirector works but on the raspberry pi 4 via the own python script it doesnt. Somehow GXSettings sets more parameters that it works. I dont know which one though
Thank you for your help.
BR,Oli
Hi,
Hi,
If you add this line what is output?
print(secClient.authentication)
BR,
Mikko