custom-components / sensor.airthings_wave

hassio support for Airthings Wave BLE environmental radon sensor.
MIT License
100 stars 28 forks source link

Get battery status? (feature) #70

Closed montjoy closed 2 years ago

montjoy commented 2 years ago

Hi - thanks so much for making this!

Do you have any plans to report on the battery status? It's something you can view in the official app. It would be nice to be able to see when the batteries are low and send a notification.

sverrham commented 2 years ago

That information is not available on the documented interface I think, if someone knows how to get that info we could implement it. So no not planned.

montjoy commented 2 years ago

Ok thank you. I just thought maybe there was a "standard" bluetooth identifier for battery. Cheers!

sverrham commented 2 years ago

Maybe it is possible, have to test if the endpoint is available some links of relevance https://www.andreasjakl.com/read-battery-level-bluetooth-le-devices/ https://stackoverflow.com/questions/52281070/what-does-battery-level-state-0x2a1b-bluetooth-specification-mean

If I have time I might check this out more...

mstaalesen commented 2 years ago

I've been trying to get the batterystatus for some time now too (manually with bluetoothctl + gatt). I was not successful, but I did stumble across this: https://github.com/Airthings/waveplus-reader/issues/11#issuecomment-929493453

Perhaps that could put you in the right direction?

sverrham commented 2 years ago

I see, that is interesting, seems like it should be kind of stright forward for the pluss model with the command uuid point if write and read to that works as I think... Would need to access this: command_uuid = UUID('b42e2d06-ade7-11e4-89d3-123b93f75cba') # "Access Control Point" Characteristic Send this: struct.pack('<B', 0x6d) Read back and parse as ` d = struct.unpack('<L12B6H', q2['raw'])

q2['ambientlight'] = d[2]
q2['measurement_periods'] =  d[5]
q2['voltage'] = d[17] / 1000.0

V_MAX=3.2
V_MIN=2.2
q2['battery']= max(0, min(100, round( (q2['voltage']-V_MIN)/(V_MAX-V_MIN)*100)))`

ok, maybe I can setup a rpi and test this the comming days...

sverrham commented 2 years ago

I guess not as stright forward, did not get read to work, it uses notifications and I did not get that to work...

Seems I do not get any reply or notification... probably me not getting the setup correctly.

Tried adding delegate:


class MyDelegate(btle.DefaultDelegate):
    def __init__(self):
        btle.DefaultDelegate.__init__(self)
        # ... initialise here

    def handleNotification(self, cHandle, data):
        # ... perhaps check cHandle
        # ... process 'data'
        print(cHandle)
        print(data)

self._dev = btle.Peripheral(mac.lower())
self._dev.withDelegate( MyDelegate() )

Then write to the command uuid and wait:

char.write(struct.pack('<B', 0x6d))
 for i in range(10):
    if self._dev.waitForNotifications(1.0):                                        
       continue

But nothing received, hmm Maybe I need to enable the notification but how to do.

sverrham commented 2 years ago

Got it working I think, needed to add this to get notifications to work:

characteristic_configure_uuid   = btle.UUID('2902')
d, = char.getDescriptors(forUUID=characteristic_configure_uuid)
d.write(struct.pack('<H', 1), True)

Mannaged to get this printout: DEBUG:__main__: Got cmddata {'ambientlight': 0, 'measurement_periods': 36, 'voltage': 2.826, 'battery': 63}

sverrham commented 2 years ago

Updated in fork, seems to be working for me, if someone else wants to test before I make a pull request and release. I have only tested with airthings wave plus device, as that is the only one I have. If it works with other devices or will crash horibly I do not know... would be nice with more testing.

mstaalesen commented 2 years ago

Great work. I will try to test it this afternoon.

MartyTremblay commented 2 years ago

Cool stuff!

Tested and seems to work without breaking my first-gen Wave; but has no battery status of course.

...Time to upgrade my Wave I guess :/

mstaalesen commented 2 years ago

Looking good!

DEBUG:__main__:<redacted> Got cmddata {'ambientlight': 13, 'measurement_periods': 19, 'voltage': 3.261, 'battery': 100}

sverrham commented 2 years ago

Just pushed some updates to handle some bad data that I have seen runing this a couple of days, will let it run some more.

Also I am debating if the battery sensor with % battery should be as it is, since it is derived from the voltage, I am leaning towrads having this calculated on a "higher" level, maybe letting the user set max min values, if I keep it linear as now, but then again might just keep it as it is, will not be "right" either way...

sverrham commented 2 years ago

Ok, I feel more happy with the latest version, now there is one battery sensor that converts from voltage to percentage with user configurable max min values and the voltage is added as an attribute. I think this is a good solution that is more flexible so the user can "tune" the batter percentage levels.

I will lett it run a bit to see if I have any issues, then push this out unless there are any objections or maybe other solutions.

montjoy commented 2 years ago

@sverrham Looks like it works! Thank you so much!

arnerek commented 2 years ago

I set V_MAX to 3.0 and V_MIN to 2.0. Noe The battery reading is consistent with the official Airthings app.