Getting Started with Python Bluetooth Beta SDK
In this tutorial you'll find detailed instructions for getting started with the Python Bluetooth SDK - HMKit. The SDK can be run on openly available Raspberry Pi Zero W, Model 3B and Model 3B+ hardware boards and consists of the package hmkit. The SDK enables your application to work with vehicle data from IOT devices through short range communication (Bluetooth Low Energy).
The Python SDK is in beta and currently works only when using Bluetooth. No production data can be accessed at the moment although testing with the emulator works well.
Introduction and Setup
HMKit requires Python 3.7. Testing and verification has been done with Raspberry Pi Zero W. The car emulator uses Bluetooth connectivity through the Web Bluetooth initiative. At the moment it's only supported in Google Chrome on OS X, Linux and Chromebooks.
Install hmkit and setup your device
Install the following dependencies:
Clone the Python SDK from https://github.com/highmobility/hmkit-python
Install hmkit and other libraries in your device
Disable system default Bluetooth software functions (just do once per reboot)
Create an App
In the Develop tab you will find your apps. In the app details page you are going to set the permissions it requires, manage devices and link virtual vehicles from your garage to test.
- Go to the Develop tab, click the big plus (+) button and select Device App. Enter a name and continue.
- In the left section, select the permissions that your app needs.
- You can edit your app name and image from the menu icon next to the app name.
Create a Vehicle
In the carmaker workspaces you will be able to create vehicles or other items to link with your app and to test with the emulators.
- Go to a carmaker workspace, click the big plus (+) button and select one vehicle to start. Enter a name and continue.
- You will find the vehicle capabilities listed to the left.
- If you click on the "Launch emulator" button you will see how it looks like. Next we will need to link an app with the vehicle.
Initialise the SDK
For a straight forward example of how to initialise the SDK, download the Python BT Scaffold sample app from GitHub.
- Once you have downloaded the SDK or sample app, go to the Apps tab, and select the app you created in the previous steps.
- Choose "Device certificates" from the left section and enter a name for the device.
- Click on the device you just created and copy the snippet from Python tab.
- Insert the snippet into app.py(sample app) to initialise the SDK.
This section outlines how to set the app to Bluetooth broadcasting mode, making it visible to vehicles.
The main access point is the class Broadcaster, which accepts incoming connections (Links). A Link handles the authorisation(TODO expose authorisation) and different functionalities between the device and the connected vehicle.
Access to the Broadcaster is provided by the HMKit class.
Broadcaster broadcaster = HMKit.getInstance().getBroadcaster();
Once the SDK has been initialised, the Broadcaster is ready to be operated. In order to observe incoming links a listener must be set. Once this is done, broadcasting can be started.
Implement a broadcastlistener class(ie. BroadcastListener()) derived from ABC hmkit.broadcastlistener.broadcastlistener. with functions connected(), disconnected(), state_changed(). refer abstractmethods in hmkit.broadcastlistener.broadcastlistener # set the implemented Broadcast listener object for receiving BT broadcast events broadcastListener = BroadcastListener() hmkit.bluetooth.broadcaster.set_listener(broadcastListener) # Start BLE broadcasting/advertising hmkit.bluetooth.startBroadcasting() # Stop BLE broadcasting/advertising #hmkit.bluetooth.stopBroadcasting()
Link events are sent to the BroadcasterListener. To observe incoming links, connected(), disconnected(), state_changed() functions should be used.
# Application code class Broadcast_Listener(hmkit.broadcastlistener.BroadcastListener): def __init__(self): #print(" hm_app BroadcastListener(), __init__() ") self.bt_connected = 0; def connected(self, Link): log.info("App: Link connected") self.bt_connected = 1; # Application code after a Link has been established def disconnected(self, Link): log.info("App: Link disconnected") self.bt_connected = 0;
disconnected() is invoked when the Bluetooth connection is lost.
def disconnected(self, Link): // Application code after a Link has disconnected from the device
Send a Bluetooth Command
Once the emulator is open, fire away a Bluetooth command. For example to unlock the doors of the vehicle. Note that you will get a "Vehicle Asleep" error returned if the emulator is closed.
Read more about the sdk code references in the Python SDK.
# Example: Send GetCapabilities command to vehicle through Bluetooth # hmkit.bluetooth.link.sendcommand(constructed_bytes) # get the command binary for GetCapabilities constructed_bytes = get_capabilities.GetCapabilities().get_bytearray() if constructed_bytes is not None: if self.hmkit.bluetooth.broadcaster.is_connected() == False: print("---- PY: Device is not connected through Bluetooth. Cannot send commands ----") return False else: # send the constructed binary to the connected vehicle self.hmkit.bluetooth.link.sendcommand(constructed_bytes)
Receive a Command
Incoming commands are dispatched via linklistener. The content of command corresponds to the Auto API.
The callback provides raw bytes that can be parsed with CommandResolver.resolve() in order to construct the command object. Parsing and construction of all Auto APIs commands are built into HMKit.
Read more about the sdk code references in the Python SDK.
# Example: Handle received commands from Vehicle # Commands will be received through the registered Link_Listener() class # Callbacks methods class Link_Listener(hmkit.linklistener.LinkListener): def __init__(self): pass def command_incoming(self, link, cmdbytes): """ Callback for incoming commands received from bluetooth link. Change in States will be received in this callback :param link Link: :class:`link` object :param bytearray cmd: data received :rtype: None """ hmkit_inst = hmkit.get_instance() #hmkit_inst.autoapi_dump.message_dump(cmd) # resolve the received command bytes to the # corresponding Autoapi handler class object cmd_obj = CommandResolver.resolve(cmdbytes) if isinstance(cmd_obj, capabilities.Capabilities): print("Capabilities received ") # Example: Capability Checks doorlock_capability = cmd_obj.get_capability(Identifiers.DOOR_LOCKS) ..... elif ____ : .....
Check out the Python code reference for Auto API for further details on how to use vehicle commands.