Good afternoon!
There is an original configurator of metering devices MIR. The program can only work with one metering device at a time. The task arose to implement batch processing. The developers recommended your project because their configurator is based on it. Since python is closer to me, I decided to look into this branch. To communicate with the counter, the program sends a 12-byte snmr command:
7ea00a00025853c99357e67e
port 10000, password 00000000, administrator access level, address structure 4 bytes, information field length 128, device address 5673.
When running python client example with parameters:
python3 main.py -h 192.168.185.135 -p 10000 -c 16 -s 1 -r sn -a Low -P 00000000 -t Verbose
the script sends another command of 9 bytes:
7E A0 07 03 21 93 0F 01 7E
I'm new to this and as far as I understand, I probably didn't specify the physical address of the device, or I specified it incorrectly. In the description of the client parameters, I did not find information about what the command should look like.
Further. After initializing the connection, you need to send the command itself directly. It is necessary to sew up the active direct instantaneous power, prohibit the possibility of switching on from the buttons and allow auto-switching after exceeding the threshold.
The configurator , when sent to the counter with the address 1263 and a capacity of 15,000 , sends the following command:
7ea01c000212dfc9f4bc7fe6e600c0018100010000600100ff02008c6d7e
What should the python command look like in this case and what application should I use for this?
Additional questions - tell me, where can I read the description of the fields and the structure of the commands (byte by byte and with decryption - which byte is responsible for what, what value is written in it and how is it obtained)?
If I write the script myself, what functions and in what order do I need to use?
Hi, Try with parameters:…
Hi,
Try with parameters:
python3 main.py -h 192.168.185.135 -p 10000 -c 100 -s 22057 -a Low -P 00000000 -t Verbose
Reading your data
data = GXDLMSData("0.0.96.1.0.255")
self.read(data, 2)
DLMS is really complicated protocol and it can't be explained like that. You need to get the standards and study from there.
Check the client example. I believe it will help you to get started.
BR,
Mikko
Hello! Sent a request and…
Hello!
Sent a request and received a lot of data! Lots of data! But I needed, as far as I understand, just to send a snrm request, get a response to it and then send a command to flash the power. Can I add it as an option for mine like
-g \"0.0.96.1.0.255:1\"?
But this, again, is a read command, not a write command! what would a 10,000 watt write command look like?
I tried to write a script. here is his code:
import os
import sys
import traceback
from gurux_serial import GXSerial
from gurux_net import GXNet
from gurux_dlms.enums import ObjectType
from gurux_dlms.objects.GXDLMSObjectCollection import GXDLMSObjectCollection
from GXSettings import GXSettings
from GXDLMSReader import GXDLMSReader
from gurux_dlms.GXDLMSClient import GXDLMSClient
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, GXDLMSTranslator
from gurux_dlms import GXByteBuffer, GXDLMSTranslatorMessage, GXReplyData
from gurux_dlms.objects import GXDLMSData
from gurux_dlms.enums import RequestTypes, Security, InterfaceType
from gurux_dlms.secure.GXDLMSSecureClient import GXDLMSSecureClient
client = GXDLMSClient()
#Is used Logican Name or Short Name referencing.
client.useLogicalNameReferencing = True
#Is used HDLC or COSEM transport layers for IPv4 networks (IEC 62056-47)
client.interfaceType = InterfaceType.HDLC
client.clientAddress = 100
client.serverAddress = 22057
reply = GXReplyData()
print(reply)
#breakpoint()
#data = client.snrmRequest()
data = GXDLMSData("0.0.96.1.0.255")
client.read(data,2)
#breakpoint()
if data:
print(data)
#self.readDLMSPacket(data, reply)
GXDLMSReader.readDLMSPacket(data, reply)
#Has server accepted client.
client.parseUAResponse(reply.Data)
#Generate AARQ request.
#Split requests to multiple packets if needed.
#If password is used all data might not fit to one packet.
for it in client.aarqRequest():
reply.clear()
# reply = self.readDLMSPacket(it, reply)
reply = GXDLMSReader.readDLMSPacket(it, reply)
#Parse reply.
client.parseAAREResponse(reply.Data)
When I run it I get TypeError: 'GXReplyData' object is not iterable
And to be honest, I still don't understand how you got the values of client 100 and server 22057? Please write in more detail! Thanks!
Hi, Add -o output.xml…
Hi,
Add -o output.xml argument and association view is saved for the file. After that, communication is faster when the association view is not needed to read for this meter.
SNRM requests only describe the size of the HDLC payload. You need to connect to the meter before you can do anything.
DLMS is a complicated protocol and it's not possible to explain shorty.
Check the AARQ handling from the source code and don't modify it.
BR,
Mikko
So where did the values 100…
So where did the values 100 and 22057 come from? Help me to understand?!
Yes, I already understood that it is difficult! That is why I turned to you. :)
How exactly does the connection to the counter look like (without reading a huge amount of data, if possible)? Which command is responsible for the connection? Can you describe the call sequence?
Hi, The meter manufacturer…
Hi,
The meter manufacturer has decided what client and server address they want to use.
I hope this will help you get an idea of how to establish the connection for the DLMS meters.
https://www.gurux.fi/Gurux.DLMS.Client
BR,
Mikko
Suppose that I need to…
Suppose that I need to contact another device with the address 4724. The rest of the data is the same. What will the query string look like? What should I substitute as client and server addresses? Where can I get them, how and on the basis of what to calculate? Based on address 4724 or something else?
The program prompts:
7ea00a00024883c993f9aa7e
I understand here 7e is a flag. Further a00a is the format. further 0 segmentation. And then the frame should go. What do we have in it? Addresses? But no matter how I tried to decipher them, I can’t do anything:
Is 0024 an address? and 8 is lsb? Does not work! I understand lsb should be 0 for upper and 1 for lower . But my address is 4 digits!
Hi, You can get the device…
Hi,
You can get the device address from the serial number using getServerAddressFromSerialNumber-method.
Try this is your device serial number is 4724:
python3 main.py -h 192.168.185.135 -p 10000 -c 100 -n 4724 -a Low -P 00000000 -t Verbose
BR,
Mikko
Good afternoon The -n option…
Good afternoon
The -n option works, but not exactly like that. The getServerAddressFromSerialNumber function gives me the number, but it is different. For example, for the physical address in question, 5673, we get the address 23057 at the output, but you specify 22057. That is, it turns out that you need to take the 2nd digit and subtract 1 from it?
Further. Previously, when specifying the -o output.xml option in the section with code 0.0.96.1.0.255, I received the physical address of the device in decimal format. And yes, it coincided with the right one! But recently I reinstalled the operating system and now in the output.xml file I get the value in hexadecimal format! Perhaps you know. why did the format change and how do I get the decimal display back?
Without specifying the -g option, the xml file is filled, as I understand it, with all possible values that the program can read. With the option and value 0.0.96.1.0.255 specified without the output to file specified at the beginning I get a lot of rx
and tx messages and at the end the following output to the console:
Index: 1 Value: 0.0.96.1.0.255
DisconnectRequest
that is, the name of the quantity is displayed, but the value itself is not displayed. When I specify the option and path to the output file, I generally get an error:
Failed to load object 1.0.1.6.2.255 Ch. 0 Sum Li Active power+ (QI+QIV) Max. 1 Rate 2 (0 is total) unconverted data remains: Z
Failed to load object 1.0.1.6.3.255 Ch. 0 Sum Li Active power+ (QI+QIV) Max. 1 Rate 3 (0 is total) unconverted data remains: Z
Failed to load object 1.0.1.6.4.255 Ch. 0 Sum Li Active power+ (QI+QIV) Max. 1 Rate 4 (0 is total) unconverted data remains: Z
Failed to load object 1.0.2.6.2.255 Ch. 0 Sum Li Active power- (QII+QIII) Max. 1 Rate 2 (0 is total) unconverted data remains: Z
Failed to load object 1.0.2.6.3.255 Ch. 0 Sum Li Active power- (QII+QIII) Max. 1 Rate 3 (0 is total) unconverted data remains: Z
Failed to load object 1.0.2.6.4.255 Ch. 0 Sum Li Active power- (QII+QIII) Max. 1 Rate 4 (0 is total) unconverted data remains: Z
TX: 10:48:38 7E A0 1C 00 02 58 53 C9 32 D0 BF E6 E6 00 C0 01 C1 00 01 00 00 60 01 00 FF 01 00 E1 8A 7E
RX: 10:48:38 7E A0 1B C9 00 02 58 53 52 75 EB E6 E7 00 C4 01 81 00 09 06 00 00 60 01 00 FF 7E 96 7E
Index: 1 Value: 0.0.96.1.0.255
Can't change structure types.
DisconnectRequest
The actual questions are how to reduce the number of initial messages rx tx, that is, remove them from the exchange. and how can I calculate exactly the data I need?
Well, naturally, the most important question remains valid - how can I write the required values into the device?
For example, I need to program active direct instantaneous power. Which OBIS code should I choose? There are many of them. 1.7.0? That is, in our case it will be 0.1.7.0.255? Is this done via Gurux.DLMS.XMLClient.Python? Messages/LN? What and how to add there? GetRequest? ActionRequest? Can you give an example of an xlm file for my specific case?
Or can this be implemented via the command line and client.example?
ok, I think I understand…
ok, I think I understand what happened with the value 0.0.96.1.0.255 - it's not a hexadecimal format. this is the device number, to each digit of which 3 was added to the left(or 30 was added to each digit of the number) and the values were separated by spaces. but why was this done?!
If you look at the rest of the values in the file, they really look like hexadecimal ones. but I'm already starting to doubt it! In what format is this data and how to convert it?!
Hi, You must establish the…
Hi,
You must establish the connection before you can read anything from the meter,
so you need all those RX and TX messages.
You can write uvalues in the same way you have read them. Like this:
clock = GXDLMSClock()
self.read(clock, 2)
#Set new time,
self.write(clock, 2)
The meter returns the manufacturer number as a byte array. It's shown as a hex string.
Most of the values are shown in the format that the meter returns them.
BR,
Mikko