Skip to main content

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 : string

    IP address of the CLM10k unit.

  • password : string

    Admin 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: bool

    Set this parameter to True in order to retrieve configuration defaults instead of actually set values.

  • with_description: bool

    Set 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 : bool

    Controls presence of human readable group descriptions in the response.

  • recursive : bool

    Parameter 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 : str

    Name 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: str

    Name 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: bool

    If 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 : str

    Name of the user for which the password needs to be set. Currently either "admin" or "upload.

  • admin_pass : str

    Current admin password which is required for the validation of this call.

  • new_pass : str

    New 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

clmprotoclient-1.0.3.tar.gz (30.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clmprotoclient-1.0.3-py3-none-any.whl (31.6 kB view details)

Uploaded Python 3

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

Hashes for clmprotoclient-1.0.3.tar.gz
Algorithm Hash digest
SHA256 8fe7a735e7ff561548816d2576709e5063bdca1f88da62ebd060ca86446f1211
MD5 9130bd5f1f9183ec2534ce3483ff678b
BLAKE2b-256 5bc10dc8d492425319138b72555cd5c9d1dd10e4e12e6d4575a06acead29d8af

See more details on using hashes here.

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

Hashes for clmprotoclient-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 eedca26603d1a1f9770305ae46945e1f8da5799064a2b6f8895c1aeaac1a9c08
MD5 4857ac81c25fa76f4b5b1382cb85e263
BLAKE2b-256 1a5c4fa0e27b92b1b39e3b18f95bc299838c3522f24e4e6b25881403484a93c8

See more details on using hashes here.

Supported by

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