Securifi Peanut plug not updating power sensors

I’m running HAOS 17.0
Core 2026.1.2
Supervisor 2026.01.1
Frontend 20260107.2

I have many Securifi Peanut plugs that I’ve followed this process to update the firmware to the latest. It’s a older process but it appears to have worked as the firmware is showing that it updated.

The firmware shows that it’s been updated, but I get no updates on any of the power/energy sensors shown below. What am I doing wrong?

1 Like

Have you tried the “reconfigure” button yet?

I had a few of these plugs and they were pretty reliable for power reporting. I only got rid of them to try and stabilize my mesh. I read that the peanut plugs weren’t very reliable routers.

Thanks for the suggestion. I tried the reconfigure button and it’s still not reporting power. This was the result of the reconfigure button.

That’s really strange. I didn’t have to do anything. Once the firmware was updated they started working. As a last resort you could add the plugs again? Not sure what else could be causing this.

I’ll try deleting and re-adding to see if that fixes it. Did you update the firmware in ZHA or another way?

I tried to delete and re-add and I noticed the firmware was back to the original. I tried to update the firmware and get the warning below. My best guess is that the firmware update isn’t going through although the device shows the updated firmware (0x00000027) after running the set zigbee cluster attribute. I went back and made sure I was following the write up. I even tried changing the cluster type with the same results as suggested in the write up. Any ideas?? The write is quite old, perhaps something has broken this with the HA updates?

Logger: zha
Source: runner.py:289
First occurred: 2:25:52 PM (1 occurrence)
Last logged: 2:25:52 PM

Received unknown event: DeviceFirmwareInfoUpdatedEvent(event_type=‘zha_device_updated_event’, event=‘zha_device_updated_event’, old_firmware_version=‘0x00000000’, new_firmware_version=‘0x00000027’)

I’m in the same boat, old instructions don’t work. It doesn’t seem to recognize the OTA file as a valid firmware for the device.

Edit: I found an updated process here, and zha prompted me to install the update without dev tools:

1 Like

Great find. I’ll give it a shot. Approx. how long after you followed the process did zha ask you if you wanted to update the firmware (minutes, hours, longer)?

Just a few minutes, but not until I went to the device page for the peanut plug.

I’m getting all stats except for frequency. Good enough I guess.

For some reason mine isn’t updating past the 0x00000027 firmware. When I run the set zigbee cluster attribute the peanut plug light flashes red to green for a while, but it never tries to install the 0x00000039 firmware. Screenshots below. Any ideas?

I think the filename needs to be ZPS_CS5490_039.ota - that’s what I downloaded from somewhere and I think the filename is associated with this device so that zha knows to use it for that device.

1 Like

I tried that. Still no luck. The plug flashes green to red, then turns solid red. I left it for about 30 minutes. No option to update firmware. Then I tried unplugging it for about 15 seconds and plugging it back in. Still no option to update firmware. Perhaps I’m doing something wrong (I’ve only been on HA for a few weeks)? I just can’t see what’s wrong. I’d really like to get this figured out as I have 10 of these peanut plugs.


Update: I was able to get it to work by removing the device and re-adding it. I had to then re-run the zigbee cluster attribute and it updated to show the power.

2 Likes

Thank you all for these tips. I’ve made a lot of progress with the updated configuration which now looks like this on HAOS 17.1:

zha:
  zigpy_config:
    ota:
      extra_providers:
        - type: advanced  # !!! Please read the message below before enabling OTA updates from raw OTA files !!!
          warning: I understand I can *destroy* my devices by enabling OTA updates from
            files. Some OTA updates can be mistakenly applied to the wrong
            device, breaking it. I am consciously using this at my own risk.
          path: /config/ota_peanut

logger:
  default: warning
  logs:
    homeassistant.core: warning
    homeassistant.components.zha: debug
    bellows.zigbee.application: info
    bellows.ezsp: info
    zigpy: debug
    zigpy_cc: info
    zigpy_deconz.zigbee.application: info
    zigpy_deconz.api: info
    zigpy_xbee.zigbee.application: info
    zigpy_xbee.api: info
    zigpy_zigate: info
    zigpy_znp: info
    zhaquirks: info

The OTA filename is /config/ota_peanut/ZPS_CS5490_039.ota

When I write the attribute:

I can see from the logs that it’s able to identify the custom OTA file:

