pysk8 package

Submodules

pysk8.constants module

pysk8 constants.

pysk8.constants.DATA_STRUCT

structure for unpacking SK8 IMU data packets

pysk8.constants.MAX_IMUS

maximum number of IMUs attached to any SK8

pysk8.constants.DEF_TIMEOUT

default timeout (seconds) for various operations

pysk8.core module

Core classes for the pysk8 package.

This module contains the core classes for interacting with SK8 Bluetooth Low Energy sensor packs. Currently supported is limited to Windows/OSX/Linux desktop platforms, and requires a Silicon Labs BLED112 USB dongle. A link to a webpage with more information about this dongle can be found here.

class pysk8.core.Dongle

Bases: bgapi.api.BlueGigaCallbacks

Represents a physical BLED112 dongle.

Provides various methods to scan for and connect to one or more SK8 devices

BAUDRATE = 250600

serial port baud rate for the BLED112

DEF_SCAN_INTERVAL = 75

default BLE scan interval, units of 625us

DEF_SCAN_WINDOW = 75

default BLE scan window, units of 625us

PORT_RETRIES = 3

number of attempts to make at opening the serial port

__init__()

Create a Dongle instance (without connecting to the physical device)

begin_scan(callback=None, interval=75, window=75)

Begins a BLE scan and returns immediately.

Using this method you can begin a BLE scan and leave the dongle in scanning mode in the background. It will remain in scanning mode until you call the end_scan() method or the reset() method.

Parameters:
  • callback (callbable) – a callback that will be called for each new device discovered by the scanning process. Will be passed a single argument, a ScanResult object. May be None if not needed.
  • interval (int) – BLE scan interval, in units of 625us
  • window (int) – BLE scan window, in units of 625us
Returns:

True on success, False otherwise.

close()

Closes the connection to the dongle.

Calls reset() and then closes the serial port connection to the dongle.

connect(devicelist, calibration=True)

Establish a connection to one or more SK8 devices.

Given a list of 1 or more ScanResult objects, this method will attempt to create a connection to each SK8 in sequence. It will return when all connections have been attempted, although they may not all have succeeded. In addition, the dongle has a limit on simultaneous connections, which you can retrieve by calling get_supported_connections(). If the number of supplied device names exceeds this value then the method will abort immediately.

Parameters:
  • devicelist (list) – a list of ScanResult instances, one for each SK8 you wish to create a connection to.
  • calibration (bool) – True if calibration data should be loaded post-connection, for each device (if available).
Returns:

tuple (result, devices), where result is a bool indicating if connections were successfully made to all given devices. If True, devices will contain a list of SK8 instances representing the connected SK8 devices. If False, devices will contain a smaller number of SK8 instances depending on the number of connections that succeeded (possibly 0).

connect_direct(device, calibration=True)

Establish a connection to a single SK8.

Parameters:
  • device – either a ScanResult or a plain hardware address string in xx:xx:xx:xx:xx:xx format.
  • calibration (bool) – True to attempt to load calibration data for this device after connection, False otherwise. See SK8.load_calibration().
Returns:

tuple (result, device), where result is a bool indicating if a connection was created successfully. If result is True, device will be set to a new SK8 instance. Otherwise it will be None.

end_scan()

Ends an ongoing BLE scan started by begin_scan().

Returns:a ScanResults object containing the scan results.
static find_dongle_port()

Convenience method which attempts to find the port where a BLED112 dongle is connected.

This relies on the pyserial.tools.list_ports.grep method, and simply searches for a port containing the string “Bluegiga” in its description. (This probably only works on Windows at the moment (TODO)).

Returns:A string containing the detected port address, or None if no matching port was found.
get_connection_interval()

Returns the current BLE connection interval in ms

get_device(n)

Get SK8 instance for a specific connected device.

Retrieves an SK8 object identified by its hardware address.

Parameters:n (str) – device address in xx:xx:xx:xx:xx:xx format
Returns:The SK8 instance matching the supplied address, or None if no matching device exists.
get_device_addresses()

