Client to communicate with the CANlink mobile 10000 protobuf API.
Project description
clmprotoclient - Protomolecule Python Module
The module simplifies interaction with the CANlink mobile via the protocol buffers based websocket API. It provides convenience methods which will create the actual proto messages and it also wraps around websockets in order to take care of sending and receiving the messages. It has a dependency to the clmprotowrapper which contains the Python bindings generated by proto compiler which can be used directly if one would want to implement the whole handling without using the provided module.
The package also contains a reference application clmshell which uses the
module and which allows to configure the device from a command line prompt.
Installation
The latest built version can be installed from PyPI.
Install from PyPI using pip:
pip install clmprotoclient
Building
We use poetry as build system.
Contributing
We encourage you to contribute. In case you can not find a pull request reviewer please do not hesitate to reach out to Proemion support.
Usage
clmprotoclient.clmlib
The clmlib submodule provides the clm10k class which is basically a
convenience wrapper around proto generation and websocket communication.
The clm10k class represents a connection instance to the CLM10k protobuf API.
The clm10k class provides easy to use methods to generate requests to the
device via the websocket, using the protocol buffers based API.
The responses from the unit are forwarded as is in proto messages, these messages already present the data in a well structured way, so it does not make much sense to repack it.
This client requires the clmprotowrapper as wrapper around the protocol buffers API
of the device which will be automatically installed due to defined dependencies.
Instantiation
clm10k(ip, password, cb_connected = None, cb_firmware_update = None,
cb_config_update = None, cb_disconnected = None)
Parameters:
-
ip:stringIP address of the CLM10k unit.
-
password:stringAdmin password of the CLM10k unit.
-
cb_connected:callback(device_info_data)This callback function which will be called once a connection to the device is established. Device information will be passed to this function as the only parameter.
-
cb_firmware_update:callback(firmware_update_info_data)This callback function will be called when a firmware update has been performed or attempted on the device. The update notification is sent out to all connected clients, regardless of who started the update.
Locally the update can be started by HTTPS
POST'ing the firmware image to the https://..device-ip../firmware URL.Example:
curl -u admin:password -k -v -F 'file=@./firmware.swu' \
https://192.168.1.43/firmware
-
cb_config_update:callback(config_update_info_data)This callback function will be called when a configuration update has been performed or attempted on the device. The update notification is sent out to all connected clients, regardless of who started the update.
Locally the update can be started by HTTPS
POST'ing the configuration file to the https://..device-ip../config URL.Example:
curl -u admin:password -k -v -F 'file=@./myconf.clm' \
https://192.168.1.43/config`
-
cb_disconnected:callback()This callback function will be called when a connection to the device has been closed. The callback is not bound to any specific logic, i.e. the callback will be triggered regardless if the connection has been closed due to user action like a call to terminate() or due to an error (for instance when an incorrect password has been supplied). It is up to the application to build up a logic in order to interpret the reason of the callback.
Important: once disconnected a new instance needs to be instantiated in order to open a new connection.
Termination
terminate()
Terminate the websocket thread and close the websocket. The class can not be used afterwards. If you would like to connect again, a new instance needs to be created.
Retrieving Device Configuration
get_config(self, options = None, groups = None, get_defaults = False,
with_description = True, cb_response = None)
Retrieve one or more configuration settings.
This function allows to retrieve configuration values of one or more settings. Either pass the option/group elements which should be read, or do not pass any at all - in this case all available settings will be returned.
If the get_defaults parameter is set to true, then factory defaults of the given options will be retrieved instead of the currently set values.
The logic for requesting groups works as follows:
-
no groups + no options
return all options
-
groups + no options
return options found in requested groups
-
no groups + options
return requested options
-
groups + options
return options found in requested groups + return individually specified options
Note: requesting a group that is a parent to other subgroups will return all child options, including the ones found in subgroups.
Parameters:
-
options:[ (option_type, group_name), (option_type, ), ... ]Each list element must be a tuple where the first member of the tuple is the option type, while the second member is optional and is the associated group name which is required for options which belong to dynamic groups. -
groups:[ (group_type, group_name), (group_type, ), ... ]Each list element must be a tuple where the first member of the tuple is the group type, while the second member is optional and is the group name, which is required for dynamic groups.
-
get_defaults:boolSet this parameter to True in order to retrieve configuration defaults instead of actually set values.
-
with_description:boolSet this parameter to True in order to enable human readable option descriptions in the response.
-
cb_response:callable(response)Callback which will provide the response to this request.
Applying Device Configuration
apply_config(options, cb_response = None)
Apply one or more application settings.
Zero config elements are not allowed, i.e. if there is nothing to change, then don't call this function, otherwise the application will answer with an error response.
Options that belong to the same group will be automatically handled as "transactions", i.e. all options from the group must succeed, if one fails, then the whole group won't get applied.
Parameters:
-
options:[ (option_type, value, group_name), (option_type, value,),.. ]Each list element must be a tuple where the first member of the tuple is the option type, while the second member is optional and belong to dynamic groups.
-
cb_response:callable(response)Callback which will provide the response to this request.
Validate Configuration
validate_config(self, options, cb_response = None)
Validate if configuration settings can be applied, without actually applying them. This call is also helpful to user interfaces which need to figure out what fields become disabled and thus also need to be disabled in the UI if a certain configuration is applied.
Zero config elements are not allowed, i.e. if there is nothing to validate, then don't call this function, otherwise the application will answer with an error response.
Parameters:
-
options:[ (option_type, value, group_name), (option_type, value,),.. ]Each list element must be a tuple where the first member of the tuple is the option type, while the second member is optional and is the associated group name which is required for options which belong to dynamic groups.
-
**
cb_response``: _callable(response)`_Callback which will provide the response to this request.
Getting Configuration Group Information
get_config_group_info(groups = [], with_description = True,
recursive = True, cb_response = None)
Request information about configuration groups and their parent-child relationship.
Parameters:
-
groups:[ group_type, group_type, ...]List of group types for which to request the information.
-
with_description:boolControls presence of human readable group descriptions in the response.
-
recursive:boolParameter which controls if the group information should be returned recursively or if only the top level groups are returned.
-
cb_response:callable(response)Callback which will provide the response to this request.
Create a New Configuration Group
create_config_group(group, name, cb_response = None)
This function creates a configuration group for the requested group type, this is how network profiles can be created. A unique name must be provided, names span across all dynamic groups regardless of the group type.
Only dynamic group types are allowed.
Parameters:
group:int
Type of the group to create.
-
name:strName of the new group.
-
cb_response:callable(response)Callback which will provide the response to this request.
Remove a Configuration Group
remove_config_group(name, cb_response = None)
This function removes a configuration group with the given name, this is how network connection profiles can be removed. Note, that the last profile for each interface can not be deleted, attempting to do so will result in an error.
Only dynamic groups can be removed, since group names are unique, it is not necessary to supply the group type.
Parameters:
-
name:strName of the group which needs to be deleted.
-
cb_response:callable(response)Callback which will provide the response to this request.
Export Configuration
config_export(options = None, groups = None,
factory_reset = None, cb_response = None):
Export device configuration to a file that can later be reimported.
If all fields are left out, then all writable config options will be exported.
If the factory_reset parameter is true, then the exported file will contain only the reset to factory defaults instruction. Options and groups parameters must not be set.
Parameters:
-
options:[ (option_type, group_name), (option_type, ), ...]Options to export, list of tuples containing the option type as the first tuple member and an optional group name as the second tuple member. The group name is required for options that belong to a dynamic group.
-
groups:[ (group_type, group_name), (group_type, ), ... ]Groups to export, list of tuples containing the group type as the first member and an optional group name as the second tuple member. The group name is required for dynamic groups.
-
factory_reset:boolIf this parameter is set, the configuration export will only contain the reset instruction, options and groups parameters must not be set.
-
cb_response:callable(response)Callback which will provide the response to this request.
Reset Device to Factory Settings
reset_to_factory_settings(cb_response = None)
Reset device to factory settings.
The factory reset deletes all data on the device and restores the original factory settings. Note, that the device will be rebooted, meaning that the websocket connection will be interrupted.
Parameters:
-
cb_response:callable(response)Callback which will provide the response to this request.
Reset Configuration to Factory Defaults
reset_configuration(cb_response = None)
Reset device configuration to factory defaults.
Note, that the configuration reset only restores the application settings to factory defaults and does not affect credentials nor removes created users. The application will be restarted, meaning that the websocket connection will be interrupted.
Parameters:
-
cb_response:callable(response)Callback which will provide the response to this request.
Abort Firmware Update
firmware_update_abort(cb_response = None)
Abort an ongoing firmware update. This command can only cancel a pending or ongoing download, the flashing process can not be interrupted.
Parameters:
-
cb_response:callable(response)Callback which will provide the response to this request.
Retrieve Device Information
get_device_info()
This will return the same data as the cb_connected callback, providing information about the current firmware and hardware version and alike.
Set API/Web-UI Access Password
set_password(username, admin_pass, new_pass, cb_response = None)
Change the password for the web server of the device, this affects access to the web UI and to this protocol buffers API.
The current admin password is always required, the new password will only be set if the current one is correct.
Currently only two users are supported: "admin" has access to everything while "upload" can only POST files for further transfer to the DataPortal, but has no access to the protocol buffers API.
Parameters:
-
username:strName of the user for which the password needs to be set. Currently either "admin" or "upload.
-
admin_pass:strCurrent admin password which is required for the validation of this call.
-
new_pass:strNew password for the selected user.
-
cb_response:callable(response)Callback which will provide the response to this request.
Remove "Upload" User
remove_upload_user(cb_response = None)
The "upload" user is a special account which has no access to the API/UI, but
one that is allowed to POST files to the device. The files will then be
automatically uploaded to the DataPortal.
This user has a separate password which can be set via the set_password()
call.
In order to disable the "upload" account, simply remove the user.
Parameters:
-
cb_response:callable(response)Callback which will provide the response to this request.
Get List Of User Accounts
get_users(self, cb_response = None)
Get a list of currently available user accounts.
Parameters:
-
cb_response:callable(response)Callback which will provide the response to this request.
Set Date / Time
set_datetime(self, timestamp = None, cb_response = None)
Set system date and time.
Parameters:
-
timestamp:datetime.datetime()Datetime object containing a timestamp which should be applied on the device.
-
cb_response:callable(response)Callback which will provide the response to this request.
Get Data / Time
get_datetime(self, cb_response = None)
Get date and time from the device.
Parameters:
-
cb_response:callable(response)Callback which will provide the response to this request.
Examples
Here is a basic example of how this module could be used. Also have a
look at clmshell sources (part of this distribution). Let's assume that we
want to read out and print the communication unit ID, we omit most
of the error checking, however we still implement a minimum amount of
synchronization.
#!/usr/bin/env python3
from clmprotoclient import clmlib
from clmprotoclient import clmapi_pb2
import threading
evt = threading.Event() # we will use the event to wait for certain states
connected = False # global flag to indicate if we managed to connect
# response callback to the get_config call:
# look for the expected option in the response and print it
def cb_cu_id_response(data):
if (isinstance(data, clmapi_pb2.get_config_response)):
# we are expecting one element
if (len(data.element) > 0):
el = data.element[0]
if (el.option == clmapi_pb2.CFG_OPTION_STR_DP_CU_ID):
print(f"Current CU ID is \"{el.value.str}\".")
elif (isinstance(data, clmapi_pb2.standard_response)):
print(clmapi_pb2.standard_response) # will contain an error message
evt.set()
# callback which will be triggered upon connection
def cb_connected(data):
global connected
connected = True
evt.set()
evt.clear()
# make sure to edit the next line and use the IP and password of your device
inst = clmlib.clm10k("192.168.2.61", "mypassword", cb_connected = cb_connected)
if (evt.wait(timeout=5) != True) or (not connected):
print("Timeout: failed to establish a connection!")
inst.terminate()
exit(1)
evt.clear()
inst.get_config(options = [ clmapi_pb2.CFG_OPTION_STR_DP_CU_ID ],
cb_response = cb_cu_id_response)
evt.wait(timeout=5)
inst.terminate()
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clmprotoclient-1.0.3.tar.gz.
File metadata
- Download URL: clmprotoclient-1.0.3.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.3 CPython/3.12.1 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fe7a735e7ff561548816d2576709e5063bdca1f88da62ebd060ca86446f1211
|
|
| MD5 |
9130bd5f1f9183ec2534ce3483ff678b
|
|
| BLAKE2b-256 |
5bc10dc8d492425319138b72555cd5c9d1dd10e4e12e6d4575a06acead29d8af
|
File details
Details for the file clmprotoclient-1.0.3-py3-none-any.whl.
File metadata
- Download URL: clmprotoclient-1.0.3-py3-none-any.whl
- Upload date:
- Size: 31.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.3 CPython/3.12.1 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eedca26603d1a1f9770305ae46945e1f8da5799064a2b6f8895c1aeaac1a9c08
|
|
| MD5 |
4857ac81c25fa76f4b5b1382cb85e263
|
|
| BLAKE2b-256 |
1a5c4fa0e27b92b1b39e3b18f95bc299838c3522f24e4e6b25881403484a93c8
|