I've been stuck for months on this issue and would appreciate your help. I am trying to read meter data that has a dynamic IP address using Gurux Python, following the steps in this document: Gurux.DLMS.DynamicIP. However, there is no example for Python, so I created a server that listens on port 9090. I am receiving data from the meter in the onReceived function, but the onClientConnected function is not being triggered, and I don't know why.
Additionally, the documentation suggests using server.attached(e.getinfo) in onClientConnected, but there is no server.attached in the Python GXNet code. How can I implement this in Python? Also, why is the onClientConnected function not being triggered?
Furthermore, where should I call the readAll function, and what are the necessary steps within this function? Should I first create a client with the correct client/server interface type and password?
Please guide me on how to read and write to my meter with a dynamic IP. If you have any examples in Python, sharing them would be incredibly helpful. I am also including the code I have tried and the responses I have received in the functions for your reference.
Your guidance will be greatly appreciated.
MY server service Code
import threading
from gurux_net import GXNet
from gurux_net.enums import NetworkType
import socket
import threading
from gurux_common.MediaStateEventArgs import MediaStateEventArgs
from gurux_common.TraceEventArgs import TraceEventArgs
class ServerListener:
def onClientConnected(self, sender, e):
print(f"Client {e.info} is connected.")
def onMediaStateChange(self, sender, e):
print(f"Media state changed: {e.state}")
def onReceived(self, sender, e):
print(f"Data received from {e}: {e.data}")
# Define the server setup and listening logic
def setup_server():
server = GXNet(NetworkType.TCP, None, 9090)
server.server = True # Set to server mode
listener = ServerListener()
server.addListener(listener) # Add event listener for connections
server.open() # Open the server to start listening
print("Server is listening...")
try:
while True:
pass # Keep the main thread alive
except KeyboardInterrupt:
print("Server is shutting down.")
server.close()
# Start the server
if __name__ == "__main__":
setup_server()
____________________________________________________
the 2nd approach with i use
import threading
from gurux_net import GXNet
from gurux_net.enums import NetworkType
from gurux_common.MediaStateEventArgs import MediaStateEventArgs
from gurux_common.TraceEventArgs import TraceEventArgs
from gurux_dlms.enums import InterfaceType, Authentication, ObjectType
from gurux_dlms import GXDLMSClient, GXReplyData
from gurux_common.enums import TraceLevel
class ServerListener:
def __init__(self):
self.trace_level = TraceLevel.INFO # Set the default trace level
def onMediaStateChange(self, sender, e):
print(f"Media state changed: {e.state}")
def onReceived(self, sender, e):
print(f"Data received from {e}: {e.data}")
try:
# Create and configure the GXDLMSClient
client = GXDLMSClient(
useLogicalNameReferencing=True,
interfaceType=InterfaceType.WRAPPER,
clientAddress=17,
serverAddress=1,
forAuthentication=Authentication.LOW,
password=b'00000000'
)
print(f"Client configuration: {client}")
# Send and handle AARQ request
reply = GXReplyData()
self.send_aarq_request(client, reply)
print(f"AARQ request sent and AARE response handled successfully: {reply}")
# Retrieve and process profile generics
profileGenerics = client.objects.getObjects(ObjectType.PROFILE_GENERIC)
for pg in profileGenerics:
self.writeTrace("Profile Generic " + str(pg.name) + " Columns:", TraceLevel.INFO)
if pg.canRead(3):
self.read(pg, 3)
if self.trace_level > TraceLevel.WARNING:
sb = ""
for k, _ in pg.captureObjects:
if sb:
sb += " | "
sb += str(k.name)
sb += " "
desc = k.description
if desc:
sb += desc
self.writeTrace(sb, TraceLevel.INFO)
except Exception as ex:
self.writeTrace("Error! Failed to read columns:" + str(ex), TraceLevel.ERROR)
finally:
# Proper resource management should be ensured
print("Cleanup resources if any")
def onClientConnected(self, sender, e):
print(f"Client {e} is connected.")
def onTrace(self, sender, e):
print(f"onTrace {e}")
def onPropertyChanged(self, sender, e):
print(f"onPropertyChanged {e}")
@staticmethod
def send_aarq_request(client, reply):
"""Send AARQ request and handle AARE response."""
try:
reply.clear()
data_list = client.aarqRequest()
if isinstance(data_list, list) and len(data_list) > 0:
data = data_list[0]
print(f"AARQ Request data: {data}")
ServerListener.read_data_block(data, reply)
client.parseAareResponse(reply.data)
print(f"AARE response: {reply}")
reply.clear()
if client.authentication.value > Authentication.LOW.value:
for it in client.getApplicationAssociationRequest():
ServerListener.read_data_block(it, reply)
client.parseApplicationAssociationResponse(reply.data)
except Exception as e:
print(f"Error in AARQ/AARE process: {e}")
@staticmethod
def read_data_block(data, reply):
"""Simulate reading a data block."""
if isinstance(data, (bytearray, bytes)):
if len(data) > 0:
try:
print(f"Data to be set: {data.hex()} (length: {len(data)})")
reply.data.set(data)
print(f"Data block read: {data.hex()}")
except IndexError as e:
print(f"Index error while reading data block: {e}")
print(f"Data length: {len(data)}")
print(f"Data content: {data.hex()}")
except TypeError as e:
print(f"Type error while reading data block: {e}")
else:
print("Received empty data block.")
else:
print("Unexpected data type:", type(data))
def writeTrace(self, message, level):
if level >= self.trace_level:
print(message)
def read(self, object, attribute_index):
# Placeholder method for reading an attribute of an object
print(f"Reading attribute {attribute_index} of object {object.name}")
# Define the server setup and listening logic
def setup_server():
server = GXNet(NetworkType.TCP, None, 9090)
server.server = True # Set to server mode
listener = ServerListener()
# Adding event listener for connections
server.addListener(listener) # Fallback if __netListeners does not exist
print("Attempting to open server...")
server.open() # Open the server to start listening
print("Server is listening...")
try:
while True:
pass # Keep the main thread alive
except KeyboardInterrupt:
print("Server is shutting down.")
server.close()
# Start the server
if __name__ == "__main__":
setup_server()
_________________________________
RESPONSE
root@ip-172-31-44-127:~# python3 GXNET.py
Media state changed: MediaState.OPENING
Media state changed: MediaState.OPEN
Server is listening...
Data received from 182.191.133.110:34816:00 01 00 01 00 11 00 12 DD 10 30 30 30 30 30 30 32 38 39 38 30 30 30 30 31 38 : bytearray(b'\x00\x01\x00\x01\x00\x11\x00\x12\xdd\x100000002898000018')
Hi, onClientConnected issue…
Hi,
onClientConnected issue is fixed.
Dynamic IP address support is implemented only for Java and C#.
You need to implement socket reading by yourself if you want to use Python.
I'll ask customers if they need Python support. Let's see what they answer, but before that, you need to use Java or C#.
BR,
Mikko
Ok, thank you, so I will go…
Ok, thank you, so I will go with Java and try to start implementing it in Java. Can you please provide me with the step-by-step guide for Java, if you have one? Do you have any code demos until you read metres? or just tell me, How should I start?
So step 1:
I have to listen to port 9090 using GXnet.
step 2:
It will return to me. OnClientConnected with the response object, I have to use that sender object with GXnet to attach the server
After the second step, I am confused about what to do now to read metre data. What is this function doing? How is it ReadAll? Where is the AARQ and the client stuff? Please guide me with the next steps.
{
GXDLMSReader cl = new Net.GXDLMSReader(media);
cl.ReadAll();
Create your own thread for each metre if you are handling multiple metres simultaneously.
//new Thread(new ThreadStart(cl.ReadAll));
}
Hi, Have you read this?…
Hi,
Have you read this?
https://www.gurux.fi/Gurux.DLMS.DynamicIP
Read all establish a connection for the meter and read it. You can get the idea from here.
https://github.com/Gurux/Gurux.DLMS.Net/blob/d2fbfa25aa8dc1030e423e9162…
BR,
Mikko
yes i have read this…
yes i have read this document but i am confused where i have to create client like this ?
because in this doc https://www.gurux.fi/Gurux.DLMS.DynamicIP there is nothing related to this and there is no function in java readMeter(cl); so from where readmeter is been called ? i want to ask after the server.attach what i have to do next ?
try (GXNet cl = server.attach(e.getInfo())) {
readMeter(cl);
}
GXDLMSClient client = new GXDLMSClient();
// Is used Logican Name or Short Name referencing.
client.setUseLogicalNameReferencing(true);
// Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47)
client.setInterfaceType(InterfaceType.HDLC);
client.setClientAddress(16);
client.setServerAddress(1);
Hi, Listen OnClientConnected…
Hi,
Listen OnClientConnected. The server notifies it when the meter connects to the server.
https://github.com/Gurux/Gurux.DLMS.Net/blob/d2fbfa25aa8dc1030e423e9162…
Then you can read the meter.
BR,
Mikko
ok let me try thank you so…
ok let me try thank you so much