Skip to main content

No project description provided

Project description

Crownstone BLE

We're using Bleak as bluetooth backend, which supports Windows, MacOS and Linux.

Since the Crownstone communicates through BLE, we can use BLE to tell it to do things!

This library works with Python 3.7 and higher.

Installing the library

If you want to use python virtual environments, take a look at the README_VENV

We use pip3 in the example below because pip is usually the python 2 client. If you're using virtual environments, it could be that pip3 does not exist there. In that case, use pip.

pip3 install crownstone_ble

You can also build the library from the project itself by:

sudo python3 setup.py install

Async functions

This library uses async methods. This is part of Python and uses the asyncio core module to do this. Async methods must be awaited. If you're unsure about how to use these, there's a million guides and tutorials online. We will assume you know how to use these in the rest of the documentation.

Documentation

To use Crownstone BLE, you first import it from crownstone_ble.

from crownstone_ble import CrownstoneBle

ble = CrownstoneBle(bleAdapterAddress="00:32:FA:DE:15:02")

CrownstoneBle is composed of a number of top level methods and modules for specific commands. We will first describe these top level methods.

__init__(bleAdapterAddress=None)

When initializing the CrownstoneBle class, you can provide an bleAdapterAddress if you're on linux. You can get these addressed by running:

hcitool dev

These addresses are in the "00:32:FA:DE:15:02" format. The constructor is not explicitly called with init, but like this:

ble = CrownstoneBle(bleAdapterAddress="00:32:FA:DE:15:02")

On other platforms you can't currently define which bleAdapter to use.


async isCrownstoneInSetupMode(address: string, scanDuration=3)

This will scan (blocking) for scanDuration. After which it will return True or False, depending if the Crownstone with this address (like "f7:19:a4:ef:ea:f6") is in setup mode or not.


async shutDown()

Shut down the BLE module. This is should be done on closing your script.


setSettings(adminKey: string, memberKey: string, basicKey: string, serviceDataKey: string, localizationKey: string, meshApplicationKey: string, meshNetworkKey: string, referenceId="PythonLib")

The Crownstone uses encryption by default. There are 3 keys used. You can find more information on that in the protocol. These keys are 16 characters long like "adminKeyForCrown" or 32 characters as a hex string like "9332b7abf19b86ff48156d88c687def6". The referenceId is optional. If you know what you're doing, you can disable the encryption but it should never be required.


loadSettingsFromFile(path: string)

As an alternative to using setSettings, you can load it from a json file. The path is relative to the script being executed. An example of this json file is:

{
 "admin":  "adminKeyForCrown",
 "member": "memberKeyForHome",
 "basic":  "basicKeyForOther",
 "serviceDataKey":  "MyServiceDataKey",
 "localizationKey":  "aLocalizationKey",
 "meshApplicationKey":  "MyGoodMeshAppKey",
 "meshNetworkKey":  "MyGoodMeshNetKey",
}

async connect(address: string)

This will connect to the Crownstone with the provided MAC address. You get get this address by scanning or getting the nearest Crownstone. More on this below.


async setupCrownstone(address: string, sphereId: int, crownstoneId: int, meshDeviceKey: string, ibeaconUUID: string, ibeaconMajor: uint16, ibeaconMinor: uint16)

New Crownstones are in setup mode. In this mode they are open to receiving encryption keys. This method facilitates this process. No manual connection is required.

  • address is the MAC address.
  • sphereId is a uint8 id for this Crownstone's sphere (Required for FW 3.0.0+)
  • crownstoneId is a uint8 id for this Crownstone
  • meshDeviceKey is a 16 character string (Required for FW 3.0.0+)
  • ibeaconUUID is a string like "d8b094e7-569c-4bc6-8637-e11ce4221c18"
  • ibeaconMajor is a number between 0 and 65535
  • ibeaconMinor is a number between 0 and 65535

async disconnect()

This will disconnect from the connected Crownstone.


async getCrownstonesByScanning(scanDuration=3)

This will scan for scanDuration in seconds and return an array of the Crownstone it has found. This is an array of dictionaries that look like this:

{
   "address": string,      # mac address like "f7:19:a4:ef:ea:f6"
   "setupMode": boolean,   # is this Crownstone in setup mode?
   "validated": boolean,   # if True, this Crownstone belongs to your Sphere (ie. it can be decrypted by the provided keys).
   "rssi": Float           # average of the rssi of this Crownstone. If None, there have been no valid measurements.
}

This array can be directly put in the 'addressesToExclude' field of the 'getNearest..' methods.


async startScanning(scanDuration=3)

This will start scanning for Crownstones in a background thread. The scanDuration denotes how long we will scan for. Once scanning is active, BleTopics.advertisement events will be triggered with the advertisements of the Crownstones that share our encryption keys or are in setup mode.


async stopScanning()

This will stop an active scan.


async getNearestCrownstone(rssiAtLeast=-100, scanDuration=3, returnFirstAcceptable=False, addressesToExclude=[]) -> ScanData or None

This will search for the nearest Crownstone. It will return ANY Crownstone, not just the ones sharing our encryption keys.

  • rssiAtLeast, you can use this to indicate a maximum distance
  • scanDuration, the amount of time we scan (in seconds)
  • returnFirstAcceptable, if this is True, we return on the first Crownstone in the rssiAtLeast range. If it is False, we will scan for the timeout duration and return the closest one.
  • addressesToExclude, this is an array of either address strings (like "f7:19:a4:ef:ea:f6") or an array of dictionaries that each contain an address field (like what you get from "getCrownstonesByScanning").

If anything was found, the ScanData will be returned. This datatype is defined here.


async getNearestValidatedCrownstone(rssiAtLeast=-100, scanDuration=3, returnFirstAcceptable=False, addressesToExclude=[]) -> ScanData or None

Same as getNearestCrownstone but will only search for Crownstones with the same encryption keys. If anything was found, the ScanData will be returned. This datatype is defined here.


async getNearestSetupCrownstone(rssiAtLeast=-100, scanDuration=3, returnFirstAcceptable=False, addressesToExclude=[]) -> ScanData or None

Same as getNearestCrownstone but will only search for Crownstones in setup mode. If anything was found, the ScanData will be returned. This datatype is defined here.

Control Module

The modules contain groups of methods. You can access them like this:

import asyncio
from crownstone_ble import CrownstoneBle

# initialize the Bluetooth Core
ble = CrownstoneBle()

async def example():
    # set the switch stat eusing the control module
    await ble.connect(address) # address is a mac address (or handle on OSX)
    await ble.control.setSwitch(0)
    await ble.disconnect()

loop = asyncio.get_event_loop()
loop.run_until_complete(example())

Methods:

async setSwitch(switchVal: int)

You can switch the Crownstone. 0 for off, 100 for on, between 0 and 100 to dim. There are also special values to be found in SwitchValSpecial. If you want to dim, make sure dimming is enabled. You can enable this using the allowDimming method.

async commandFactoryReset()

Assuming you have the encryption keys, you can use this method to put the Crownstone back into setup mode.

async allowDimming(allow: bool)

Enable or disable dimming on this Crownstone. Required if you want to dim with setSwitchState.

async disconnect()

Tell the Crownstone to disconnect from you. This can help if your Bluetooth stack does not reliably disconnect.

async lockSwitch(lock: bool)

Lock the switch. If locked, it's switchState cannot be changed.

async reset()

Restart the Crownstone.


async setRelay(turnOn: bool)

DEVELOPMENT ONLY: you can switch the relay. True for on, False for off. Use the setSwitch instead.

async setDimmer(intensity)

DEVELOPMENT ONLY: you can switch the IGBTs. 0 for off, 100 for on, in between for dimming. Use the setSwitch instead.

State Module