2026-03-13 18:41:07.093 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0005] Decoded ZCL frame: Scenes:WriteAttributesResponseSchema(status_records=[WriteAttributesStatusRecord(status=<Status.SUCCESS: 0>)])
2026-03-13 18:41:07.096 DEBUG (MainThread) [zigpy.event] Emitting event attribute_written with data AttributeWrittenEvent(event_type='attribute_written', device_ieee='00:0d:6f:00:05:49:9d:08', endpoint_id=1, cluster_type=<ClusterType.Server: 0>, cluster_id=5, attribute_name='current_group', attribute_id=2, manufacturer_code=None, value=49502, status=<Status.SUCCESS: 0>) (2 listeners)
2026-03-13 18:41:07.097 DEBUG (MainThread) [homeassistant.components.zha.websocket_api] Set attribute for: cluster_id: [5] cluster_type: [in] endpoint_id: [1] attribute: [2] value: [49502] manufacturer: [UndefinedType._singleton] response: [[[WriteAttributesStatusRecord(status=<Status.SUCCESS: 0>)]]]
2026-03-13 18:41:08.743 DEBUG (MainThread) [zigpy.application] Feeding watchdog
2026-03-13 18:41:08.992 DEBUG (MainThread) [zigpy.application] Received a packet: ZigbeePacket(timestamp=datetime.datetime(2026, 3, 13, 22, 41, 8, 992413, tzinfo=datetime.timezone.utc), priority=None, src=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0F5A), src_ep=1, dst=AddrModeAddress(addr_mode=<AddrMode.NWK: 2>, address=0x0000), dst_ep=1, source_route=None, extended_timeout=False, tsn=142, profile_id=260, cluster_id=25, data=Serialized[b"\x01\r\x01\x00\x02\x10\xc0^'\x00\x00\x00"], tx_options=<TransmitOptions.NONE: 0>, radius=0, non_member_radius=0, lqi=255, rssi=-26)
2026-03-13 18:41:08.993 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Received ZCL frame: '01 0d 01 00 02 10 c0 5e 27 00 00 00'
2026-03-13 18:41:08.993 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x01>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=13, command_id=1, *direction=<Direction.Client_to_Server: 0>)
2026-03-13 18:41:08.993 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Decoded ZCL frame: Ota:QueryNextImageCommand(field_control=<QueryNextImageCommandFieldControl: 0>, manufacturer_code=4098, image_type=24256, current_file_version=39)
2026-03-13 18:41:08.994 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Received command 0x01 (TSN 13): QueryNextImageCommand(field_control=<QueryNextImageCommandFieldControl: 0>, manufacturer_code=4098, image_type=24256, current_file_version=39)
2026-03-13 18:41:08.995 DEBUG (MainThread) [zigpy.event] Emitting event attribute_updated with data AttributeUpdatedEvent(event_type='attribute_updated', device_ieee='00:0d:6f:00:05:49:9d:08', endpoint_id=1, cluster_type=<ClusterType.Client: 1>, cluster_id=25, attribute_name='current_file_version', attribute_id=2, manufacturer_code=None, value=39) (2 listeners)
2026-03-13 18:41:08.996 WARNING (MainThread) [zha] Received unknown event: DeviceFirmwareInfoUpdatedEvent(event_type='zha_device_updated_event', event='zha_device_updated_event', old_firmware_version='0x00000000', new_firmware_version='0x00000027')
2026-03-13 18:41:08.998 DEBUG (MainThread) [homeassistant.components.zha.entity] update.securifi_ltd_unk_model_firmware: Handling event from entity: EntityStateChangedEvent(event_type='entity', event='state_changed', platform=<Platform.UPDATE: 'update'>, unique_id='00:0d:6f:00:05:49:9d:08-1-25-firmware_update', device_ieee=00:0d:6f:00:05:49:9d:08, endpoint_id=1, group_id=None)
2026-03-13 18:41:08.999 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Sending reply header: ZCLHeader(frame_control=FrameControl<0x19>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=1, reserved=0, *is_cluster=True, *is_general=False), tsn=13, command_id=2, *direction=<Direction.Server_to_Client: 1>)
2026-03-13 18:41:08.999 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Sending reply: query_next_image_response(status=<Status.NO_IMAGE_AVAILABLE: 152>, manufacturer_code=None, image_type=None, file_version=None, image_size=None)
2026-03-13 18:41:09.445 DEBUG (MainThread) [zigpy.ota] Loaded 20 images from provider: ZigpyOtaProvider(url='https://raw.githubusercontent.com/zigpy/zigpy-ota/release/version/stable.json', channel='stable', manufacturer_ids=())
2026-03-13 18:41:09.457 DEBUG (MainThread) [zigpy.ota] Loaded 1 images from provider: AdvancedFileProvider(path=PosixPath('/config/ota_peanut'), manufacturer_ids=())
2026-03-13 18:41:09.462 DEBUG (MainThread) [zigpy.ota] Caching image OtaImageWithMetadata(metadata=LocalOtaImageMetadata(file_version=57, manufacturer_id=4098, image_type=24256, checksum='sha1:65f29a4c2cee6601e34ad08a980c33076c5316b7', file_size=155646, manufacturer_names=(), model_names=(), changelog=None, release_notes=None, release_url=None, min_hardware_version=None, max_hardware_version=None, min_current_file_version=None, max_current_file_version=None, specificity=None, source='Advanced file provider (/config/ota_peanut)', path=PosixPath('/config/ota_peanut/ZPS_CS5490_039.ota')), firmware=OTAImage(header=OTAImageHeader(upgrade_file_id=200208670, header_version=256, header_length=56, field_control=<FieldControl: 0>, manufacturer_id=4098, image_type=24256, file_version=57, stack_version=2, header_string=<'peanut Power Plug'>, image_size=155646, *device_specific_file=False, *hardware_versions_present=False, *security_credential_version_present=False), subelements=[<SubElement(tag_id=<ElementTagId.UPGRADE_IMAGE: 0>, data=[155584:0000008c0201e350080020006ade5513e81c0020514e0208e5...ffffffffffffff])>]))
2026-03-13 18:41:09.464 DEBUG (MainThread) [homeassistant.components.zha.entity] update.securifi_ltd_unk_model_firmware: Handling event from entity: EntityStateChangedEvent(event_type='entity', event='state_changed', platform=<Platform.UPDATE: 'update'>, unique_id='00:0d:6f:00:05:49:9d:08-1-25-firmware_update', device_ieee=00:0d:6f:00:05:49:9d:08, endpoint_id=1, group_id=None)

