By the looks of it, the reader service does not use the GXDLMSClient.GetServerAddress by Serial Number.
I added the following code in the ReaderService.cs, after the check if the LogicalAddress is not equal to 0 and the InterfaceType is either HDLC or HdlcWithModeE:
//PhysicalAddress could be Serialnumber.
if(dev.PhysicalAddress > 0x4000)
{
_logger.LogDebug("Reader Service: GetServerAddress using Serial Number");
deviceAddress = GXDLMSClient.GetServerAddress(dev.PhysicalAddress);
}else
{
_logger.LogDebug("Reader Service: GetServerAddress using Physical Address and Physical Address");
deviceAddress = GXDLMSClient.GetServerAddress(dev.LogicalAddress, dev.PhysicalAddress);
I believe that you are right about this. We don't use the serial number when we are reading the meters. I'll add this to the worklist. Your approach needs a little bit of modification and it can't be used exactly like this.
All meter manufacturers are not using the same formula to count meter address for the serial number.
Also, all the meter manufacturers are not supporting serial number addressing.
For this reason, the serial number is not the default.
I believe that this is changed for the next release for the Gurux.DLMS.AMI.
Not sure if I should create a new thread for this, but please let me know if I should.
We have e L&G test meter with 3 Profiles, where one profile is 0.0.98.1.126 Ch 0 Data of billing periods.
When reading this, duplicate values are logged in the database.
This happens when it proceses index 2, after getting the last read time and performs the check if the object is sorted by datetime. By the looks of it, the meter we're using should have data sorted by datetime, but it looks like some billing periods are not sorted and therefor breaks the logic if the data has been read or not. Do you see any good possible solution work around for this, other than retrieving already stored values for the read period from the API for comparison before posting the newly read values?
Below are the structure objects where the first structure has a Uint16 with the value 8 (which should indicate that its sorted by datetime).
Sorry the data I posted was directly read from the meter using direct connection from DLMSDirectory (not using the AMI). Just wanted to provide you the readings.
When reading the values from the buffer (ProfileGeneric Index 2) there's a check "IsSortedByDateTime(task.Object) which gets the attributeIndex 3 from the GXObject and checks if the interface type is clock (8) which it is on this meter.
Then when the Reader creates rows for each row it checks if the current row datetime is "read" or not, it becomes a problem when there are entries not sorted and the last read is stored in the database for next read.
Please see the GxValues in the file here, check the ID (order they're processed) and DateTimestamps. Tabseparated text file: https://file.io/vMoR79ckVqAc
By the looks of it, the
By the looks of it, the reader service does not use the GXDLMSClient.GetServerAddress by Serial Number.
I added the following code in the ReaderService.cs, after the check if the LogicalAddress is not equal to 0 and the InterfaceType is either HDLC or HdlcWithModeE:
//PhysicalAddress could be Serialnumber.
if(dev.PhysicalAddress > 0x4000)
{
_logger.LogDebug("Reader Service: GetServerAddress using Serial Number");
deviceAddress = GXDLMSClient.GetServerAddress(dev.PhysicalAddress);
}else
{
_logger.LogDebug("Reader Service: GetServerAddress using Physical Address and Physical Address");
deviceAddress = GXDLMSClient.GetServerAddress(dev.LogicalAddress, dev.PhysicalAddress);
}
Hi,
Hi,
I believe that you are right about this. We don't use the serial number when we are reading the meters. I'll add this to the worklist. Your approach needs a little bit of modification and it can't be used exactly like this.
BR,
Mikko
Hi again
Hi again
I am wondering why you would not use the serial number. It seems like a good way to make sure you connect to the right meter.
Will the change be included at some point?
Henrik
Hi,
Hi,
All meter manufacturers are not using the same formula to count meter address for the serial number.
Also, all the meter manufacturers are not supporting serial number addressing.
For this reason, the serial number is not the default.
I believe that this is changed for the next release for the Gurux.DLMS.AMI.
BR,
Mikko
Hi,
Hi,
Get the latest version from Gurux.DLMS.AMI. It can now handle the serial number formula.
BR,
Mikko
Hi Mikko,
Hi Mikko,
Not sure if I should create a new thread for this, but please let me know if I should.
We have e L&G test meter with 3 Profiles, where one profile is 0.0.98.1.126 Ch 0 Data of billing periods.
When reading this, duplicate values are logged in the database.
This happens when it proceses index 2, after getting the last read time and performs the check if the object is sorted by datetime. By the looks of it, the meter we're using should have data sorted by datetime, but it looks like some billing periods are not sorted and therefor breaks the logic if the data has been read or not. Do you see any good possible solution work around for this, other than retrieving already stored values for the read period from the API for comparison before posting the newly read values?
Below are the structure objects where the first structure has a Uint16 with the value 8 (which should indicate that its sorted by datetime).
Here's the data read from the profile using direct connection: https://file.io/xTyBNWurPoMR
<Array> <Structure> <UInt16 Value="8" /> <OctetString Value="00 00 01 00 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 00 00 01 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 01 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 02 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 03 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 04 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 09 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 0A 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 10 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 15 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 29 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 3D 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 16 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 2A 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 3E 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 01 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 01 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 02 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 02 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 03 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 03 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 04 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 04 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 15 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 15 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 29 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 29 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 3D 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 3D 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 09 06 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 09 06 00 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 04 01 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 04 02 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 04 03 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 04 04 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 04 09 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 04 0A 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="00 00 60 08 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="3" /> <OctetString Value="01 01 0D 00 00 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 0D 03 01 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 0D 03 01 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 0D 03 02 FF" /> <Int8 Value="2" /> <UInt16 Value="0" /> </Structure> <Structure> <UInt16 Value="4" /> <OctetString Value="01 01 0D 03 02 FF" /> <Int8 Value="5" /> <UInt16 Value="0" /> </Structure> </Array>
Hi,
Hi,
From the data It seems that you are reading attribute #3 that is capture objects and not the attribute #3 that is buffer (Data is on the buffer).
Capture objects (columns of the buffer) are plan to read only once and you can remove them from the read.
BR,
Mikko
Hi,
Hi,
Sorry the data I posted was directly read from the meter using direct connection from DLMSDirectory (not using the AMI). Just wanted to provide you the readings.
When reading the values from the buffer (ProfileGeneric Index 2) there's a check "IsSortedByDateTime(task.Object) which gets the attributeIndex 3 from the GXObject and checks if the interface type is clock (8) which it is on this meter.
Then when the Reader creates rows for each row it checks if the current row datetime is "read" or not, it becomes a problem when there are entries not sorted and the last read is stored in the database for next read.
Please see the GxValues in the file here, check the ID (order they're processed) and DateTimestamps. Tabseparated text file: https://file.io/vMoR79ckVqAc
Kind regards,
Mikael