Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request - Support for Meter Pro #251

Closed
bobbinz opened this issue Sep 30, 2024 · 21 comments · Fixed by #260
Closed

Feature Request - Support for Meter Pro #251

bobbinz opened this issue Sep 30, 2024 · 21 comments · Fixed by #260

Comments

@bobbinz
Copy link

bobbinz commented Sep 30, 2024

Hi,

I just got a meter pro and was hoping to get it added to Home Assistant via Bluetooth.

Happy to help as I have the device now!

Thanks,
Adam

@talormanda
Copy link

I have the Meter Pro and the Meter Pro (CO2). Not sure what I can do to help, but I am free for anything. I am just unsure how polling bluetooth to grab the necessary data works. If someone could explain, I am willing to try.

@Mar1usW3
Copy link

Would be great to have the meter pro (co2) in HA. Can also provide information.

@talormanda
Copy link

talormanda commented Oct 22, 2024

Advertisement data. MAC is B0:E9:FE:54:32:15

{
          "name": "WoTHPc",
          "address": "B0:E9:FE:54:32:15",
          "rssi": -54,
          "manufacturer_data": {
            "2409": {
              "__type": "<class 'bytes'>",
              "repr": "b'\\xb0\\xe9\\xfeT2\\x15\\xb7\\xe4\\x07\\x9b\\xa4\\x007\\x02\\xd5\\x00'"
            }
          },
          "service_data": {
            "0000fd3d-0000-1000-8000-00805f9b34fb": {
              "__type": "<class 'bytes'>",
              "repr": "b'5\\x00d'"
            }
          },
          "service_uuids": [
            "00001800-0000-1000-8000-00805f9b34fb",
            "00001801-0000-1000-8000-00805f9b34fb",
            "0000fd3d-0000-1000-8000-00805f9b34fb",
            "cba20d00-224d-11e6-9fb8-0002a5d5c51b"
          ],
          "source": "00:1A:7D:DA:71:08",
          "advertisement": [
            "WoTHPc",
            {
              "2409": {
                "__type": "<class 'bytes'>",
                "repr": "b'\\xb0\\xe9\\xfeT2\\x15\\xb7\\xe4\\x07\\x9b\\xa4\\x007\\x02\\xd5\\x00'"
              }
            },
            {
              "0000fd3d-0000-1000-8000-00805f9b34fb": {
                "__type": "<class 'bytes'>",
                "repr": "b'5\\x00d'"
              }
            },
            [
              "00001800-0000-1000-8000-00805f9b34fb",
              "00001801-0000-1000-8000-00805f9b34fb",
              "0000fd3d-0000-1000-8000-00805f9b34fb",
              "cba20d00-224d-11e6-9fb8-0002a5d5c51b"
            ],
            null,
            -54,
            [
              "/org/bluez/hci0/dev_B0_E9_FE_54_32_15",
              {
                "Address": "B0:E9:FE:54:32:15",
                "AddressType": "public",
                "Alias": "WoTHPc",
                "Paired": false,
                "Bonded": false,
                "Trusted": false,
                "Blocked": false,
                "LegacyPairing": false,
                "RSSI": -54,
                "Connected": false,
                "UUIDs": [
                  "00001800-0000-1000-8000-00805f9b34fb",
                  "00001801-0000-1000-8000-00805f9b34fb",
                  "0000fd3d-0000-1000-8000-00805f9b34fb",
                  "cba20d00-224d-11e6-9fb8-0002a5d5c51b"
                ],
                "Adapter": "/org/bluez/hci0",
                "ManufacturerData": {
                  "2409": {
                    "__type": "<class 'bytearray'>",
                    "repr": "bytearray(b'\\xb0\\xe9\\xfeT2\\x15\\xb7\\xe4\\x07\\x9b\\xa4\\x007\\x02\\xd5\\x00')"
                  }
                },
                "ServicesResolved": false,
                "AdvertisingFlags": {
                  "__type": "<class 'bytearray'>",
                  "repr": "bytearray(b'\\x06')"
                },
                "ServiceData": {
                  "0000fd3d-0000-1000-8000-00805f9b34fb": {
                    "__type": "<class 'bytearray'>",
                    "repr": "bytearray(b'5\\x00d')"
                  }
                },
                "Name": "WoTHPc"
              }
            ]
          ],
          "device": {
            "__type": "<class 'bleak.backends.device.BLEDevice'>",
            "repr": "BLEDevice(B0:E9:FE:54:32:15, WoTHPc)"
          },
          "connectable": true,
          "time": 243335.865268782,
          "tx_power": null
        }
		
