However I am struggling with setting up the push object list and interpret the data correctly. I have looked for examples, but basically the only thing I can find is adding the GXDLMSClock to the push object list.
If I understand it correctly, I have to describe the incoming push object by adding it to the PushObjectList?
```csharp
var push = new GXDLMSPushSetup();
push.PushObjectList.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSClock(), new GXDLMSCaptureObject(2,0)));
```
The message I am receiving is fairly simple:
- DeviceId
- Load Profile (array with multiple readings per 5 minutes)
Load profile contains per item:
- Clock
- Profile status
- Active Energy Import
- Active Energy Export
- Reactive Energy Import
- Reactive Energy Export
Could you provide me with an example how I should describe this in the PushObjectList?
DLMS doesn't define the content of the push message. This causes that every meter can be configured differently. This is something that is good to keep in mind.
You need to add object something like this:
var pg = new GXDLMSProfileGeneric();
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSClock(), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSData("LOGICAL_NAME_OF_PROFILE_STATUS"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
var push = new GXDLMSPushSetup();
push.PushObjectList.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSData("LOGICAL_NAME_OF_THE_DATA_OBJECT"), new GXDLMSCaptureObject(2,0)));
push.PushObjectList.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new pf new GXDLMSCaptureObject(2,0)));
You can get the logical names if you read the push object with the GXDLMSDirector.
So after this I can see that the clone.PushObjectList has some values attached to it.
When I loop through them:
0 -> device id
1 -> GenericProfile
With the code from the example on github:
//Comment this if the meter describes the content of the push message for the client in the received data.
foreach (KeyValuePair<GXDLMSObject, GXDLMSCaptureObject> it in clone.PushObjectList)
{
int index = it.Value.AttributeIndex - 1;
Console.WriteLine(((IGXDLMSBase)it.Key).GetNames()[index] + ": " + it.Key.GetValues()[index]);
}
I get the following output:
Value: System.Byte[]
Buffer: System.Object[][]
Is there a way to further convert these data types? Do I have to set this up in the pushSetup? Or what is the way to do so?
Eventually I want to create an object, ideally with the obis codes, the values, the unit and timestamp and then pass it along to another system to further process it.
Attached a screenshot while debugging and checking the content of the clone.PushObjectList. Note I also used converter.UpdateOBISCodeInformation(it.Key); to update the description of the items in the pushObjectList.
Attached another screenshot of what is currently in the buffer. These are the reading values. But I would like to enrich / convert this data to the correct data types and map with with the obis codes.
Get values returns the value as it is defined on the DLMS standard. You can convert the byte array to hex and loop through object arrays and then print them. Another option is that you check the object type and then print it something like this:
foreach (KeyValuePair<GXDLMSObject, GXDLMSCaptureObject> it in clone.PushObjectList)
{
if (it.Key is GXDLMSClock clock)
{
if (it.Value.AttributeIndex == 2)
{
Console.WriteLine("Current time: " + clock.Time);
}
}
}
Yes, so for the items in the PushObjectList I can do a check what type it is. So in my case the 2nd entry is a GXDLMSProfileGeneric. Which has the buffer set, with the load profile values. But then in the buffer (other than possibly by the order it is in there) I don't have the information which register for example it is. Is there a way for retrieving that?
I noticed that after I call
clone.GetPushValues(client, (List<object>)notify.Value)
The captureObject list on the GXDLMSProfileGeneric (2nd item in the PushObjectList) is empty and the buffer now is filled.
What I was hoping to find is the following:
- In the GXDLMSPushSetup I have added a GXDLMSProfileGeneric with the capture objects described like this:
pg.CaptureObjects.Add(new GXKeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("1.0.1.8.0.255")
{
Description = "Active Energy Import (+A)",
Unit = Unit.ActiveEnergy,
Scaler = 1
}, new GXDLMSCaptureObject(2, 0)));
- Then after calling the clone.GetPushValues I was hoping to find these registers with the value now set. But I guess that is not the case? Or am I missing something?
I am quite new to DLMS, so maybe this is just the way it works.
You need to read capture objects from the profile generic to know what values are stored for the buffer.
If the meter doesn't send the capture objects as part of the push message you need to read them from the meter or add them manually.
Hi,
Hi,
DLMS doesn't define the content of the push message. This causes that every meter can be configured differently. This is something that is good to keep in mind.
You need to add object something like this:
var pg = new GXDLMSProfileGeneric();
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSClock(), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSData("LOGICAL_NAME_OF_PROFILE_STATUS"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
pg.CaptureObjects.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("LOGICAL_NAME_OF_REGISTER"), new GXDLMSCaptureObject(2,0)));
var push = new GXDLMSPushSetup();
push.PushObjectList.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSData("LOGICAL_NAME_OF_THE_DATA_OBJECT"), new GXDLMSCaptureObject(2,0)));
push.PushObjectList.Add(new KeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new pf new GXDLMSCaptureObject(2,0)));
You can get the logical names if you read the push object with the GXDLMSDirector.
BR,
Mikko
Thanks Mikko, this seems to
Thanks Mikko, this seems to bring me a step further :-).
So I have managed to get the
So I have managed to get the above bit to work. But I am still fiddling around with converting the data to the correct data types.
What happens so far that I set the pushobject list with the expected object, as mentioned above.
GXDLMSPushSetup clone = (GXDLMSPushSetup)push.Clone();
clone.GetPushValues(client, (List<object>)notify.Value);
So after this I can see that the clone.PushObjectList has some values attached to it.
When I loop through them:
0 -> device id
1 -> GenericProfile
With the code from the example on github:
//Comment this if the meter describes the content of the push message for the client in the received data.
foreach (KeyValuePair<GXDLMSObject, GXDLMSCaptureObject> it in clone.PushObjectList)
{
int index = it.Value.AttributeIndex - 1;
Console.WriteLine(((IGXDLMSBase)it.Key).GetNames()[index] + ": " + it.Key.GetValues()[index]);
}
I get the following output:
Value: System.Byte[]
Buffer: System.Object[][]
Is there a way to further convert these data types? Do I have to set this up in the pushSetup? Or what is the way to do so?
Eventually I want to create an object, ideally with the obis codes, the values, the unit and timestamp and then pass it along to another system to further process it.
Attached a screenshot while debugging and checking the content of the clone.PushObjectList. Note I also used converter.UpdateOBISCodeInformation(it.Key); to update the description of the items in the pushObjectList.
Attached another screenshot
Attached another screenshot of what is currently in the buffer. These are the reading values. But I would like to enrich / convert this data to the correct data types and map with with the obis codes.
Hi,
Hi,
Get values returns the value as it is defined on the DLMS standard. You can convert the byte array to hex and loop through object arrays and then print them. Another option is that you check the object type and then print it something like this:
foreach (KeyValuePair<GXDLMSObject, GXDLMSCaptureObject> it in clone.PushObjectList)
{
if (it.Key is GXDLMSClock clock)
{
if (it.Value.AttributeIndex == 2)
{
Console.WriteLine("Current time: " + clock.Time);
}
}
}
BR,
Mikko
Hi Mikko,
Hi Mikko,
Thanks for your reply.
Yes, so for the items in the PushObjectList I can do a check what type it is. So in my case the 2nd entry is a GXDLMSProfileGeneric. Which has the buffer set, with the load profile values. But then in the buffer (other than possibly by the order it is in there) I don't have the information which register for example it is. Is there a way for retrieving that?
I noticed that after I call
clone.GetPushValues(client, (List<object>)notify.Value)
The captureObject list on the GXDLMSProfileGeneric (2nd item in the PushObjectList) is empty and the buffer now is filled.
What I was hoping to find is the following:
- In the GXDLMSPushSetup I have added a GXDLMSProfileGeneric with the capture objects described like this:
pg.CaptureObjects.Add(new GXKeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(new GXDLMSRegister("1.0.1.8.0.255")
{
Description = "Active Energy Import (+A)",
Unit = Unit.ActiveEnergy,
Scaler = 1
}, new GXDLMSCaptureObject(2, 0)));
- Then after calling the clone.GetPushValues I was hoping to find these registers with the value now set. But I guess that is not the case? Or am I missing something?
I am quite new to DLMS, so maybe this is just the way it works.
Hi,
Hi,
You need to read capture objects from the profile generic to know what values are stored for the buffer.
If the meter doesn't send the capture objects as part of the push message you need to read them from the meter or add them manually.
BR,
Mikko