Skip to main content
Home
for DLMS smart meters
Open source solutions for DLMS smart metering

Main navigation

  • Home
  • Products
  • About us
  • Open Source
  • Community
  • Forum
  • Downloads
User account menu
  • Log in

Breadcrumb

  1. Home
  2. Forums
  3. FW Upgrade Using Python

FW upgrade using Python

Forum Rules

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.

By ikudryav , 4 August, 2022
Forums
Gurux.DLMS

Hi Mikko,

I am trying to upgrade meter firmware but am stuck with the block size issue.

Here is the simple code, which was in another topic:

tr = GXDLMSImageTransfer
imageBlockValue = # Read this from the file.
frames = tr.imageBlockTransfer(client, imageBlockValue, None)

So, the question is how to read imageBlockValue from the file. I check description details in Blue Book but it is still not clear how to do it in Python library.

It could be nice to have a Python example for the firmware upgrade.

Thank you,
Ilya

Profile picture for user Kurumi

Kurumi

3 years 10 months ago

Hi Ilya,

Hi Ilya,

There is no single answer for this. Some meter manufacturers are saving firmware as binary data for the file. Some are using Hex string and some are using XML.

So you need to check how data is saved for the file and then read it for the imageBlockValue.

I'll add a firmware update for the work list, but it will take some time before it's ready.
In the meantime you can check how it's done in C# from here:

https://github.com/Gurux/Gurux.DLMS.Net/blob/1643b7228552ad2c37f1320928…

BR,
Mikko

ikudryav

3 years 10 months ago

Hi Mikko,

Hi Mikko,

I understand that the format can be completely different, depending on the meter vendor. It is a relatively simple task to cope with formats. But my question is: do we need to get imageBlockValue from the image file or we can defined any size with the requirement that it should be less then PDU maximum allowed size?

Here is the table from DLMS Blue Book related to FW image::

ImageBlock 0 -> Image Block Size
ImageBlock 1 -> Image Block Size
ImageBlock 2 -> Image Block Size
ImageBlock 3 -> Image Block Size
...
ImageBlock n-1 -> Image Block Size

ImageSize = SUM(<Image Block Sizes>)

Can I use any block size (below maximum of course) or it is predefined in the FW image (when the image was build) and must be used for the transfer?

Thank you,
Ilya

Profile picture for user Kurumi

Kurumi

3 years 10 months ago

Hi Ilya,

Hi Ilya,