{
              "name": "WoTHPc",
              "address": "B0:E9:FE:54:32:15",
              "rssi": -54,
              "advertisement_data": [
                "WoTHPc",
                {
                  "2409": {
                    "__type": "<class 'bytes'>",
                    "repr": "b'\\xb0\\xe9\\xfeT2\\x15\\xb7\\xe4\\x07\\x9b\\xa4\\x007\\x02\\xd5\\x00'"
                  }
                },
                {
                  "0000fd3d-0000-1000-8000-00805f9b34fb": {
                    "__type": "<class 'bytes'>",
                    "repr": "b'5\\x00d'"
                  }
                },
                [
                  "00001800-0000-1000-8000-00805f9b34fb",
                  "00001801-0000-1000-8000-00805f9b34fb",
                  "0000fd3d-0000-1000-8000-00805f9b34fb",
                  "cba20d00-224d-11e6-9fb8-0002a5d5c51b"
                ],
                null,
                -54,
                [
                  "/org/bluez/hci0/dev_B0_E9_FE_54_32_15",
                  {
                    "Address": "B0:E9:FE:54:32:15",
                    "AddressType": "public",
                    "Alias": "WoTHPc",
                    "Paired": false,
                    "Bonded": false,
                    "Trusted": false,
                    "Blocked": false,
                    "LegacyPairing": false,
                    "RSSI": -54,
                    "Connected": false,
                    "UUIDs": [
                      "00001800-0000-1000-8000-00805f9b34fb",
                      "00001801-0000-1000-8000-00805f9b34fb",
                      "0000fd3d-0000-1000-8000-00805f9b34fb",
                      "cba20d00-224d-11e6-9fb8-0002a5d5c51b"
                    ],
                    "Adapter": "/org/bluez/hci0",
                    "ManufacturerData": {
                      "2409": {
                        "__type": "<class 'bytearray'>",
                        "repr": "bytearray(b'\\xb0\\xe9\\xfeT2\\x15\\xb7\\xe4\\x07\\x9b\\xa4\\x007\\x02\\xd5\\x00')"
                      }
                    },
                    "ServicesResolved": false,
                    "AdvertisingFlags": {
                      "__type": "<class 'bytearray'>",
                      "repr": "bytearray(b'\\x06')"
                    },
                    "ServiceData": {
                      "0000fd3d-0000-1000-8000-00805f9b34fb": {
                        "__type": "<class 'bytearray'>",
                        "repr": "bytearray(b'5\\x00d')"
                      }
                    },
                    "Name": "WoTHPc"
                  }
                ]
              ],
              "details": {
                "path": "/org/bluez/hci0/dev_B0_E9_FE_54_32_15",
                "props": {
                  "Address": "B0:E9:FE:54:32:15",
                  "AddressType": "public",
                  "Alias": "B0-E9-FE-54-32-15",
                  "Paired": false,
                  "Bonded": false,
                  "Trusted": false,
                  "Blocked": false,
                  "LegacyPairing": false,
                  "RSSI": -39,
                  "Connected": false,
                  "UUIDs": [],
                  "Adapter": "/org/bluez/hci0",
                  "ManufacturerData": {
                    "2409": {
                      "__type": "<class 'bytearray'>",
                      "repr": "bytearray(b'\\xb0\\xe9\\xfeT2\\x15\\xb6\\xe4\\x06\\x9b\\xa5\\x007\\x02\\xd5\\x00')"
                    }
                  },
                  "ServicesResolved": false,
                  "AdvertisingFlags": {
                    "__type": "<class 'bytearray'>",
                    "repr": "bytearray(b'\\x06')"
                  }
                }
              }
            }		

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

That was enough to know the decoding for the temp/humid is the same as the base pro model

I added support for decoding those in #256 so it should show up in the next HA update

I don't know how to decode the co2 data (if its there) although I suspect it is since its 3 bytes longer than the pro model without the c

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

Its likely the CO2 data is in

b'\x007\x02\xd5\x00'

maybe the last 2 bytes?

>>> int.from_bytes(b'\xd5\x00','big')
54528
>>> int.from_bytes(b'\xd5\x00','little')
213

not sure what the device was reading at the time

@talormanda
Copy link

config_entry-bluetooth-e51677d7fc3ffc805c2e11f1b02b2619.json

Here is the entire file, if that helps. In case I missed something important. I am not well versed in what to look for yet.

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

All the data looks like its there. The process to figure out the CO2 sensor value would be to turn on debug logging for homeassistant.components.bluetooth, and record the ManufacturerData field value for each CO2 value as the device reports on the screen new values. Usually I make a spreadsheet with a ManufacturerData and device reported value

# Example configuration.yaml entry
logger:
  default: info
  logs:
    homeassistant.components.bluetooth: debug

Once you have ~20 different values ManufacturerData and screen reading to compare with, that is usually enough to figure out how its encoded. Sometimes you need a lot more if they use partial byte encoding or a mistake is made comparing the ManufacturerData to the value on the screen in the spreadsheet

@talormanda
Copy link

image

  1. Does IMAGE above work the same or do I have to enable it the way you posted?
  2. After enabling, can I just log 20 different changes on the screen, and they will be in order on the debug log?

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

The link in the image should work as well.

You'll need 20 different CO2 values on the screen with the timing the reading lined up to the timestamp in the log

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

Its usually easier to ssh in an tail -f home-assistant.log | grep MAC_ADDRESS_TO_WATCH_FOR