Obtain a list of hardware addresses (hex format) for all connected SK8s.

Returns:list of str, each giving the hardware address of a currently connected SK8 device.
get_devices()

Obtain a list of SK8 objects for all connected SK8s.

Returns:list of SK8 objects, each corresponding to a currently connected SK8 device.
get_slave_latency()

Returns the current BLE slave latency in connection intervals

get_supervision_timeout()

Returns the current BLE supervision timeout in ms

get_supported_connections()

Returns the number of supported simultaneous BLE connections.

The BLED112 is capable of supporting up to 8 simultaneous BLE connections. However, the default firmware image has a limit of just 3 devices, which is a lot easier to run up against. This method retrieves the current value of this setting.

Returns:int. The number of supported simultaneous connections, or -1 on error
init(address, hard_reset=False)

Open the serial connection to a dongle at the supplied address.

Parameters:
  • address (str) – the serial port address of the BLED112 dongle, e.g. ‘COM5’
  • hard_reset (bool) – not currently used
Returns:

True if a connection with the dongle was established, False otherwise.

is_scanning()
reset()

Attempts to reset the dongle to a known state.

When called, this method will reset the internal state of the object, and disconnect any active connections.

scan_and_connect(devnames, timeout=3, calibration=True)

Scan for and then connect to a set of one or more SK8s.

This method is intended to be a simple way to combine the steps of running a BLE scan, checking the results and connecting to one or more devices. When called, a scan is started for a period equal to timeout, and a list of devices is collected. If at any point during the scan all of the supplied devices are detected, the scan will be ended immediately.

After the scan has completed, the method will only proceed to creating connections if the scan results contain all the specified devices.

Parameters:
  • devnames (list) – a list of device names (1 or more)
  • timeout (float) – a time period in seconds to run the scanning process (will be terminated early if all devices in devnames are discovered)
Returns:

Returns the same results as connect().

scan_devices(devnames, timeout=3, interval=75, window=75)

Run a BLE scan for a defined interval and return results.

