Features

This section describes all features that are shipped with this package.

Scenario Features

Base Classes

class balderhub.ant.lib.scenario_features.AntplusDeviceConfig(**kwargs)

Bases: Feature

Base universal ANT+ Device configuration feature

property device_num
Returns:

returns the device number of the device

class balderhub.ant.lib.scenario_features.BaseAntplusDeviceProfile(**kwargs)

Bases: Feature

Base class for an ANT+ Device Profile

classmethod get_existing_pages_for_profile() OrderedDict[int, BaseAntplusPage]
Returns:

returns an ordered dictionary mapping with the Page-ID and the Page this profile supports

class balderhub.ant.lib.scenario_features.AntplusTestCriteriaConfig(**kwargs)

Bases: Feature

General ANT+ test criteria configuration feature

property allowed_packet_loss_percent: float

value between 0 and 1 that defines the accepted package loss during transmission

property first_number_of_beats_to_skip
Returns:

indicates the number of beat that are ignored before the cyclic values like RR-Value, BPM, consecutive beat counts, … are validated

property request_transmission_numbers_for_ack: list[int]
Returns:

returns a list of all transmission-numbers that should be tried an validated within ScenarioHrmManualRequestForAck

property request_transmission_numbers_for_broadcast: list[int]
Returns:

returns a list of all transmission-numbers that should be tried an validated within ScenarioHrmManualRequestForBrdcst

General Ant+ Manager/Controller

class balderhub.ant.lib.scenario_features.AntNodeManagerFeature(**kwargs)

Bases: Feature

Base ANT Node Manager Feature - provides bindings to the ANT Stick or the Ant device and manages the connection to it. The AntplusControllerFeature features use this feature to instantiate their own ANT+ channel.

property network_and_network_key: tuple[int, list[int]]
Returns:

returns the network and its key the manager should use

shutdown() None

Shuts down the manager

start() None

Starts the manager

class balderhub.ant.lib.scenario_features.AntplusControllerFeature(**kwargs)

Bases: Feature

Base ANT+ Controller Feature that can be used for any Profile. It holds a inner VDevice that needs to define exactly one profile that is based on BaseAntplusDeviceProfile.

This scenario-level feature is used as base class for different type of controllers that are specified for a specific profile type.

class AntPlusDevice

Bases: VDevice

vdevice holding the ANT+ device profile

exception ValidationError

Bases: Exception

error that is raised by internal profile validation functions

property channel_is_active: bool
Returns:

returns True if the channel is active, otherwise False

property channel_period: int
Returns:

the channel period the controller should use

property channel_type: int
Returns:

the own channel type the controller should use

close_channel() None

Closes the Channel

property device_type: int
Returns:

the device type the controller should search for

fixt_make_sure_ant_channel_is_closed(restore_entry_state: bool = True) Generator[None, None, None]

Fixture that makes sure that the ANT Channel is opened before finishing the construction part of this fixture.

If restore_entry_state is True, the method will reestablish the state that was given before entering this fixture.

Note

You can use this fixture directly by using:

@balder.fixture(...)
def my_fixture(...):
    yield from feat.fixt_make_sure_ant_channel_is_closed(...)
Parameters:

restore_entry_state – True if the previous state (either connected or disconnected) should be reestablished in the teardown part of this fixture

Returns:

the ready to use fixture generator, but without any values

fixt_make_sure_ant_channel_is_opened(restore_entry_state: bool = True) Generator[None, None, None]

Fixture that makes sure that the ANT Channel is opened. If it is already open when entering this fixture, it will do nothing. If it is closed, it will ensure that it is opened as soon as the construction part of this fixture is finished.

Note

You can use this fixture directly by using:

@balder.fixture(...)
def my_fixture(...):
    yield from feat.fixt_make_sure_ant_channel_is_opened(...)
Parameters:

restore_entry_state – True if the previous state (either open or closed) should be reestablished in the teardown part of this fixture

Returns:

the ready to use fixture generator, but without any values

get_profile_consistency_validation_report() OrderedDict[str, str | None]