This is used to get state variables from the Crownstone. [https://github.com/crownstone/bluenet/blob/master/docs/PROTOCOL.md#state-packet-1]

The modules contain groups of methods. You can access them like this:

import asyncio
from crownstone_ble import CrownstoneBle

# initialize the Bluetooth Core
ble = CrownstoneBle()

async def example():
    # set the switch state using the control module
    await ble.connect(address)
    switchstate = await ble.state.getSwitchState()
    await ble.disconnect()

loop = asyncio.get_event_loop()
loop.run_until_complete(example())

async getSwitchState()

Get the switch state as SwitchState class.

async getTime()

Get the time on the Crownstone as a timestamp since epoch in seconds. This has been corrected for location.

EventBus

API

once(TopicName: string, functionPointer)

This will subscribe for a single event. After this event, the listener will be removed automatically. It still returns a unsubscriptionId if you want to cleanup before the event occurs.

subscribe(TopicName: string, functionPointer)

Returns a subscription ID that can be used to unsubscribe again with the unsubscribe method

unsubscribe(subscriptionId: number)

This will stop the invocation of the function you provided in the subscribe method, unsubscribing you from the event.

Events

These events are available for the BLE part of this lib:

BleTopics.newDataAvailable

This is a topic to which events are posted which are unique. The same message will be repeated on the advertisement and the rawAdvertisement packets.

BleTopics.rawAdvertisement

This topic will broadcast all incoming Crownstone scans, including those that do not belong to your sphere (ie. can't be decrypted with your keys).

BleTopics.advertisement

This topic will broadcast all incoming Crownstone scans which belong to your sphere (ie. which can be decrypted with your keys).

Data format

All these events contain the same data format:

class ScanData:

    def __init__(self):
        self.address       = None    # this is the handle of the device that broadcast the advertisement. This is usually a MAC address, but on OSX it is a handle.
        self.rssi          = None    # the signal strength indicator
        self.name          = None    # name of the device
        self.operationMode = None    # CrownstoneOperationMode enum (SETUP, NORMAL, DFU, UNKNOWN)
        self.serviceUUID   = None    # the UUID of the scanned service
        self.deviceType    = None    # type of Crownstone 
        self.payload       = None    # See below.
        self.validated     = None    # Whether your provided keys could decrypt this advertisement

These fields are always filled. The payload will differ depending on what sort of data is advertised. You can see all possible types here. These payloads all have a type field which is defined here. Payloads come in these flavours:

Usage

You can obtain the eventBus directly from the lib:

from crownstone_ble import BleEventBus, BleTopics

# simple example function to print the data you receive
def showNewData(data):
	print("received new data: ", data)

# Set up event listeners
subscriptionId = BleEventBus.subscribe(BleTopics.newDataAvailable, showNewData)

# unsubscribe again
BleEventBus.unsubscribe(subscriptionId)

Bluetooth on Linux

If bluetooth seems stuck, try sudo rfkill block bluetooth sudo rfkill unblock bluetooth

running

Something about threading when setup is complete --you don't have Python 3.5

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crownstone-ble-2.0.0.tar.gz (24.3 kB view details)

Uploaded Source

Built Distribution

crownstone_ble-2.0.0-py3-none-any.whl (27.3 kB view details)

Uploaded Python 3

File details

Details for the file crownstone-ble-2.0.0.tar.gz.

File metadata

  • Download URL: crownstone-ble-2.0.0.tar.gz
  • Upload date:
  • Size: 24.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.9.2

File hashes

Hashes for crownstone-ble-2.0.0.tar.gz
Algorithm Hash digest
SHA256 695123fb07fee71a6666f50306af48354b7ad9a7184c2241b70248879cbebeb8
MD5 aed250f3ffdc343bf887714204d70993
BLAKE2b-256 8a0f42a03419a65881035e90f5912cd7fa486303392cc323a4421c70534be0d4

See more details on using hashes here.

File details

Details for the file crownstone_ble-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: crownstone_ble-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 27.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.9.2

File hashes

Hashes for crownstone_ble-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f7e5b2a1a6ce7eb61fc508f1545f8985dd0f7c6155054c85f925e9e2f3f21e5
MD5 54125c235f645f0dbe71876dec185db0
BLAKE2b-256 ca62fe3c8d8b70ccbed071363277d0559e275589b3b4e85b72f6491ca8be6ae0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page