Alternative to begin_scan/:meth:`end_scan().

Parameters:
  • timeout (float) – time in seconds to run the scanning process for
  • interval (int) – BLE scan interval, in units of 625us
  • window (int) – BLE scan window, in units of 625us
Returns:

a ScanResults object containing the scan results.

set_disconnect_handler(h)

Allows an application to register a callback to receive disconnection events.

An application can pass a callback here to be notified when a connected device is unexpectedly disconnected. The supplied callable should have signature: (dongle(Dongle), sk8(SK8), reason, msg) where reason will be a numeric code indicating the reason for the disconnection, and msg will be a string containing a human readable description.

set_reconnect_parameters(interval, attempts, restore_state=True)

Sets the behaviour of the automatic reconnect feature.

When a connected SK8 is disconnected unexpectedly (in other words not by a user-triggered action), an automatic attempt to reconnect to the device can be made. If successful this will typically resume the connection with an interruption of only a few seconds.

This method allows the application to configure some aspects of the automatic reconnect functionality.

Parameters:
  • interval (float) – time in seconds between successive attempts to reconnect. Also applies to the delay between the initial disconnection and the first attempt to reconnect.
  • attempts (int) – the number of attempts to make to recreate the connection. This can be set to zero in order to disable the reconnection feature.
  • restore_state (bool) – if True, the streaming state of the device will also be restored if possible. For example, the IMU configuration will be re-applied after the reconnection attempt succeeds, to return the SK8 to the same state it was in before the disconnection occurred.
Returns:

None

class pysk8.core.SK8(dongle, conn_handle, devinfo, calibration=True)

Bases: object

Represents a single, currently connected SK8 device.

NOTE: normally you should not create instances of this class manually. Instead, use the methods of the Dongle object to create connections and retrieve the corresponding SK8 objects.

Parameters:
  • dongle – reference to the host Dongle instance.
  • conn_handle (int) – BLED112 connection handle.
  • devinfo – ScanResult for this device, containing address information.
  • calibration (bool) – indicates if calibration data should be loaded (if available)
disable_extana_streaming()

Disable SK8-ExtAna streaming for this device.

Returns:True on success, False if an error occurred.
disable_imu_streaming()

Disable IMU streaming for this device.

Returns:True on success, False if an error occurred.
disconnect()

Disconnect the dongle from this SK8.

Simply closes the active BLE connection to the device represented by the current instance.

Returns:bool. True if connection was closed, False if not (e.g. if already closed).
enable_extana_streaming(include_imu=False, enabled_sensors=7)

Configures and enables sensor data streaming from the SK8-ExtAna device.

By default this will cause the SK8 to only stream data from the analog sensors on the SK8-ExtAna, but if include_imu is set to True, it will also send data from the internal IMU in the SK8.

NOTE: only one streaming mode can be active at any time, so e.g. if you want to stream IMU data normally, you must disable SK8-ExtAna streaming first.

Parameters:
  • include_imu (bool) – If False, only SK8-ExtAna packets will be streamed. If True, the device will also stream data from the SK8’s internal IMU.
  • enabled_sensors (int) – If include_imu is True, this can be used to select which IMU sensors will be active.
Returns:

bool. True if successful, False if an error occurred.

enable_imu_streaming(enabled_imus, enabled_sensors=7)

Configures and enables IMU sensor data streaming.

NOTE: only one streaming mode can be active at any time, so e.g. if you want to stream IMU data, you must disable SK8-ExtAna streaming first.

Parameters:
  • enabled_imus (list) – a list of distinct ints in the range 0-4 inclusive identifying the IMU. 0 is the SK8 itself, and 1-4 are the subsidiary IMUs on the USB chain, starting from the end closest to the SK8.
  • enabled_sensors (int) – to save battery, you can choose to enable some or all of the sensors on each enabled IMU. By default, the accelerometer, magnetometer, and gyroscope are all enabled. Pass a bitwise OR of one or more of SENSOR_ACC, SENSOR_MAG, and SENSOR_GYRO to gain finer control over the active sensors.
Returns:

bool. True if successful, False if an error occurred.

get_battery_level()

Reads the battery level descriptor on the device.

Returns:int. If successful this will be a positive value representing the current battery level as a percentage. On error, -1 is returned.
get_calibration()

Get calibration state for attached IMUs.

Returns:list. A 5-element list of bools indicating if calibrated output is currently enabled or disabled on the IMU with the corresponding index. Note that if calibration is enabled but no calibration file has been loaded, uncalibrated data will still be output!
get_ccc_handle_from_uuid(uuid)

Utility function to retrieve the client characteristic configuration descriptor handle for a given characteristic.

Parameters:uuid (str) – a string containing the hex-encoded UUID
Returns:None if an error occurs, otherwise an integer handle.
get_characteristic_from_uuid(uuid)

Given a characteristic UUID, return a Characteristic object containing information about that characteristic

Parameters:uuid (str) – a string containing the hex-encoded UUID
Returns:None if an error occurs, otherwise a Characteristic object
get_characteristic_handle_from_uuid(uuid)

Given a characteristic UUID, return its handle.

Parameters:uuid (str) – a string containing the hex-encoded UUID
Returns:None if an error occurs, otherwise an integer handle.
get_device_name(cached=True)

Returns the SK8 device BLE name.

Parameters:cached (bool) – if True, returns the locally cached copy of the name. If this is set to False, or the name is not cached, it will read from the device instead.
Returns:str. The current device name. May be None if an error occurs.
get_enabled_imus()

Returns the set of currently enabled IMUs.

This method returns a copy of the list of enabled IMUs as most recently passed to the enable_imu_streaming() method.

Returns:The list will contain ints from 0-4, up to a maximum of 5 entries, and may be empty if no IMUs are enabled.
get_enabled_sensors()

Returns the bitmask indicating the currently active set of IMU sensors.

This method returns a copy of the bitmask of enabled sensors as most recently passed to the enable_imu_streaming() method.

Returns:A combination of the SENSOR_ constants, e.g. SENSOR_ALL, or SENSOR_ACC | SENSOR_GYRO.
get_extana()

Returns a pysk8.extana.ExtAnaData object representing an attach SK8-ExtAna board.

Returns:pysk8.extana.ExtAnaData object.
get_extana_led(cached=True)

Returns the current (R, G, B) colour of the SK8-ExtAna LED.

Parameters:cached (bool) – if True, returns the locally cached state of the LED (based on the last call to set_extana_led()). Otherwise query the device for the current state.
Returns:a 3-tuple (r, g, b) (all unsigned integers) in the range 0-255, or None on error.
get_firmware_version(cached=True)

Returns the SK8 device firmware version.

Parameters:cached (bool) – if True, returns the locally cached copy of the firmware version. If this is set to False, or the version is not cached, it will read from the device instead.
Returns:str. The current firmware version string. May be None if an error occurs.
get_imu(imu_number)

Returns a pysk8.imu.IMUData object representing one of the attached IMUs.

Parameters:imu_number (int) – a value from 0-4 inclusive identifying the IMU. 0 is the SK8 itself, and 1-4 are the subsidiary IMUs on the USB chain, starting from the end closest to the SK8.
Returns:pysk8.imu.IMUData object, or None if an invalid index is supplied.
get_polling_override()

Get the current polling override value in milliseconds.

See set_polling_override() for more information.

Returns:None on error, otherwise the current override period in milliseconds (0 = disabled).
get_received_packets()

Returns number of received data packets.

Returns:int. Number of sensor data packets received either since the connection was established, or since reset_received_packets() was called.
get_service(uuid)

Lookup information about a given GATT service.

Parameters:uuid (str) – a string containing the hex-encoded service UUID
Returns:None if an error occurs, otherwise a Service object.
get_service_for_handle(handle)

Given a characteristic handle, return the Service object that the handle belongs to.

Parameters:handle (int) – the characteristic handle
Returns:None if no service matches the given handle, otherwise a Service object.
has_extana(cached=True)
Can be used to check if an SK8-ExtAna device is currently connected.
NOTE: do not attempt to call while data streaming is active!
Parameters:cached (bool) – if True, use the cached value of the connected hardware state rather than querying the device. Set to False to force a query.
Returns:bool. True if the SK8 currently has an SK8-ExtAna device attached, False otherwise.
has_imus(cached=True)
Can be used to check if an external IMU chain is currently connected.
NOTE: do not attempt to call while data streaming is active!
Parameters:cached (bool) – if True, use the cached value of the connected hardware state rather than querying the device. Set to False to force a query.
Returns:bool. True if the SK8 currently has an IMU chain attached, False otherwise.
load_calibration(calibration_file=None)

Load calibration data for IMU(s) connected to this SK8.

This method attempts to load a set of calibration data from a .ini file produced by the sk8_calibration_gui application (TODO link!).

By default, it will look for a file name “sk8calib.ini” in the current working directory. This can be overridden using the calibration_file parameter.

Parameters:calibration_file (str) – Path to a user-specified calibration file (ini format).
Returns:True if any calibration data was loaded, False if none was. Note that True will be returned even if for example only 1 IMU had any calibration data available.
pp_services()
Display (somewhat) pretty-printed dump of service, charactertistic
and descriptor information for this device.
Returns:Nothing.
reset_received_packets()

Reset counter tracking received data packets to zero

set_calibration(enabled, imus)

Set calibration state for attached IMUs.

Parameters:
  • enabled (bool) – True to apply calibration to IMU data (if available).
  • to output uncalibrated data. (False) –
  • imus (list) – indicates which IMUs the calibration state should be set on.
  • list or [0, 1, 2, 3, 4] will apply to all IMUs, [0, 1] only to (Empty) –
  • 2 IMUs, etc. (first) –
set_device_name(new_name)

Sets a new BLE device name for this SK8.

Parameters:new_name (str) – the new device name as an ASCII string, max 20 characters.
Returns:True if the name was updated successfully, False otherwise.
set_extana_callback(callback, data=None)

Register a callback for incoming data packets from the SK8-ExtAna board.

This method allows you to pass in a callable which will be called on receipt of each packet sent from the SK8-ExtAna board. Set to None to disable it again.

Parameters:
  • callback
    a callable with the following signature:
    (ana1, ana2, temp, seq, timestamp, data)
    where:
    ana1, ana2 = current values of the two analogue inputs temp = temperature sensor reading seq = packet sequence number (int, 0-255) timestamp = value of time.time() when packet received data = value of data parameter passed to this method
  • data – an optional arbitrary object that will be passed as a parameter to the callback
set_extana_led(r, g, b, check_state=True)

Update the colour of the RGB LED on the SK8-ExtAna board.

Parameters:
  • r (int) – red channel, 0-255
  • g (int) – green channel, 0-255
  • b (int) – blue channel, 0-255
  • check_state (bool) – if True (default) and the locally cached LED state matches the given (r, g, b) triplet, pysk8 will NOT send any LED update command to the SK8. If you want to force the command to be sent even if the local state matches the new colour, set this to False.
Returns:

True on success, False if an error occurred.

set_imu_callback(callback, data=None)

Register a callback for incoming IMU data packets.

This method allows you to pass in a callbable which will be called on receipt of each IMU data packet sent by this SK8 device. Set to None to disable it again.

Parameters:
  • callback
    a callable with the following signature:
    (acc, gyro, mag, imu_index, seq, timestamp, data)
    where:
    acc, gyro, mag = sensor data ([x,y,z] in each case) imu_index = originating IMU number (int, 0-4) seq = packet sequence number (int, 0-255) timestamp = value of time.time() when packet received data = value of data parameter passed to this method
  • data – an optional arbitrary object that will be passed as a parameter to the callback
set_polling_override(override)

Set the sensor polling timer override value in milliseconds.

Due to the time it takes to poll all the sensors on up to 5 IMUs, it’s not possible for the SK8 firmware to define a single fixed rate for reading new samples without it being artificially low for most configurations.

Instead the firmware tries to define a sensible default value for each combination of IMUs and sensors that can be enabled (any combination of 1-5 IMUs and 1-3 sensors on each IMU). In most cases this should work well, but for example if you have multiple SK8s connected through the same dongle and have multiple IMUs enabled on each, you may find packets start to be dropped quite frequently.

To mitigate this, you can adjust the period of the timer used by the firmware to poll for new sensor data (and send data packets to the host device). The value should be in integer milliseconds, and have a minimum value of 20. Values below 20 will be treated as a request to disable the override and return to the default polling period.

The method can be called before or after streaming is activated, and will take effect immediately.

NOTE1: the value is stored in RAM and will not persist across reboots, although
it should persist for multiple connections.
NOTE2: once set, the override applies to ALL sensor configurations, so for
example if you set it while using 5 IMUs on 2 SK8s, then switch to using 1 IMU on each SK8, you will probably want to disable it again as the latter configuration should work fine with the default period.
Parameters:override (int) – polling timer override period in milliseconds. Values below 20 are treated as 0, and have the effect of disabling the override in favour of the default periods.
Returns:True on success, False on error.
class pysk8.core.ScanResult(addr, raw_addr, name=None, rssi=0)

Bases: object

An individual result from a BLE scan process for a particular device

addr

Device hardware address in xx:xx:xx:xx:xx:xx format.

Type:str
raw_addr

Device hardware address as raw bytes.

Type:bytearray
name

Device name (if available) as ASCII text.

Type:str
rssi

Latest RSSI from the scan result for the device, if any.

Type:float
__init__(addr, raw_addr, name=None, rssi=0)

Initialise a new ScanResult.

Parameters:
  • addr (str) – Device hardware address in xx:xx:xx:xx:xx:xx format.
  • raw_addr (bytearray) – Device hardware address as raw bytes.
  • name (str) – Device name (if available) as ASCII text.
  • rssi (float) – Latest RSSI from the scan result for the device, if any.
age

Returns the “age” of the ScanResult.

Simply returns the time (in seconds) since this ScanResult was created or updated.

update(name, rssi)

Update the device name and/or RSSI.

During an ongoing scan, multiple records from the same device can be received during the scan. Each time that happens this method is called to update the name and/or rssi attributes.

class pysk8.core.ScanResults

Bases: object

Collection of results from a BLE device scan.

Provides methods to manage and query a set of results from an ongoing or completed BLE scan.

clear()

Clear all device information.

found(ids)

Utility method to check if a set of devices are contained in the result set.

Parameters:ids (list) – a list of device addresses in xx:xx:xx:xx:xx:xx format.
Returns:True if all supplied devices exist in the result set, False otherwise.
get()

Returns the raw dict containing the scan result data.

Returns:A standard Python dictionary. Keys are device addresses in xx:xx:xx:xx:xx:xx format, values are ScanResult objects.
get_device(addr_or_name)

Retrieve a device with a given address or name from the results.

Parameters:addr_or_name (str) – a string containing either a BLE address in xx:xx:xx:xx:xx:xx format, or a plain device name. The supplied value is checked as an address first and if that fails to produce a result, it is matched against each named device in the collection.
Returns:The first matching ScanResult instance, or None.
update(addr, raw_addr, name=None, rssi=None)

Updates the collection of results with a newly received scan response.

Parameters:
  • addr (str) – Device hardware address in xx:xx:xx:xx:xx:xx format.
  • raw_addr (bytearray) – Device hardware address as raw bytes.
  • name (str) – Device name (if available) as ASCII text. May be None.
  • rssi (float) – Latest RSSI from the scan result for the device. May be 0.
Returns:

True if an existing device was updated, False if a new entry was created.

pysk8.discovery module

class pysk8.discovery.Characteristic(handle, value)

Bases: object

Represents a BLE characteristic within a service

add_descriptor(handle, raw_uuid, uuid)
can_notify()
can_read()
can_write()
get_descriptor_by_uuid(uuid)
pp(baseindent=1)
pp_properties()
class pysk8.discovery.Descriptor(handle, raw_uuid, uuid)

Bases: object

Represents a BLE descriptor within a characteristic

pp(baseindent=2)
class pysk8.discovery.Service(start_handle, end_handle, uuid)

Bases: object

Represents a BLE service

add_characteristic(handle, value)
get_characteristic_by_handle(handle)
get_characteristic_by_uuid(uuid)
pp()

pysk8.imu module

class pysk8.imu.IMUData(index, calibration_data=None)

Bases: object

Instances of this class provide access to sensor data from individual IMUs.

acc

latest accelerometer readings, [x, y, z]

Type:list
mag

latest magnetometer readings, [x, y, z]

Type:list
acc

latest gyroscope readings, [x, y, z]

Type:list
seq

sequence number from most recent packet (0-255 range)

Type:int
timestamp

value of time.time() when packet received

Type:float
PACKET_PERIOD = 3
get_packets_lost()
get_sample_rate()
get_total_packets_lost()
reset()

pysk8.util module

pysk8.util.fmt_addr(addr)

Format a Bluetooth hardware address as a hex string.

Parameters:addr (bytes) – raw Bluetooth address in dongle format.
Returns:str. Address in xx – xx:xx:xx:xx:xx format.
pysk8.util.fmt_addr_raw(addr, reverse=True)

Given a string containing a xx:xx:xx:xx:xx:xx address, return as a byte sequence.

Parameters:
  • addr (str) – Bluetooth address in xx:xx:xx:xx:xx:xx format.
  • reverse (bool) – True if the byte ordering should be reversed in the output.
Returns:

A bytearray containing the converted address.

pysk8.util.pp_hex(raw, reverse=True)

Return a pretty-printed (hex style) version of a binary string.

Parameters:
  • raw (bytes) – any sequence of bytes
  • reverse (bool) – True if output should be in reverse order.
Returns:

Hex string corresponding to input byte sequence.

Module contents

pysk8.setLoglevel(lvl=30)

Shortcut method to set pysk8.core loglevel

Parameters:lvl (int) – a standard level enum from the logging module
Returns:nothing