chrisc123 / jebao_aqua-homeassistant

Home Assistant integration to control Wi-Fi enabled Jebao wavemaker devices
5 stars 2 forks source link

ep-xxx implementation #8

Open ramarro123 opened 2 weeks ago

ramarro123 commented 2 weeks ago

hi,

i am trying to add support for 02039876751049deb404d1d89221ec4b that's the ep model for powerhead

i ended with this minimum example as attrs in the json config file (added at end of post) the pump is recognized, including the custom name i give it via aqua app, so i guess i am on the right path.

now, couple of issue (i got this data by decompiling apk of adroid, latest version)

1) speed work, but only one way, i can set it, the controller get updated and same for android app, if i change with app or controller homeassistant don't reflect the change even after a few mins

2) all the other stuff doens't work quite right at all, i have try to set feed mode, to shutdown the pump but nothing seems work

any idea on what i did wrong? or there are other config that should be taken into account?

   {
      "display_name": "Switch",
      "name": "SwitchON",
      "data_type": "bool",
      "position": {
        "byte_offset": 0,
        "unit": "bit",
        "len": 1,
        "bit_offset": 0
      },
      "type": "status_writable",
      "id": 0,
      "desc": ""
    },
    {
      "display_name": "Motor Speed",
      "name": "Motor_Speed",
      "data_type": "uint8",
      "position": {
        "byte_offset": 1,
        "unit": "byte",
        "len": 1,
        "bit_offset": 0
      },
      "uint_spec": {
        "addition": 0,
        "max": 100,
        "ratio": 1,
        "min": 0
      },
      "type": "status_writable",
      "id": 5,
      "desc": ""
    },
    {
      "display_name": "Feeding Switch",
      "name": "FeedSwitch",
      "data_type": "bool",
      "position": {
        "byte_offset": 0,
        "unit": "bit",
        "len": 1,
        "bit_offset": 2
      },
      "type": "status_writable",
      "id": 2,
      "desc": "Feeding switch, 0: off, 1: on"
    },
    {
      "display_name": "Timer Switch",
      "name": "TimerON",
      "data_type": "bool",
      "position": {
        "byte_offset": 0,
        "unit": "bit",
        "len": 1,
        "bit_offset": 3
      },
      "type": "status_writable",
      "id": 3,
      "desc": "0: Timing off, 1: Timing on"
    },
    {
      "display_name": "Current timing mode",
      "name": "AutoMode",
      "data_type": "enum",
      "enum": [
        "shutdown",
        "auto",
        "feeding"
      ],
      "position": {
        "byte_offset": 0,
        "unit": "bit",
        "len": 2,
        "bit_offset": 4
      },
      "type": "status_writable",
      "id": 4,
      "desc": "Current timing mode: 0: shutdown; 1: automatic; 2: feeding"
    },
chrisc123 commented 2 weeks ago

Hi, Sounds like the IP address discovery of the local device might not have worked. The integration uses local polling (rather than cloud) to update device status.