This method is used to execute a set of validation_functions that makes sure that check that can be applied on the raw data of the profile.

Returns:

an ordered dict with a description of the validation as key and the error string as value (or None, if sub validation passed)

open_channel() None

Opens the channel

property received_ack_messages: PageMessageCollection
Returns:

returns the current available ACK messages that has been received since the channel is active

property received_broadcast_messages: PageMessageCollection
Returns:

returns the current available BROADCAST messages that has been received since the channel is active

property rf_channel_frequency: int
Returns:

the own RF Channel the controller should use

send_ack_message(message: BaseAntplusPage) None

This method sends a given message as ACK message within the open channel :param message: the message that should be sent

send_broadcast_message(message: BaseAntplusPage) None

This method sends a given message as BROADCAST message within the open channel :param message: the message that should be sent

property transmission_type: int
Returns:

the own transmission type the controller should use

validate_profile_consistency() None

This method is used to execute a set of validation_functions that makes sure that check that can be applied on the raw data of the profile.

property validation_methods: OrderedDict[str, Callable[[], None]]
Returns:

mapping of validation methods that can be used to check the full validity of all messages sent by a ANT+ device as ordered dict (key is printable name and the callable as value)

wait_for_new_ack_message(of_page_type: list[type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage]] | type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage] | None = None, timeout: float = 10) BaseAntplusPage

This method waits for a new ACK message to be received. All messages that has been received before entering this method are not considered.

If no message is received within the given timeout, the method raises a TimeoutError.

Parameters:
  • of_page_type – if given, the only considers messages of this specific type

  • timeout – the maximum time in seconds to wait for a new message

Returns:

the new received message

wait_for_new_broadcast_message(of_page_type: list[type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage]] | type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage] | None = None, timeout: float = 10) BaseAntplusPage

This method waits for a new BROADCAST message to be received. All messages that has been received before entering this method are not considered.

If no message is received within the given timeout, the method raises a TimeoutError.

Parameters:
  • of_page_type – if given, the only considers messages of this specific type

  • timeout – the maximum time in seconds to wait for a new message

Returns:

the new received message

Specific ANT+ Profile: Heart-Rate-Monitor (HRM)

class balderhub.ant.lib.scenario_features.AntplusControllerHrmFeature(**kwargs)

Bases: AntplusControllerFeature

Special ANT+ controller implementation for the ANT+ Heart-Rate Monitor Profile. The VDevice implements the HeartRateMonitorDeviceProfile.

class AntPlusDevice

Bases: AntPlusDevice

inner vdevice representing the ANT+ Device with and implementation of the HeartRateMonitorDeviceProfile

property channel_is_active: bool
Returns:

returns True if the channel is active, otherwise False

property channel_period: int
Returns:

the channel period the controller should use

property channel_type: int
Returns:

the own channel type the controller should use

determine_background_pages() list[type[Union[balderhub.ant.lib.utils.pages.hrm.hrm_0_default_data_page.Hrm0DefaultDataPage, balderhub.ant.lib.utils.pages.hrm.hrm_1_cumulative_operation_time_page.Hrm1CumulativeOperationTimePage, balderhub.ant.lib.utils.pages.hrm.hrm_2_manufacturer_information_page.Hrm2ManufacturerInformationPage, balderhub.ant.lib.utils.pages.hrm.hrm_3_product_information_page.Hrm3ProductInformationPage, balderhub.ant.lib.utils.pages.hrm.hrm_4_previous_heart_beat_event_time_page.Hrm4PreviousHeartBeatEventTimePage, balderhub.ant.lib.utils.pages.hrm.hrm_5_swim_interval_summary_page.Hrm5SwimIntervalSummaryPage, balderhub.ant.lib.utils.pages.hrm.hrm_6_capabilities_page.Hrm6CapabilitiesPage, balderhub.ant.lib.utils.pages.hrm.hrm_7_battery_status_page.Hrm7BatteryStatusPage, balderhub.ant.lib.utils.pages.hrm.hrm_9_device_information_page.Hrm9DeviceInformationPage, balderhub.ant.lib.utils.pages.hrm.hrm_32_hr_feature_page.Hrm32HrFeaturePage]]]