@talormanda
Copy link

I see why you said it's better to do it yourself. I will try. It updates CO2 every 1 minute when plugged in, so this will take some time.

@talormanda
Copy link

If this looks good, I will continue. Here is one sample:

2024-10-22 01:09:36.719 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] hci0 (00:1A:7D:DA:71:08) [connectable]: <BluetoothServiceInfoBleak name=WoTHPc address=B0:E9:FE:54:32:15 rssi=-45 manufacturer_data={2409: b'\xb0\xe9\xfeT2\x15\xd0\xe4\x01\x9b\xa4\x007\x02\xaa\x00'} service_data={'0000fd3d-0000-1000-8000-00805f9b34fb': b'5\x00d'} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fd3d-0000-1000-8000-00805f9b34fb', 'cba20d00-224d-11e6-9fb8-0002a5d5c51b'] source=00:1A:7D:DA:71:08 connectable=True time=249919.469503794 tx_power=None> match: set()

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

That looks like the right data. The goal is to produce something like this... https://dpaste.org/npg3j

CO2 value manufacturer_data
xyz b'\xb0\xe9\xfeT2\x15\xd0\xe4\x01\x9b\xa4\x007\x02\xaa\x00'
xyz b'\xb0\xe9\xfeT2\x15\xd0\xe4\x01\x9b\xa4\x007\x02\xaa\x00'
xyz b'\xb0\xe9\xfeT2\x15\xd0\xe4\x01\x9b\xa4\x007\x02\xaa\x00'

....

@talormanda
Copy link

talormanda commented Oct 22, 2024

I setup a log to capture 20 updates using

tail -f home-assistant.log | grep "B0:E9:FE:54:32:15" | grep "manufacturer_data" | awk '{print NR ": " strftime("%Y-%m-%d %H:%M:%S") ": " $0}' | tee -a switchbotco2.log

Example output:
1: 2024-10-22 01:26:32: 2024-10-22 01:26:32.766 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] hci0 (00:1A:7D:DA:71:08) [connectable]: <BluetoothServiceInfoBleak name=WoTHPc address=B0:E9:FE:54:32:15 rssi=-51 manufacturer_data={2409: b'\xb0\xe9\xfeT2\x15\xe0\xe4\x07\x9a\xa5\x007\x03\x19\x00'} service_data={'0000fd3d-0000-1000-8000-00805f9b34fb': b'5\x00d'} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fd3d-0000-1000-8000-00805f9b34fb', 'cba20d00-224d-11e6-9fb8-0002a5d5c51b'] source=00:1A:7D:DA:71:08 connectable=True time=250935.516698236 tx_power=None> match: set()

Do I need to do anything else special with the timestamp? I figured it can just be logged when the command fires off, no? (other than recording the CO2 value by hand obviously)

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

The timestamps aren't usually important except for making sure you got the hand recorded value correct. I usually note the time when I write down the values and than double check them against the log timestamps later to make sure I didn't get any out of order or incorrect as one wrong one can make it harder to figure out how its encoded as you might miss the pattern

@talormanda
Copy link

The timestamp confuses me.

time=250935.516698236 is this the time since the bluetooth service was started?

@talormanda
Copy link

talormanda commented Oct 22, 2024

CO2 | manufacturer_data
-- | --
645 | b'\xb0\xe9\xfeT2\x15 \xe4\t\x99\xa8\x00#\x02\x85\x00'
1126 | b'\xb0\xe9\xfeT2\x15!\xe4\t\x99\xa5\x00#\x02\x85\x00'
769 | b'\xb0\xe9\xfeT2\x15#\xe4\t\x99\xa5\x00#\x04f '
658 | b'\xb0\xe9\xfeT2\x15%\xe4\t\x99\xa4\x00#\x02\xa1\x00'
636 | b'\xb0\xe9\xfeT2\x15+\xe4\t\x99\xa4\x00#\x02\xaa\x00'
613 | b'\xb0\xe9\xfeT2\x15+\xe4\t\x99\xa4\x00#\x02\xaa\x00'

Got these 6 so far. If it looks okay, I'll get more later on. Taking a break.

@talormanda
Copy link

talormanda commented Oct 22, 2024

When I run:

data = b'\xb0\xe9\xfeT2\x15#\xe4\t\x99\xa5\x00#\x04f '
co2_bytes = data[13:15] 
co2_value = int.from_bytes(co2_bytes, 'big')
print(co2_value)

with the data I pulled at timestamp 255089.206798486, I get a value of 1126, which is the CO2 value I recorded.

@bdraco
Copy link
Member

bdraco commented Oct 22, 2024

home-assistant/core#128991

@saeedesmaili
Copy link

Why my Meter Pro devices are detected as light strips? What should I do to be able to add them properly into HomeAssistant? I'm using the latest version (2024.11.2).
image

@saeedesmaili
Copy link

Ah, I should've asked in the HomeAssistant issues (still would appreciate if anyone knows what I should do).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants