예제 #1
0
def processBLEBeacon(data):
    # While I'm not a fan of globals, not sure how else we can store state here easily
    global opts
    global reload_objects_at
    global tilts
    global uuids

    ev = aiobs.HCI_Event()
    xx = ev.decode(data)

    # To make things easier, let's convert the byte string to a hex string first
    raw_data_hex = ev.raw_data.hex()

    if len(raw_data_hex) < 80:  # Very quick filter to determine if this is a valid Tilt device
        return False
    if "1370f02d74de" not in raw_data_hex:  # Another very quick filter (honestly, might not be faster than just looking at uuid below)
        return False

    # For testing/viewing raw announcements, uncomment the following
    # print("Raw data (hex) {}: {}".format(len(raw_data_hex), raw_data_hex))
    # ev.show(0)

    try:
        # Let's use some of the functions of aioblesscan to tease out the mfg_specific_data payload
        payload = ev.retrieve("Payload for mfg_specific_data")[0].val.hex()

        # ...and then dissect said payload into a UUID, temp, gravity, and rssi (which isn't actually rssi)
        uuid = payload[8:40]
        temp = int.from_bytes(bytes.fromhex(payload[40:44]), byteorder='big')
        gravity = int.from_bytes(bytes.fromhex(payload[44:48]), byteorder='big')
        # tx_pwr = int.from_bytes(bytes.fromhex(payload[48:49]), byteorder='big')
        # rssi = int.from_bytes(bytes.fromhex(payload[49:50]), byteorder='big')
        rssi = 0  # TODO - Fix this
    except:
        return

    if verbose:
        print("Tilt Payload (hex): {}".format(payload))

    color = TiltHydrometer.color_lookup(uuid)  # Map the uuid back to our TiltHydrometer object
    tilts[color].process_decoded_values(gravity, temp, rssi)  # Process the data sent from the Tilt

    # The Fermentrack specific stuff:
    reload = False
    if datetime.datetime.now() > reload_objects_at:
        # Doing this so that as time passes while we're polling objects, we still end up reloading everything
        reload = True
        reload_objects_at = datetime.datetime.now() + datetime.timedelta(seconds=15)

    for this_tilt in tilts:
        if tilts[this_tilt].should_save():
            tilts[this_tilt].save_value_to_fermentrack(verbose=verbose)

        if reload:  # Users editing/changing objects in Fermentrack doesn't signal this process so reload on a timer
            tilts[this_tilt].load_obj_from_fermentrack()
예제 #2
0
def callback(bt_addr, rssi, packet, additional_info):
    # Although beacontools provides a device filter option, we're not going to use it as it doesn't currently allow
    # specifying a list of UUIDs (I don't think, at least). Instead, we'll filter here.
    if additional_info['uuid'] in uuids:
        color = TiltHydrometer.color_lookup(
            additional_info['uuid']
        )  # Map the uuid back to our TiltHydrometer object
        tilts[color].process_ibeacon_info(
            packet, rssi)  # Process the data sent from the Tilt
        if verbose:
            # If we're in 'verbose' mode, also go ahead and print out the data we received
            tilts[color].print_data()
예제 #3
0
def processBLEBeacon(data):
    # While I'm not a fan of globals, not sure how else we can store state here easily
    global verbose
    global reload_objects_at
    global tilts

    ev = aiobs.HCI_Event()
    xx = ev.decode(data)

    # To make things easier, let's convert the byte string to a hex string first
    if ev.raw_data is None:
        if verbose:
            LOG.error("Event has no raw data")
        return False

    raw_data_hex = ev.raw_data.hex()

    if len(
            raw_data_hex
    ) < 80:  # Very quick filter to determine if this is a valid Tilt device
        # if verbose:
        #     LOG.info("Small raw_data_hex: {}".format(raw_data_hex))
        return False
    if "1370f02d74de" not in raw_data_hex:  # Another very quick filter (honestly, might not be faster than just looking at uuid below)
        # if verbose:
        #     LOG.info("Missing key in raw_data_hex: {}".format(raw_data_hex))
        return False

    # For testing/viewing raw announcements, uncomment the following
    # print("Raw data (hex) {}: {}".format(len(raw_data_hex), raw_data_hex))
    # ev.show(0)

    # try:
    #     mac_addr = ev.retrieve("peer")[0].val
    # except:
    #     pass

    try:
        # Let's use some of the functions of aioblesscan to tease out the mfg_specific_data payload

        manufacturer_data = ev.retrieve("Manufacturer Specific Data")
        payload = manufacturer_data[0].payload
        payload = payload[1].val.hex()

        # ...and then dissect said payload into a UUID, temp, and gravity
        uuid = payload[4:36]
        temp = int.from_bytes(bytes.fromhex(payload[36:40]), byteorder='big')
        gravity = int.from_bytes(bytes.fromhex(payload[40:44]),
                                 byteorder='big')
        # On the latest tilts, TX power is used for battery
        tx_pwr = int.from_bytes(bytes.fromhex(payload[44:46]),
                                byteorder='big',
                                signed=False)
        rssi = ev.retrieve("rssi")[-1].val

    except Exception as e:
        LOG.error(e)
        capture_exception(e)
        exit(1)
        return False  # This can't be called, but it's here to make Pycharm happy

    if verbose:
        LOG.info("Tilt Payload (hex): {}".format(raw_data_hex))

    color = TiltHydrometer.color_lookup(
        uuid)  # Map the uuid back to our TiltHydrometer object
    tilts[color].process_decoded_values(
        gravity, temp, rssi, tx_pwr)  # Process the data sent from the Tilt

    if verbose:
        # print("Color {} - MAC {}".format(color, mac_addr))
        print("Raw Data: `{}`".format(raw_data_hex))
        print(
            f"{color} - Temp: {temp}, Gravity: {gravity}, RSSI: {rssi}, TX Pwr: {tx_pwr}"
        )

    # The Fermentrack specific stuff:
    reload = False
    if datetime.datetime.now() > reload_objects_at:
        # Doing this so that as time passes while we're polling objects, we still end up reloading everything
        reload = True
        reload_objects_at = datetime.datetime.now() + datetime.timedelta(
            seconds=30)

    for this_tilt in tilts:
        if tilts[this_tilt].should_save():
            if verbose:
                LOG.info("Saving {} to Fermentrack".format(this_tilt))
            tilts[this_tilt].save_value_to_fermentrack(verbose=verbose)

        if reload:  # Users editing/changing objects in Fermentrack doesn't signal this process so reload on a timer
            if verbose:
                LOG.info("Loading {} from Fermentrack".format(this_tilt))
            tilts[this_tilt].load_obj_from_fermentrack()
예제 #4
0
application = get_wsgi_application()

from gravity.tilt.TiltHydrometer import TiltHydrometer
import gravity.models

# import django.core.exceptions

tilt_monitor_utils.process_monitor_options()

verbose = tilt_monitor_utils.verbose
mydev = tilt_monitor_utils.bluetooth_device

#### The main loop

# Create a list of TiltHydrometer objects for us to use
tilts = {x: TiltHydrometer(x)
         for x in TiltHydrometer.tilt_colors
         }  # type: Dict[str, TiltHydrometer]

# Create the default
reload_objects_at = datetime.datetime.now() + datetime.timedelta(seconds=15)


def processBLEBeacon(data):
    # While I'm not a fan of globals, not sure how else we can store state here easily
    global verbose
    global reload_objects_at
    global tilts

    ev = aiobs.HCI_Event()
    xx = ev.decode(data)
    def centralManager_didDiscoverPeripheral_advertisementData_RSSI_(
            self, manager, peripheral, advertisementData, rssi):

        #is it an iBeacon?
        # print(advertisementData)
        if advertisementData == None:
            return
        # advertisementData is an NSDictionary
        manufacturerData = advertisementData.objectForKey_(
            "kCBAdvDataManufacturerData")
        if manufacturerData == None:
            return

        # see if we have an iBeacon
        if manufacturerData.length() != 25:
            return

        data = manufacturerData.bytes()

        if data[0] != 0x4C or data[1] != 0x00:
            return  # { return nil } // Apple identifier

        if data[2] != 0x02:
            return  #{ return nil } // iBeacon subtype identifier
        if data[3] != 0x15:
            return  # { return nil } // Subtype length (fixed)

        uuid_data = data[4:20]
        # how to better convert bytes to a string?
        uuid = ""
        for i in range(16):
            uuid = uuid + "{0:x}".format(uuid_data[i])

        # is this a tilt?
        color = TiltHydrometer.color_lookup(
            uuid)  # Map the uuid back to our TiltHydrometer object
        if color == None:
            return

        temp = int.from_bytes(data[20:22], byteorder='big')
        gravity = int.from_bytes(data[22:24], byteorder='big')
        transmitPower = int.from_bytes(data[24:2], byteorder='big')

        global tilts
        global reload_objects_at

        tilts[color].process_decoded_values(
            gravity, temp,
            transmitPower)  # Process the data sent from the Tilt

        # This stuff below seems racy..

        # The Fermentrack specific stuff:
        reload = False
        if datetime.datetime.now() > reload_objects_at:
            # Doing this so that as time passes while we're polling objects, we still end up reloading everything
            reload = True
            reload_objects_at = datetime.datetime.now() + datetime.timedelta(
                seconds=30)

        for this_tilt in tilts:
            if tilts[this_tilt].should_save():
                tilts[this_tilt].save_value_to_fermentrack(
                    verbose=tilt_monitor_utils.verbose)

            if reload:  # Users editing/changing objects in Fermentrack doesn't signal this process so reload on a timer
                tilts[this_tilt].load_obj_from_fermentrack()
예제 #6
0
from gravity.tilt.TiltHydrometer import TiltHydrometer
import gravity.models

# import django.core.exceptions

tilt_monitor_utils.process_monitor_options()

verbose = tilt_monitor_utils.verbose
mydev = tilt_monitor_utils.bluetooth_device



#### The main loop

# Create a list of TiltHydrometer objects for us to use
tilts = {x: TiltHydrometer(x) for x in TiltHydrometer.tilt_colors}  # type: Dict[str, TiltHydrometer]

# Create the default
reload_objects_at = datetime.datetime.now() + datetime.timedelta(seconds=15)


def processBLEBeacon(data):
    # While I'm not a fan of globals, not sure how else we can store state here easily
    global verbose
    global reload_objects_at
    global tilts

    ev = aiobs.HCI_Event()
    xx = ev.decode(data)

    # To make things easier, let's convert the byte string to a hex string first