def start(): adapter = get_provider().get_adapter() q = Queue() observer = Observer(adapter) observer.on_advertising_data = q.put # Put advertisement to queue observer.start() return (observer, q)
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 start_listen_ble(): try: adapter = get_provider().get_adapter() global receiver_mac receiver_mac = adapter.get_device_info().address.address observer = Observer(adapter) observer.on_advertising_data = on_advertisement observer.start() except OSError: print( "Error listening for BLE advertisements, using fixed test data instead" ) start_send_test_data()
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()
def __init__(self, publisher, logger, params, sensors, actuators): """Initializes the listener and kicks off the listening""" self.logger = logger self.dest_root = params("Destination") self.publish = publisher self.logger.info( '----------Configuring Govee listener with destination {}'.format( self.dest_root)) self.GOVEE_BT_MAC_PREFIX = "A4:C1:38" self.H5075_UPDATE_UUID16 = UUID16(0xEC88) self.adapter = get_provider().get_adapter() self.observer = Observer(self.adapter) self.observer.on_advertising_data = self.on_advertisement self.observer.start() self.poll = -1 self.devices = {}
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(bt_device=''): ''' Attributes: device (string): BLE device (default 0) ''' if not bt_device: bt_device = 0 else: # Old communication used hci0 etc. bt_device = bt_device.replace('hci', '') log.info('Start receiving broadcasts (device %s)', bt_device) q = Queue() adapter = get_provider().get_adapter(int(bt_device)) observer = Observer(adapter) observer.on_advertising_data = q.put observer.start() return (observer, q)
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'})
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()
#!/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()
def run_observer(): with Observer(get_provider().get_adapter(), lambda advertisement_report: print(advertisement_report)): sleep(5)
#!/usr/bin/env python3 import sys from time import sleep from bleson import get_provider, Observer from bleson.logger import log, set_level, DEBUG #set_level(DEBUG) # 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 with Observer(get_provider().get_adapter(), lambda device: log.info(device)): sleep(WAIT_TIME)
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
org=_influx_config["org"], enable_gzip=True, verify_ssl=True, ) _write_client = _influx_client.write_api(write_options=WriteOptions( flush_interval=15_000, max_retries=1, max_retry_delay=10_000)) _mac_list = [bytes.fromhex(x.replace(":", "")) for x in _config["macs"]] _measurements = Subject() thread_pool_scheduler = ThreadPoolScheduler(2) _measurements_subj = _measurements.pipe( ops.observe_on(thread_pool_scheduler)) # _measurements_subj.subscribe(on_next=lambda x: print(x, flush=True)) _write_client.write( bucket="sensors", record=_measurements_subj.pipe(ops.map(_ruuvi_data_to_influx)), ) def on_advertisement(advertisement): msg = RuuviTagData.from_mfg_data(advertisement.mfg_data, _mac_list) if msg is not None: _measurements.on_next(msg) observer = Observer(get_provider().get_adapter()) observer.on_advertising_data = on_advertisement observer.start() while True: sleep(10)
class goveeSensor: """Listens for Govee temp/humi sensor BT broadcasts and publishes them.""" def __init__(self, publisher, logger, params, sensors, actuators): """Initializes the listener and kicks off the listening""" self.logger = logger self.dest_root = params("Destination") self.publish = publisher self.logger.info( '----------Configuring Govee listener with destination {}'.format( self.dest_root)) self.GOVEE_BT_MAC_PREFIX = "A4:C1:38" self.H5075_UPDATE_UUID16 = UUID16(0xEC88) self.adapter = get_provider().get_adapter() self.observer = Observer(self.adapter) self.observer.on_advertising_data = self.on_advertisement self.observer.start() self.poll = -1 self.devices = {} def on_advertisement(self, advertisement): self.logger.debug("Received advertisement from {}".format( advertisement.address.address)) if advertisement.address.address.startswith(self.GOVEE_BT_MAC_PREFIX): self.logger.debug("Received Govee advertisement") mac = advertisement.address.address if self.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] = name encoded_data = int(advertisement.mfg_data.hex()[6:12], 16) battery = int(advertisement.mfg_data.hex()[12:14], 16) temp_c = format((encoded_data / 10000), ".2f") temp_f = format((((encoded_data / 10000) * 1.8) + 32), ".2f") humi = format(((encoded_data % 1000) / 10), ".2f") self.logger.debug( "Govee data to publish: name = {}, " "battery = {}, temp_c = {}, temp_f = {}, and " "humi = {}".format(name, battery, temp_c, temp_f, humi)) for conn in self.publish: conn.publish(str(battery), "{}/{}/battery".format(self.dest_root, name)) conn.publish(str(temp_c), "{}/{}/temp_C".format(self.dest_root, name)) conn.publish(str(temp_f), "{}/{}/temp_F".format(self.dest_root, name)) conn.publish(str(humi), "{}/{}/humi".format(self.dest_root, name)) if advertisement.rssi is not None and advertisement.rssi != 0: if mac in self.devices: for conn in self.publish: conn.publish( str(advertisement.rssi), "{}/{}/rssi".format(self.dest_root, self.devices[mac])) def checkState(self): """Does nothing""" def publishState(self): """Does nothing""" def cleanup(self): """Stop the observer""" self.logger.info("Stopping Govee observer") self.oberver.stop()
###### Define graceful exit atexit.register(exit_handler) ###### Define output if args.logfile=="" or args.logfile=="stdout": _useStdOut = True else: _useStdOut = False level=set_level(args.loglevel) ###### ibeacon adapter and observers adapter = get_provider().get_adapter(args.hci) observer = Observer(adapter) observer.on_advertising_data = on_advertisement observer.start(True) # filter duplicates ###### Sleep this thread while the observer thread does its magic listentime = args.listentime if listentime == -1: ###### TODO: Service Healthcheck and sleep??? while True: sleep (10) #TODO clean up files. #TODO what other useful things could this thread do else:
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()