Specifically DeviceFirmwareInfoUpdatedEvent(event_type='zha_device_updated_event', event='zha_device_updated_event', old_firmware_version='0x00000000', new_firmware_version='0x00000027')

and

Loaded 1 images from provider: AdvancedFileProvider(path=PosixPath('/config/ota_peanut'), manufacturer_ids=())

But then I notice its saying that the there is no image file to be sent!
Sending reply: query_next_image_response(status=<Status.NO_IMAGE_AVAILABLE: 152>, manufacturer_code=None, image_type=None, file_version=None, image_size=None)

It seems that it’s not able to match the firmware file with the peanut plug.

And I keep seeing this repeated over and over again.

2026-03-13 18:50:54.897 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl<0x01>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False), tsn=15, command_id=1, *direction=<Direction.Client_to_Server: 0>)
2026-03-13 18:50:54.898 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Decoded ZCL frame: Ota:QueryNextImageCommand(field_control=<QueryNextImageCommandFieldControl: 0>, manufacturer_code=4098, image_type=24256, current_file_version=39)
2026-03-13 18:50:54.898 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Received command 0x01 (TSN 15): QueryNextImageCommand(field_control=<QueryNextImageCommandFieldControl: 0>, manufacturer_code=4098, image_type=24256, current_file_version=39)
2026-03-13 18:50:54.898 DEBUG (MainThread) [zigpy.event] Emitting event attribute_updated with data AttributeUpdatedEvent(event_type='attribute_updated', device_ieee='00:0d:6f:00:05:49:9d:08', endpoint_id=1, cluster_type=<ClusterType.Client: 1>, cluster_id=25, attribute_name='current_file_version', attribute_id=2, manufacturer_code=None, value=39) (2 listeners)
2026-03-13 18:50:54.901 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Sending reply header: ZCLHeader(frame_control=FrameControl<0x19>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=1, reserved=0, *is_cluster=True, *is_general=False), tsn=15, command_id=2, *direction=<Direction.Server_to_Client: 1>)
2026-03-13 18:50:54.901 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Sending reply: query_next_image_response(status=<Status.NO_IMAGE_AVAILABLE: 152>, manufacturer_code=None, image_type=None, file_version=None, image_size=None)
2026-03-13 18:50:55.012 DEBUG (MainThread) [zigpy.ota] Provider ZigpyOtaProvider(url='https://raw.githubusercontent.com/zigpy/zigpy-ota/release/version/stable.json', channel='stable', manufacturer_ids=()) was recently contacted, using cached response
2026-03-13 18:50:55.013 DEBUG (MainThread) [zigpy.ota] Provider AdvancedFileProvider(path=PosixPath('/config/ota_peanut'), manufacturer_ids=()) was recently contacted, using cached response