returns the page types of the background pages or None if it is not possible to determine this information with the available messages

It raises a exception in case the internal pattern is definitly wrong.

determine_main_pages() list[type[Union[balderhub.ant.lib.utils.pages.hrm.hrm_0_default_data_page.Hrm0DefaultDataPage, balderhub.ant.lib.utils.pages.hrm.hrm_1_cumulative_operation_time_page.Hrm1CumulativeOperationTimePage, balderhub.ant.lib.utils.pages.hrm.hrm_2_manufacturer_information_page.Hrm2ManufacturerInformationPage, balderhub.ant.lib.utils.pages.hrm.hrm_3_product_information_page.Hrm3ProductInformationPage, balderhub.ant.lib.utils.pages.hrm.hrm_4_previous_heart_beat_event_time_page.Hrm4PreviousHeartBeatEventTimePage, balderhub.ant.lib.utils.pages.hrm.hrm_5_swim_interval_summary_page.Hrm5SwimIntervalSummaryPage, balderhub.ant.lib.utils.pages.hrm.hrm_6_capabilities_page.Hrm6CapabilitiesPage, balderhub.ant.lib.utils.pages.hrm.hrm_7_battery_status_page.Hrm7BatteryStatusPage, balderhub.ant.lib.utils.pages.hrm.hrm_9_device_information_page.Hrm9DeviceInformationPage, balderhub.ant.lib.utils.pages.hrm.hrm_32_hr_feature_page.Hrm32HrFeaturePage]]]

returns the page types of the main pages

It raises a exception in case there are more than 2 main pages or none main pages

property device_type: int
Returns:

the device type the controller should search for

property rf_channel_frequency: int
Returns:

the own RF Channel the controller should use

property transmission_type: int
Returns:

the own transmission type the controller should use

validate_page_2_manufacturer()

Note that this method raises no error if non message has this message type

Returns:

validate_page_3_product()

Note that this method raises no error if non message has this message type

Returns:

property validation_methods: OrderedDict[str, Callable[[], None]]
Returns:

mapping of validation methods that can be used to check the full validity of all messages sent by a ANT+ device as ordered dict (key is printable name and the callable as value)

class balderhub.ant.lib.scenario_features.AntplusHrmDeviceConfig(**kwargs)

Bases: AntplusDeviceConfig

More specific scenario-level device config for devices that implement the HRM profile.

class SupportedSpecVersion(value)

Bases: Enum

enum describing the supported spec version this feature supports

property expected_background_pages: list[type[balderhub.ant.lib.utils.pages.hrm.base_hrm_page.BaseHrmPage]]
Returns:

returns a list of all pages that are expected to be a BACKGROUND page

property expected_main_page: type[balderhub.ant.lib.utils.pages.hrm.hrm_0_default_data_page.Hrm0DefaultDataPage] | type[balderhub.ant.lib.utils.pages.hrm.hrm_4_previous_heart_beat_event_time_page.Hrm4PreviousHeartBeatEventTimePage]
Returns:

returns the expected MAIN page

get_expected_battery_state_for_level(battery_level: int) int

Converts the given BatteryLevel into the expected Battery-State that is returned withing Hrm7BatteryStatusPage

Parameters:

battery_level – the battery level to get the expected Battery-State for

Returns:

the battery state as integer

property hardware_version
Returns:

the expected hardware version of the device

property manual_request_possible_for: list[type[balderhub.ant.lib.utils.pages.hrm.base_hrm_page.BaseHrmPage]]
Returns:

returns a list of all pages a manual Page-Request (PAGE ID 70) can be done with

property manual_request_redirect_ack_as_broadcast: bool
Returns:

returns True if it is expected that all requested Pages as ACK response are redirected as BROADCAST, False otherwise

property manufacturer_id
Returns:

the expected manufacturer ID

property model_number
Returns:

the expected model number of the device

property serial_number
Returns:

the expected serial number of the device

property software_version
Returns:

the expected software version of the device