If you turn on debug logging for the plugin (it's very verbose!) that might help narrow things down. I didn't really expect anyone else to end up using this integration to be honest but seeing as it's getting a little interest I'll try to find some time next week to tidy up a few broken bits (exposing device IP address in config menu after initial install for example) and look at the other device types mentioned in other issues.

ramarro123 commented 2 weeks ago

hi @chrisc123 not sure if it's what you are looking for, it's repeated quite a few time so i guess it could be useful to get just a pieace.

the 2 invalid product are a dosing pump and the new gyre that i don't remember the name. the one i ma trying to make it work is reCzxZhEdgrC2RjdMWJbq6 ip = 192.168.1.15 is correct. some strange things Motor_Speed': 238 -> it's that right? AutoMode': '喂食' -> where it comes from?

and also 2024-08-25 13:52:37.718 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: {'did': 'reCzxZhEdgrC2RjdMWJbq6', 'attr': {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'}}

switchOn should be true, as it's actually turned on the pump, and feedswitch should be false i think, but i am not 100% sure. timerOn and auto mode no idea what they really are probably is the way to enable the programming function (if it's the case, it should be off, i don't use programming)

btw, i think there are quite a few ppl willing to add jebao echosystem to home assistant, it's a good budget option and was great to see soeone putting effort, thank you very much for your help!

2024-08-25 13:51:35.720 DEBUG (MainThread) [custom_components.jebao_aqua] Successfully parsed local device data: {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'} 2024-08-25 13:51:35.720 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: {'did': 'reCzxZhEdgrC2RjdMWJbq6', 'attr': {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'}} 2024-08-25 13:51:35.721 DEBUG (MainThread) [custom_components.jebao_aqua] Finished fetching jebao_aqua data in 0.014 seconds (success: True) 2024-08-25 13:51:37.707 ERROR (MainThread) [custom_components.jebao_aqua] Invalid product key or missing attribute model for product key: 54114ccdac1e41c0bb17e222887c07ba 2024-08-25 13:51:37.707 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: None 2024-08-25 13:51:37.707 ERROR (MainThread) [custom_components.jebao_aqua] Invalid product key or missing attribute model for product key: 25c5b146791f465bbefdbfd312b9e8ea 2024-08-25 13:51:37.707 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: None 2024-08-25 13:51:37.707 DEBUG (MainThread) [custom_components.jebao_aqua] Attempting to get local device data - IP: 192.168.1.15, Device ID: reCzxZhEdgrC2RjdMWJbq6 2024-08-25 13:51:37.709 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0006, Payload: 2024-08-25 13:51:37.709 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:37.712 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0008, Payload: 000a574d4544445051474550 2024-08-25 13:51:37.712 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:37.714 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0093, Payload: 0000000202 2024-08-25 13:51:37.715 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:37.718 ERROR (MainThread) [root] Error parsing device status payload: index out of range 2024-08-25 13:51:37.718 DEBUG (MainThread) [custom_components.jebao_aqua] Successfully parsed local device data: {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'} 2024-08-25 13:51:37.718 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: {'did': 'reCzxZhEdgrC2RjdMWJbq6', 'attr': {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'}} 2024-08-25 13:51:37.718 DEBUG (MainThread) [custom_components.jebao_aqua] Finished fetching jebao_aqua data in 0.011 seconds (success: True) 2024-08-25 13:51:38.485 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'value_json' is undefined when rendering '{{ value_json.active1 }}' 2024-08-25 13:51:38.485 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'value_json' is undefined when rendering '{{ value_json.active2 }}' 2024-08-25 13:51:38.485 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'value_json' is undefined when rendering '{{ value_json.active3 }}' 2024-08-25 13:51:38.486 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'value_json' is undefined when rendering '{{ value_json.active3 }}' 2024-08-25 13:51:39.708 ERROR (MainThread) [custom_components.jebao_aqua] Invalid product key or missing attribute model for product key: 54114ccdac1e41c0bb17e222887c07ba 2024-08-25 13:51:39.708 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: None 2024-08-25 13:51:39.708 ERROR (MainThread) [custom_components.jebao_aqua] Invalid product key or missing attribute model for product key: 25c5b146791f465bbefdbfd312b9e8ea 2024-08-25 13:51:39.708 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: None 2024-08-25 13:51:39.708 DEBUG (MainThread) [custom_components.jebao_aqua] Attempting to get local device data - IP: 192.168.1.15, Device ID: reCzxZhEdgrC2RjdMWJbq6 2024-08-25 13:51:39.711 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0006, Payload: 2024-08-25 13:51:39.711 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:39.713 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0008, Payload: 000a574d4544445051474550 2024-08-25 13:51:39.713 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:39.715 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0093, Payload: 0000000202 2024-08-25 13:51:39.715 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:39.719 ERROR (MainThread) [root] Error parsing device status payload: index out of range 2024-08-25 13:51:39.719 DEBUG (MainThread) [custom_components.jebao_aqua] Successfully parsed local device data: {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'} 2024-08-25 13:51:39.719 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: {'did': 'reCzxZhEdgrC2RjdMWJbq6', 'attr': {'SwitchON': False, 'Motor_Speed': 238, 'FeedSwitch': True, 'TimerON': True, 'AutoMode': '喂食'}} 2024-08-25 13:51:39.719 DEBUG (MainThread) [custom_components.jebao_aqua] Finished fetching jebao_aqua data in 0.011 seconds (success: True) 2024-08-25 13:51:41.707 ERROR (MainThread) [custom_components.jebao_aqua] Invalid product key or missing attribute model for product key: 54114ccdac1e41c0bb17e222887c07ba 2024-08-25 13:51:41.707 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: None 2024-08-25 13:51:41.707 ERROR (MainThread) [custom_components.jebao_aqua] Invalid product key or missing attribute model for product key: 25c5b146791f465bbefdbfd312b9e8ea 2024-08-25 13:51:41.707 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: None 2024-08-25 13:51:41.707 DEBUG (MainThread) [custom_components.jebao_aqua] Attempting to get local device data - IP: 192.168.1.15, Device ID: reCzxZhEdgrC2RjdMWJbq6 2024-08-25 13:51:41.710 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0006, Payload: 2024-08-25 13:51:41.710 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:41.713 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0008, Payload: 000a574d4544445051474550 2024-08-25 13:51:41.713 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:41.716 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0093, Payload: 0000000202 2024-08-25 13:51:41.716 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-25 13:51:41.719 ERROR (MainThread) [root] Error parsing device status payload: index out of range

ramarro123 commented 2 weeks ago

hi i add some details that maybe can be useful for the investigation

i added some log at the end of sending command 0x93

what we got in response is 2024-08-26 11:00:44.745 DEBUG (MainThread) [custom_components.jebao_aqua] response 00000003b602000094000000020301640a64001418081a0009262d000000000164eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00

now, if you see here, the payload start after 00000003b6020000940000000203 as per protocolo last part should be 0x94 4 bytes of seq number (same that api.py send 0x02) 0x03 for hack rest of junk while after the _extract_device_status_payload we got a slice that doens't look right (missing the first part)

the reponse lenght of _extract_device_status_payload is 174, that seems strange. also we need that? can't we just offset of + 0x03 and maybe make sequence number change at every call? and, why it does a little endian conversion, i can't find the part where it should be done honestly for both len (that the js sutff i looked at doesn't even use) nor for payload extraction

here the log!

Thanks!

2024-08-26 11:00:44.742 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0093, Payload: 0000000202 2024-08-26 11:00:44.742 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully 2024-08-26 11:00:44.745 DEBUG (MainThread) [custom_components.jebao_aqua] response 00000003b602000094000000020301640a64001418081a0009262d000000000164eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00 2024-08-26 11:00:44.745 DEBUG (MainThread) [custom_components.jebao_aqua] respoinse len 174 2024-08-26 11:00:44.745 DEBUG (MainThread) [custom_components.jebao_aqua] payload: b'\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\x00' <class 'bytes'>

ramarro123 commented 2 weeks ago

i did "fix" it in this way

it's for sure wrong, so it's better if you find a better way as i am not a developer :) what i did was searching on the response the 'offset' of what should be the payload of the device. to do that i looped on the repsonse, then extracted 0x0 0x0 0x0 0x02 0x03 that seems the recurring part of the answer with sequence number and 0x03

i also remove the encoding that didn't worked for me

as said, not a developer 👍

    def _extract_device_status_payload(self, response):
        """Extract the device status payload from the response."""
        try:
            N = -1

            for x in range(0,14):
              if response[x] == 0 and response[x+1] == 0 and response[x+2] == 0 and response[x+3] == 2 and response[x+4] == 3:
                    N = x+5
                    LOGGER.debug(f"found what i was looking for at index {x+5}")

            if N < 0:
                LOGGER.error(f"Error extracting device payload")
                return None

            device_status_payload = response[N:]
            LOGGER.debug(f"response {device_status_payload.hex()}")
            return device_status_payload.hex()
        except Exception as e:
            LOGGER.error(f"Error in extracting device status payload: {e}")

        return None
noobookbig commented 1 week ago

i did "fix" it in this way

it's for sure wrong, so it's better if you find a better way as i am not a developer :) what i did was searching on the response the 'offset' of what should be the payload of the device. to do that i looped on the repsonse, then extracted 0x0 0x0 0x0 0x02 0x03 that seems the recurring part of the answer with sequence number and 0x03

i also remove the encoding that didn't worked for me

as said, not a developer 👍

    def _extract_device_status_payload(self, response):
        """Extract the device status payload from the response."""
        try:
            N = -1

            for x in range(0,14):
              if response[x] == 0 and response[x+1] == 0 and response[x+2] == 0 and response[x+3] == 2 and response[x+4] == 3:
                    N = x+5
                    LOGGER.debug(f"found what i was looking for at index {x+5}")

            if N < 0:
                LOGGER.error(f"Error extracting device payload")
                return None

            device_status_payload = response[N:]
            LOGGER.debug(f"response {device_status_payload.hex()}")
            return device_status_payload.hex()
        except Exception as e:
            LOGGER.error(f"Error in extracting device status payload: {e}")

        return None

I have got the same problem as you said with Water Pump [02039876751049deb404d1d89221ec4b] the code above has fix it sadly but, it's affect the wave pump. I will try to look into this one.

chrisc123 commented 3 days ago

Yeah it's interesting - the Water pump (02039876751049deb404d1d89221ec4b) has a simpler response payload (fewer config options) compared to the Wavemaker (1d8c63eaccac4205b92c84d77d5a08fb).

The reason you have to swap the endianness of the first two bytes for the Wavemaker response seems to be a result of the weird 'byte 0' structure defined in it's JSON - e.g the bit below which suggests "Automode" is bit_offset 9 (???) of byte 0.

The waterpump JSON is more sane in that it doesn't have anything with a bit offset > 8 for a given byte so doesn't need this weirdness.

I suppose it should be pretty simple to identify is a given device JSON has a weird/long 'byte 0' structure or not and parse appropriately. @noobookbig As it looks like you have both device types in your tank hopefully you can test this out once I've updated the code to handle this.

@ramarro123 You're right that the code for calculating the length of the response payload is wrong - and also that it's probably redundant, I think your approach of looking for that 'magic sequence' is probably better for now as I can't quite figure out code that 'properly' extracts the payload length from both my devices and the response you provided.

{
      "display_name": "当前定时模式",
      "name": "AutoMode",
      "data_type": "enum",
      "enum": [
        "停机",
        "经典造浪",
        "正弦造浪",
        "随机造浪",
        "恒流造浪",
        "喂食"
      ],
      "position": {
        "byte_offset": 0,
        "unit": "bit",
        "len": 3,
        "bit_offset": 9
      },
      "type": "status_writable",
      "id": 7,
      "desc": "当前定时模式:0:停机 1.经典造浪 2.正弦造浪 3.随机造浪 4.恒流造浪 5.喂食"
    },
chrisc123 commented 2 days ago

Ah ChatGPT helped me figure out they use LEB128 to encode the payload length. I've fixed that and hopefully added support for the EP series pumps now.

If you'd be able to update your api.py with latest from the repo as well as add the new JSON file to your /models/ directory and give it a go @noobookbig it'd be great to know if it works for you.

noobookbig commented 2 days ago

Ah ChatGPT helped me figure out they use LEB128 to encode the payload length. I've fixed that and hopefully added support for the EP series pumps now.

If you'd be able to update your api.py with latest from the repo as well as add the new JSON file to your /models/ directory and give it a go @noobookbig it'd be great to know if it works for you.

Thank you so much for a lot of work that you do for the community :)

