示例#1
0
def sensor_data(json):

    print('sensor message:', json)
    if(json['sensorStatus'] == 'True'):
        adapter = get_provider().get_adapter()

        observer = Observer(adapter)
        observer.on_advertising_data = on_advertisement
        observer.start()
        time.sleep(5)
        observer.stop()
        emit('tempHumSensorUpdate', govee_devices)
    else:
        emit('tempHumSensorUpdate', {'data': 'data disabled'})
示例#2
0
class Observer(object):
    '''
    '''
    def __init__(self, url="https://thu-band.org"):
        self.adapter = get_provider().get_adapter()

        self.observer = OB(self.adapter)
        self.observer.on_advertising_data = self.on_advertisement

    def print_eddystone_values(self, data):
        """
        :param data:
        :return:
        """
        expected_keys = {'name space': 'hex_format',
                         'instance': 'hex_format',
                         'url': 'string_format',
                         'mac address': 'string_format',
                         'tx_power': 'int_format',
                         'rssi': 'int_format'}
        endian = 'big'

        print('New Eddystone data:')
        for prop in data:
            if prop in expected_keys:
                if expected_keys[prop] == 'string_format':
                    print('\t{} = {}'.format(prop, data[prop]))
                if expected_keys[prop] == 'hex_format':
                    print('\t{} = 0x{:X}'.format(prop,
                                                 int.from_bytes(data[prop],
                                                                endian)))
                if expected_keys[prop] == 'int_format':
                    print('\t{} = {}'.format(prop, int(data[prop])))

    def on_advertisement(self, advertisement):
        if (check_prefix("https://thu-band.org")):
            print(advertisement)
            # self.print_eddystone_values(advertisement.mfg_data)

    def start(self):
        self.observer.start()
        # observer.scan_eddystone(on_data=self.print_eddystone_values)

    def stop(self):
        self.observer.stop()
示例#3
0
class BlesonClient(BluetoothAdaptor):
    '''Bluetooth LE communication with Bleson'''
    def handle_callback(self, advertisement):

        if not advertisement.mfg_data:
            return

        processed_data = {
            # WARNING, Apple sucks, so it does not provide mac address
            # in the advertisement! Go tell them that they suck!
            # https://forums.developer.apple.com/thread/8442
            "address":
            advertisement.address.address
            if advertisement.address != None else None,
            # Linux returns bytearray for mfg_data, but mac os returns _NSInlineData
            # which casts to byte array. We need to explicitly cast it to use hex
            "raw_data":
            bytearray(advertisement.mfg_data).hex(),
            "tx_power":
            advertisement.tx_pwr_lvl,
            "rssi":
            advertisement.rssi,
            "name":
            advertisement.name,
        }

        if processed_data["raw_data"][0:2] != 'FF':
            processed_data["raw_data"] = 'FF' + processed_data["raw_data"]

        self.callback(processed_data)

    def __init__(self, callback, bt_device=''):
        '''
        Arguments:
           callback: Function that receives the data from BLE
           device (string): BLE device (default 0)
        '''
        super().__init__(callback, bt_device)

        self.observer = None

        if not bt_device:
            bt_device = 0
        else:
            # Old communication used hci0 etc.
            bt_device = bt_device.replace('hci', '')

        log.info('Observing broadcasts (device %s)', bt_device)

        adapter = get_provider().get_adapter(int(bt_device))
        self.observer = Observer(adapter)
        self.observer.on_advertising_data = self.handle_callback

    def start(self):
        if not self.observer:
            log.info('Cannot start a client that has not been setup')
            return
        self.observer.start()

    def stop(self):
        self.observer.stop()
示例#4
0
#!/usr/bin/env python3

import sys
from time import sleep
from bleson import get_provider, Observer

# Get the wait time from the first script argument or default it to 10 seconds
WAIT_TIME = int(sys.argv[1]) if len(sys.argv) > 1 else 10


def on_advertisement(advertisement):
    print(advertisement)


adapter = get_provider().get_adapter()

observer = Observer(adapter)
observer.on_advertising_data = on_advertisement

observer.start()
sleep(WAIT_TIME)
observer.stop()
示例#5
0
class GoveeSensor(Sensor):
    """Listens for Govee temp/humi sensor BTLE broadcases and publishes them."""
    def __init__(self, publishers, params):
        """Initializes the listener and kicks off the listening thread."""
        super().__init__(publishers, params)

        self.dest_root = params("Destination")

        self.log.info("Configuring Govee listener with destination %s",
                      self.dest_root)

        self.adapter = get_provider().get_adapter()
        self.observer = Observer(self.adapter)
        self.observer.on_advertising_data = self.on_advertisement
        self.observer.start()

        # Store readings so they can be reported on demand.
        self.devices = {}

    def on_advertisement(self, advertisement):
        """Called when a BTLE advertisement is received. If it goes with one
        of the Govee H5075 sensors, the reading is parsed and published."""
        self.log.debug("Received advertisement from %s",
                       advertisement.address.address)

        if advertisement.address.address.startswith(GOVEE_BT_MAC_PREFIX):
            self.log.debug("Received Govee advertisement")

            mac = advertisement.address.address

            # Process a sensor reading.
            if H5075_UPDATE_UUID16 in advertisement.uuid16s:
                split = advertisement.name.split("'")

                name = split[0] if len(split) == 1 else split[1]
                if mac not in self.devices:
                    self.devices[mac] = {}
                    self.devices[mac]["name"] = name

                encoded_data = int(advertisement.mfg_data.hex()[6:12], 16)
                self.devices[mac]["battery"] = int(
                    advertisement.mfg_data.hex()[12:14], 16)
                self.devices[mac]["temp_c"] = format((encoded_data / 10000),
                                                     ".2f")
                self.devices[mac]["temp_f"] = format(
                    (((encoded_data / 10000) * 1.8) + 32), ".2f")
                self.devices[mac]["humi"] = format(
                    ((encoded_data % 1000) / 10), ".2f")

                self.log.debug("Govee data to publish: %s", self.devices)
                self.publish_state()

            # Process an rssi reading. Don't bother to publish now, wait for the
            # next sensor reading.
            if advertisement.rssi is not None and advertisement.rssi != 0:
                # Ignore rssi from devices that haven't reported a sensor
                # reading yet.
                if mac in self.devices:
                    self.devices[mac]["rssi"] = advertisement.rssi

    def publish_state(self):
        """Publishes the most recent of all the readings."""

        for conn in self.publishers:
            for mac in self.devices:
                if "name" in self.devices[mac]:
                    name = self.devices[mac]["name"]
                    dest = "{}/{}".format(self.dest_root, name)
                    for dev in [
                            dev for dev in self.devices[mac] if dev != "name"
                    ]:
                        conn.publish(str(self.devices[mac][dev]),
                                     "{}/{}".format(dest, dev))

    def cleanup(self):
        """Stop the observer."""
        self.log.info("Stopping Govee observer")
        self.observer.stop()