property support_battery_voltage_messuring: bool
Returns:

returns True if the device supports battery voltage messages within its BatteryLevel Page, otherwise False

property supported_spec_version: SupportedSpecVersion

gives the current supported spec version the device should support

class balderhub.ant.lib.scenario_features.AntplusHrmTestCriteriaConfig(**kwargs)

Bases: AntplusTestCriteriaConfig

Heart-Rate-Monitor specific ANT+ test criteria configuration feature

get_allowed_min_max_bpm_value_for(expected_bpm_value: int) tuple[int, int]

This method returns the allowed min and max value for a given BPM value within a heart-rate monitor profile :param expected_bpm_value: the expected value of the BPM :return: a tuple with the min and the max allowed values the real BPM is allowed to have

get_allowed_min_max_rr_value_for(expected_rr_value_sec: float) tuple[float, float]

This method returns the allowed min and max value for a given RR-Value within a heart-rate monitor profile :param expected_rr_value_sec: the expected value of the RR-Value :return: a tuple with the min and the max allowed values the real RR-Value is allowed to have

class balderhub.ant.lib.scenario_features.HeartRateMonitorDeviceProfile(**kwargs)

Bases: BaseAntplusDeviceProfile

This feature can be assigned to an ANT+ device that supports the Heart Rate Monitor profile.

Setup Features

class balderhub.ant.lib.setup_features.OpenantManagerFeature(**kwargs)

Bases: AntNodeManagerFeature

Setup Level feature implementation of balderhub.ant.lib.scenario_features.AntNodeManagerFeature that uses the OpenAnt Python Library to interact with remote devices

property node: Node | None
Returns:

returns the openant.easy.node.Node object

shutdown(timeout=5) bool

Shuts down the manager

start()

Starts the manager

class balderhub.ant.lib.setup_features.OpenantPlusControllerHrmFeature(**kwargs)

Bases: AntplusControllerHrmFeature

Setup Level feature implementation for the AntplusControllerHrmFeature, by using the openant library.

property channel_is_active: bool
Returns:

returns True if the channel is active, otherwise False

close_channel() bool

Closes the Channel

property extended_format: Literal['legacy', 'flagged', 'none']
Returns:

returns the extended format that should be requested for the ANT channel

get_page_for_no(page_no: int) type[balderhub.ant.lib.utils.pages.base_received_antplus_page.BaseReceivedAntplusPage]

This method returns the page type object for the given page number. It raises a KeyError in case that there is no page specified for the given page-number.

Parameters:

page_no – the page number the page type should be returned

Returns:

the page type that describes the given page number

open_channel()

Opens the channel

property received_ack_messages: PageMessageCollection
Returns:

returns the current available ACK messages that has been received since the channel is active

property received_broadcast_messages: PageMessageCollection
Returns:

returns the current available BROADCAST messages that has been received since the channel is active

send_ack_message(message: BaseAntplusPage)

This method sends a given message as ACK message within the open channel :param message: the message that should be sent

send_broadcast_message(message: BaseAntplusPage) None

This method sends a given message as BROADCAST message within the open channel :param message: the message that should be sent

wait_for_new_ack_message(of_page_type: list[type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage]] | type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage] | None = None, timeout: float = 10) BaseAntplusPage

This method waits for a new ACK message to be received. All messages that has been received before entering this method are not considered.

If no message is received within the given timeout, the method raises a TimeoutError.

Parameters:
  • of_page_type – if given, the only considers messages of this specific type

  • timeout – the maximum time in seconds to wait for a new message

Returns:

the new received message

wait_for_new_broadcast_message(of_page_type: list[type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage]] | type[balderhub.ant.lib.utils.pages.base_antplus_page.BaseAntplusPage] | None = None, timeout: float = 10) BaseAntplusPage

This method waits for a new BROADCAST message to be received. All messages that has been received before entering this method are not considered.

If no message is received within the given timeout, the method raises a TimeoutError.

Parameters:
  • of_page_type – if given, the only considers messages of this specific type

  • timeout – the maximum time in seconds to wait for a new message

Returns:

the new received message