The code for EP Series have typo issue in the header which contain .json in the product key ,

Line 2 in **02039876751049deb404d1d89221ec4b.json** 
`"product_key": "02039876751049deb404d1d89221ec4b",   `

after correct it working properly , however the issue of the wave pump still exist and I just realize thai I have use different wave pump of the integration I use the MLW Wave Maker [f0d844ab0d4947ac9527a286160bc705] that I have use the base model [1d8c63eaccac4205b92c84d77d5a08fb] the problem that I got is the Power Switch from On show as Off and The Feeding Switch goes On.

I have attach the model from log in gizwit app from android , I check it's the same with [1d8c63eaccac4205b92c84d77d5a08fb]

GIZ_SDK_SUCCESS,
productKeyis{
    "name": "\u672c\u5730\u9020\u6d6a\u6cf5",
    "packetVersion": "0x00000004",
    "protocolType": "standard",
    "product_key": "f0d844ab0d4947ac9527a286160bc705",
    "entities": [
        {
            "display_name": "\u673a\u667a\u4e91\u5f00\u53d1\u5957\u4ef6",
            "attrs": [
                {
                    "display_name": "\u5f00\u5173",
                    "name": "SwitchON",
                    "data_type": "bool",
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 0,
                    "desc": ""
                },
                {
                    "display_name": "\u8109\u51b2\u6f6e\u6c50",
                    "name": "PulseTide",
                    "data_type": "bool",
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 1,
                        "bit_offset": 1
                    },
                    "type": "status_writable",
                    "id": 1,
                    "desc": "\u8109\u51b2\u548c\u6f6e\u6c50\u9020\u6d6a\u9009\u62e9,0\uff1a\u8109\u51b2\u9020\u6d6a\uff0c1:\u6f6e\u6c50\u9020\u6d6a"
                },
                {
                    "display_name": "\u5582\u98df\u5f00\u5173",
                    "name": "FeedSwitch",
                    "data_type": "bool",
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 1,
                        "bit_offset": 2
                    },
                    "type": "status_writable",
                    "id": 2,
                    "desc": "\u5582\u98df\u5f00\u5173\uff0c0\uff1a\u5173\u95ed\uff0c1\uff1a\u6253\u5f00"
                },
                {
                    "display_name": "\u5b9a\u65f6\u5f00\u5173",
                    "name": "TimerON",
                    "data_type": "bool",
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 1,
                        "bit_offset": 3
                    },
                    "type": "status_writable",
                    "id": 3,
                    "desc": "0:\u5b9a\u65f6\u5173\u95ed\uff0c1\uff1a\u5b9a\u65f6\u6253\u5f00"
                },
                {
                    "display_name": "\u5f53\u524d\u5b9a\u65f6\u8109\u51b2\u6f6e\u6c50",
                    "name": "AutoPulseTide",
                    "data_type": "bool",
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 1,
                        "bit_offset": 4
                    },
                    "type": "status_writable",
                    "id": 4,
                    "desc": "\u8109\u51b2\u548c\u6f6e\u6c50\u9020\u6d6a\u9009\u62e9,0\uff1a\u8109\u51b2\u9020\u6d6a\uff0c1:\u6f6e\u6c50\u9020\u6d6a"
                },
                {
                    "display_name": "\u6a21\u5f0f",
                    "name": "Mode",
                    "data_type": "enum",
                    "enum": [
                        "\u7ecf\u5178\u9020\u6d6a",
                        "\u6b63\u5f26\u9020\u6d6a",
                        "\u968f\u673a\u9020\u6d6a",
                        "\u6052\u6d41\u9020\u6d6a"
                    ],
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 2,
                        "bit_offset": 5
                    },
                    "type": "status_writable",
                    "id": 5,
                    "desc": "0.\u7ecf\u5178\u9020\u6d6a 1.\u6b63\u5f26\u9020\u6d6a 2.\u968f\u673a\u9020\u6d6a 3.\u6052\u6d41\u9020\u6d6a ??"
                },
                {
                    "display_name": "\u8054\u52a8",
                    "name": "Linkage",
                    "data_type": "enum",
                    "enum": [
                        "\u72ec\u7acb",
                        "\u4e3b\u673a",
                        "\u4ece\u673a"
                    ],
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 2,
                        "bit_offset": 7
                    },
                    "type": "status_writable",
                    "id": 6,
                    "desc": "\u8bbe\u7f6e\u4e3a\u72ec\u7acb\uff0c\u4e3b\u673a\uff0c\u4ece\u673a"
                },
                {
                    "display_name": "\u5f53\u524d\u5b9a\u65f6\u6a21\u5f0f",
                    "name": "AutoMode",
                    "data_type": "enum",
                    "enum": [
                        "\u505c\u673a",
                        "\u7ecf\u5178\u9020\u6d6a",
                        "\u6b63\u5f26\u9020\u6d6a",
                        "\u968f\u673a\u9020\u6d6a",
                        "\u6052\u6d41\u9020\u6d6a",
                        "\u5582\u98df"
                    ],
                    "position": {
                        "byte_offset": 0,
                        "unit": "bit",
                        "len": 3,
                        "bit_offset": 9
                    },
                    "type": "status_writable",
                    "id": 7,
                    "desc": "\u5f53\u524d\u5b9a\u65f6\u6a21\u5f0f\uff1a0:\u505c\u673a 1.\u7ecf\u5178\u9020\u6d6a 2.\u6b63\u5f26\u9020\u6d6a 3.\u968f\u673a\u9020\u6d6a 4.\u6052\u6d41\u9020\u6d6a 5.\u5582\u98df"
                },
                {
                    "display_name": "\u6d41\u91cf",
                    "name": "Flow",
                    "data_type": "uint8",
                    "position": {
                        "byte_offset": 2,
                        "unit": "byte",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "uint_spec": {
                        "addition": 0,
                        "max": 100,
                        "ratio": 1,
                        "min": 0
                    },
                    "type": "status_writable",
                    "id": 8,
                    "desc": "\u6d41\u91cf\u503c"
                },
                {
                    "display_name": "\u9891\u7387",
                    "name": "Frequency",
                    "data_type": "uint8",
                    "position": {
                        "byte_offset": 3,
                        "unit": "byte",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "uint_spec": {
                        "addition": 0,
                        "max": 100,
                        "ratio": 1,
                        "min": 0
                    },
                    "type": "status_writable",
                    "id": 9,
                    "desc": "\u9891\u7387\u503c"
                },
                {
                    "display_name": "\u5582\u98df\u65f6\u95f4",
                    "name": "FeedTime",
                    "data_type": "uint8",
                    "position": {
                        "byte_offset": 4,
                        "unit": "byte",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "uint_spec": {
                        "addition": 0,
                        "max": 60,
                        "ratio": 1,
                        "min": 1
                    },
                    "type": "status_writable",
                    "id": 10,
                    "desc": "\u5582\u98df\u65f6\u95f4"
                },
                {
                    "display_name": "\u5f53\u524d\u5b9a\u65f6\u6d41\u91cf",
                    "name": "AutoFlow",
                    "data_type": "uint8",
                    "position": {
                        "byte_offset": 5,
                        "unit": "byte",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "uint_spec": {
                        "addition": 0,
                        "max": 100,
                        "ratio": 1,
                        "min": 0
                    },
                    "type": "status_writable",
                    "id": 11,
                    "desc": "\u5f53\u524d\u5b9a\u65f6\u6d41\u91cf"
                },
                {
                    "display_name": "\u5f53\u524d\u5b9a\u65f6\u9891\u7387",
                    "name": "AutoFreq",
                    "data_type": "uint8",
                    "position": {
                        "byte_offset": 6,
                        "unit": "byte",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "uint_spec": {
                        "addition": 0,
                        "max": 100,
                        "ratio": 1,
                        "min": 0
                    },
                    "type": "status_writable",
                    "id": 12,
                    "desc": "\u5f53\u524d\u5b9a\u65f6\u9891\u7387"
                },
                {
                    "display_name": "\u5f53\u524d\u5b9a\u65f6\u5582\u98df\u65f6\u95f4",
                    "name": "AutoFeedTime",
                    "data_type": "uint8",
                    "position": {
                        "byte_offset": 7,
                        "unit": "byte",
                        "len": 1,
                        "bit_offset": 0
                    },
                    "uint_spec": {
                        "addition": 0,
                        "max": 60,
                        "ratio": 1,
                        "min": 1
                    },
                    "type": "status_writable",
                    "id": 13,
                    "desc": "\u5f53\u524d\u5b9a\u65f6\u5582\u98df\u65f6\u95f4"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b900",
                    "name": "AutoTime00",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 8,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 14,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b901",
                    "name": "AutoTime01",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 16,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 15,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b902",
                    "name": "AutoTime02",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 24,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 16,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b903",
                    "name": "AutoTime03",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 32,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 17,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b904",
                    "name": "AutoTime04",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 40,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 18,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b905",
                    "name": "AutoTime05",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 48,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 19,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b906",
                    "name": "AutoTime06",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 56,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 20,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\u6d6a\uff0c 3.\u968f\u673a\u9020\u6d6a\uff0c 4.\u6052\u6d41\u9020\u6d6a\uff0c5.\u5582\u98df\uff0cByte5\uff1a\u6d41\u91cf/\u5582\u98df\u65f6\u95f4,\u505c\u673a\u65f6\u6d41\u91cf=0\uff0cByte6:\u9891\u7387\uff0cByte7\uff1a\u8109\u51b2/\u6f6e\u6c50"
                },
                {
                    "display_name": "\u81ea\u52a8\u65f6\u95f4\u70b907",
                    "name": "AutoTime07",
                    "data_type": "binary",
                    "position": {
                        "byte_offset": 64,
                        "unit": "byte",
                        "len": 8,
                        "bit_offset": 0
                    },
                    "type": "status_writable",
                    "id": 21,
                    "desc": "Byte0\uff1a\u5f00\u59cb\u65f6\uff0cByte1\uff1a\u5f00\u59cb\u5206,Byte2:\u7ed3\u675f\u65f6\uff0cByte3:\u7ed3\u675f\u5206\uff0cByte4\uff1a\u6a21\u5f0f,0\u505c\u673a\uff0c1.\u7ecf\u5178\u9020\u6d6a\uff0c 2.\u6b63\u5f26\u9020\]

and this is I have got from HA log

2024-09-11 10:01:28.749 DEBUG (MainThread) [custom_components.jebao_aqua] Attempting to get local device data - IP: 192.168.1.43, Device ID: xECYiFFqUCbEqhYT657wmZ
2024-09-11 10:01:28.753 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0006, Payload: 
2024-09-11 10:01:28.753 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully
2024-09-11 10:01:28.757 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0008, Payload: 000a474a51585251484c5851
2024-09-11 10:01:28.757 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully
2024-09-11 10:01:28.761 DEBUG (MainThread) [custom_components.jebao_aqua] Sending local command: 0093, Payload: 0000000202
2024-09-11 10:01:28.761 DEBUG (MainThread) [custom_components.jebao_aqua] Command sent successfully
2024-09-11 10:01:28.766 DEBUG (MainThread) [custom_components.jebao_aqua] Response after sending command 0x93: 000000039103000094000000020304495a57285a640007000b3b025a64000b3b1200015a640012000700025a6400eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00
2024-09-11 10:01:28.766 ERROR (MainThread) [custom_components.jebao_aqua] Error parsing device status payload: index out of range
2024-09-11 10:01:28.766 DEBUG (MainThread) [custom_components.jebao_aqua] Successfully parsed local device data: {'SwitchON': False, 'PulseTide': False, 'FeedSwitch': True, 'TimerON': False, 'Mode': '经典造浪', 'Linkage': '独立', 'Flow': 90, 'Frequency': 87, 'FeedTime': 40}
2024-09-11 10:01:28.767 DEBUG (MainThread) [custom_components.jebao_aqua] Coordinator ran _async_update_data and updated device data: {'did': 'xECYiFFqUCbEqhYT657wmZ', 'attr': {'SwitchON': False, 'PulseTide': False, 'FeedSwitch': True, 'TimerON': False, 'Mode': '经典造浪', 'Linkage': '独立', 'Flow': 90, 'Frequency': 87, 'FeedTime': 40}}
2024-09-11 10:01:28.767 DEBUG (MainThread) [custom_components.jebao_aqua] Finished fetching jebao_aqua data in 0.129 seconds (success: True)
2024-09-11 10:01:28.993 WARNING (MainThread) [custom_components.localtuya.common] Missing device configuration for device_id ebf1a770732ea1027el7nm
2024-09-11 10:01:28.993 WARNING (MainThread) [custom_components.localtuya.common] Missing device configuration for device_id ebf1a770732ea1027el7nm
2024-09-11 10:01:28.994 WARNING (MainThread) [custom_components.localtuya.common] Missing device configuration for device_id ebf1a770732ea1027el7nm
2024-09-11 10:01:28.994 WARNING (MainThread) [custom_components.localtuya.common] Missing device configuration for device_id ebf1a770732ea1027el7nm

Is it use the different encoding from the 1d8c63eaccac4205b92c84d77d5a08fb Wave pump?

chrisc123 commented 1 day ago

Try again have just updated api.py and it seems OK on my MLW pumps now - somehow I didn't properly test the update yesterday!

noobookbig commented 1 day ago

The last update was fix it. It's working.

Try again have just updated api.py and it seems OK on my MLW pumps now - somehow I didn't properly test the update yesterday!

Result This is MDP Pump image This is MLW Pump image