The maximum size must be smaller than the image block size (Attribute index #2), not PDU size. For that reason attribute index is read first.
http://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSImageTransfer

All this is handled automatically by the framework. ImageBlockTransfer method splits the firmware image to correct frames.

Just call those methods in that order and you can transfer the image for the meter.

Then you need to call verify and activate. You need usually to wait for a while before calling activate. Verification must be finished and it might take a long time with some meters.

BR,
Mikko

ikudryav

3 years 8 months ago

Hi Mikko,

Hi Mikko,

I followed code samples for C#, as you suggested. and adapted it for Python but it seems doesn't work properly.
The problem is with "imageTransferInitiate()" function. Here is a code:

CODE:
# 'reader' is properly initiated for network connections already

ImageTransfer = GXDLMSImageTransfer()
reply = GXReplyData()

# Step 1: read Image Block Size from the meter
imageBlockSize = reader.read(ImageTransfer, 2)
print({"imageBlockSize":imageBlockSize, "type":type(imageBlockSize)})

# Step 2: Initiate the Image transfer process.
fw_filename = "fw/V1.01.bin"
imageIdentifier = "V1.01";
forImageSize = int(os.path.getsize(fw_filename))
print({"forImageSize":forImageSize})
init_data = ImageTransfer.imageTransferInitiate(reader.client, imageIdentifier, forImageSize)
print({"init_data":init_data})
init_val = reader.readDataBlock(init_data, reply)
print({"init_val":init_val})

RESULT:
{'imageBlockSize': 256, 'type': <class 'gurux_dlms.GXUInt32.GXUInt32'>}
{'forImageSize': 66105}
{'init_data': [bytearray(b'\x00\x01\x00P\x00\x01\x00/\xcb-0\x00\x00\x00\x03\x16\xee\xd9@&8gPY\xda\xdd\xdcSH\xea\xb9\xca\xb1L\xb1\xce*\x97\xa0I-\xa1\xc0\x01\xc0\xb9}\xc4b\xcf\xc3\x9c\x98\xceF')]}

Access Error : Device reports a unmatched type.
Traceback (most recent call last):
File "DLMS/GXClient.py", line 841, in upgradeFirmware
init_val = reader.readDataBlock(init_data, reply)
File "DLMS/GXDLMSReader.py", line 190, in readDataBlock
self.readDataBlock(it, reply)
File "DLMS/GXDLMSReader.py", line 194, in readDataBlock
self.readDLMSPacket(data, reply)
File "DLMS/GXDLMSReader.py", line 128, in readDLMSPacket
self.readDLMSPacket2(data, reply)
File "DLMS/GXDLMSReader.py", line 183, in readDLMSPacket2
raise GXDLMSException(reply.error)
gurux_dlms.GXDLMSException.GXDLMSException: Access Error : Device reports a unmatched type.

So, what I understood, the meter doesn't accept the message because it is expecting the different type.

The "readDataBlock" command works absolutly fine for other type of commands, like disconnect/reconnect: reader.readDataBlock(obj.remoteReconnect(reader.client), reply)
or
reader.readDataBlock(obj.remoteDisconnect(reader.client), reply)

Also I read data from the meter for 0.0.44.0.0.255:

CODE:
for i in (2,3,4,5,6,7):
val = reader.read(ImageTransfer, i)
log_message = "----> Reading: Type: {}, Name: {}, LN: {}:{}, Value: {} ".format(str(ImageTransfer.objectType), ImageTransfer.description, str(ImageTransfer.name), i, val)
self.logger.info(log_message)

RESULT:
----> Reading: Type: ObjectType.IMAGE_TRANSFER, Name: , LN: 0.0.44.0.0.255:2, Value: 256
----> Reading: Type: ObjectType.IMAGE_TRANSFER, Name: , LN: 0.0.44.0.0.255:3, Value:
----> Reading: Type: ObjectType.IMAGE_TRANSFER, Name: , LN: 0.0.44.0.0.255:4, Value: 0
----> Reading: Type: ObjectType.IMAGE_TRANSFER, Name: , LN: 0.0.44.0.0.255:5, Value: True
----> Reading: Type: ObjectType.IMAGE_TRANSFER, Name: , LN: 0.0.44.0.0.255:6, Value: 0
----> Reading: Type: ObjectType.IMAGE_TRANSFER, Name: , LN: 0.0.44.0.0.255:7, Value: [<gurux_dlms.objects.GXDLMSImageActivateInfo.GXDLMSImageActivateInfo object at 0x7ffc006d0fa0>]

So, can you please point to the right direction what is wrong with it and why I can't initiate the transfer?

Thanks a lot,
Ilya

  • Create new account
  • Reset your password

Hire Us!

Latest Releases

  • Tue, 06/09/2026 - 11:16
    gurux.dlms.java 4.0.95
  • Tue, 06/09/2026 - 10:03
    Gurux.DLMS.Python 1.0.199
  • Mon, 06/08/2026 - 13:39
    gurux.dlms.cpp 9.0.2606.0801
  • Mon, 06/01/2026 - 10:15
    gurux.dlms.cpp 9.0.2606.0101
  • Thu, 05/28/2026 - 16:06
    gurux.dlms.java 4.0.94

New forum topics

  • Error reading L&G Meter
  • Pass a TCP Client to GXNet
  • Australian EDMI Mk10D (Essential Energy area)
  • Strange mix of data notificiation vs get response
  • DLMS Connection
More

Who's new

  • Tuanhgg
  • Adel
  • charnon
  • Paddles
  • Miguel Ángel
RSS feed
Privacy FAQ GXDN Issues Contact
Follow Gurux on Twitter Follow Gurux on Linkedin