I’m a little confused here. What is supposed to happen? How do I know if it’s sending the firmware image to the file and when it’s completed? Is there another way to force sending the image file to the plug? I’ve tried to pair it multiple times but nothing. Sometimes I see the solid red light when it tries to update the firmware.

Any ideas?

Okay I’m going to answer my own question above with a little help from the updated instructions link:

For me, this didn’t actually force the peanut to fully upgrade or show power, but it allowed the peanut to allow OTA updates. So now on the peanut device properties in HA I could see the firmware say “update available”. I simply clicked on that which started the update which took maybe 10 minutes and I could see the progress bar live. Once that was done the peanut automatically restarted and I could see power tracked.

So writing the attribute doesn’t update the firmware, it only allows the plug to accept a firmware update.

After writing the attribute, I now see under Settings an option to update the plug and when I click on it I see:

After clicking Update now I can see the progress in the UI and in the logs I see (I can’t post more images unfortunately as a new user)

2026-03-13 19:31:36.990 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Decoded ZCL frame: Ota:ImageBlockCommand(field_control=<ImageBlockCommandFieldControl: 0>, manufacturer_code=4098, image_type=24256, file_version=57, file_offset=8150, maximum_data_size=63)
2026-03-13 19:31:36.990 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Data remains after deserializing ZCL frame: '00 00'
2026-03-13 19:31:36.990 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Received command 0x03 (TSN 89): ImageBlockCommand(field_control=<ImageBlockCommandFieldControl: 0>, manufacturer_code=4098, image_type=24256, file_version=57, file_offset=8150, maximum_data_size=63)
2026-03-13 19:31:36.991 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Sending reply header: ZCLHeader(frame_control=FrameControl<0x19>(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Server_to_Client: 1>, disable_default_response=1, reserved=0, *is_cluster=True, *is_general=False), tsn=89, command_id=5, *direction=<Direction.Server_to_Client: 1>)
2026-03-13 19:31:36.991 DEBUG (MainThread) [zigpy.zcl] [0x0F5A:1:0x0019] Sending reply: ImageBlockResponseCommand(status=<Status.SUCCESS: 0>, manufacturer_code=4098, image_type=24256, file_version=57, file_offset=8150, image_data=b'\x14\xf8\x01"VI\x00\xf0\x10\xf8\x02"PI\x00\xf0\x0c\xf8\x03"SI\x00\xf0\x08\xf8\x04"II\x00\xf0\x04\xf8\x04\xf1\x18\x002\xe0\x10\xbd\x04\xf1\x18\x00\x96\xe7\x10\xb5')
2026-03-13 19:31:36.992 DEBUG (MainThread) [zigpy.device] Device concurrency (1) reached, delaying request (0 enqueued)
2026-03-13 19:31:37.000 INFO (MainThread) [zigpy.device] [0x0f5a] OTA upgrade progress: (8150 / 155646): 5.2362%
2026-03-13 19:31:37.000 DEBUG (MainThread) [homeassistant.components.zha.entity] update.securifi_ltd_unk_model_firmware: Handling event from entity: EntityStateChangedEvent(event_type='entity', event='state_changed', platform=<Platform.UPDATE: 'update'>, unique_id='00:0d:6f:00:05:49:9d:08-1-25-firmware_update', device_ieee=00:0d:6f:00:05:49:9d:08, endpoint_id=1, group_id=None)

After about 13 minutes it seems to have completed the update and the plug restarted itself and it started reporting power, current and voltage. I didn’t even have to pair it again. However keep in mind that not pairing it again, the firmware version will still show 0x0000000, for it to show 0x00000039 you will need to remove it and pair again AND you will need to write the attribute to the cluster again to make it ready to accept a firmware update (otherwise it still shows 0x000000).

So that was it, sending the attribute only enabled the OTA feature on the plug, then I have to actually update the firmware from the settings.

Thanks everyone for the links and tips. Hopefully this helps others as well.

BTW, AI got everything about this plug firmware update wrong until I came across this topic. Guess google is still king…