Skip to content

Feature Request: Expose Device Setting and Network Mapping Internally #264

Closed

Description

@pierreluctg

Problem

When working with python_ics, retrieving network-specific settings requires consumers to maintain device-specific mappings that duplicate information already known by the library.

For example, the following simple task:

Display the TqSeg1 value for DWCAN_02 and DWCAN_08

requires application code to maintain:

  1. A mapping from DeviceSettingType → settings structure name.
  2. A mapping from settings structure type → network-to-channel enumeration.
setting_map = {
    e_device_settings_type.DeviceFire2SettingsType: "cyan",
    e_device_settings_type.DeviceRADGigastarSettingsType: "radgigastar",
    e_device_settings_type.DeviceRADMoon2SettingsType: "radmoon2",
    e_device_settings_type.DeviceVCAN412SettingsType: "vcan412",
    e_device_settings_type.DeviceFire3SettingsType: "fire3",
    e_device_settings_type.DeviceRed2SettingsType: "red2",
    # More devices...
}

channel_order_b = (1, 8, *range(2, 8), *range(9, 17))

SettingMapA = Enum("SettingMap", [f"DWCAN_{channel:02}" for channel in range(1, 17)])
SettingMapB = IntEnum(
    "SettingMap", [f"DWCAN_{channel:02}" for channel in channel_order_b]
)

device_settings_to_netid_map = {
    ics.svcan412_settings.svcan412_settings: SettingMapA,
    ics.s_fire3_settings.s_fire3_settings: SettingMapB,
    ics.s_red2_settings.s_red2_settings: SettingMapA,
    ics.srad_gigastar_settings.srad_gigastar_settings: SettingMapB,
    # More devices...
}

This logic is required before we can even locate the appropriate CAN channel settings.

Why This Is Problematic

Applications that support multiple Intrepid devices must:

  • Hard-code device-specific mappings.
  • Duplicate logic that already exists internally.
  • Update mappings whenever new device types are introduced.
  • Reverse-engineer channel ordering differences between devices.

This creates unnecessary maintenance burden and makes it difficult to write device-agnostic tooling.

Expected Behavior

The library should provide a built-in mechanism to resolve network identifiers to the corresponding settings object.

Example ideas:

channel_settings = ics.get_network_settings(
    device,
    "DWCAN_02",
)

or

channel_settings = settings.get_network("DWCAN_02")

allowing consumers to access:

print(channel_settings.TqSeg1)

without needing to know:

  • The underlying settings structure type.
  • The channel numbering scheme.
  • Device-specific network ordering rules.

Current Example

Below is a complete example showing the amount of custom mapping currently required to read TqSeg1 from DWCAN_02 and DWCAN_08.

Example code
# /// script
# dependencies = [
#   "python_ics>=1!26.3",
# ]
# ///
from enum import Enum, IntEnum

import ics
from ics.structures.s_device_settings import s_device_settings
from ics.structures.e_device_settings_type import e_device_settings_type

setting_map = {
    e_device_settings_type.DeviceFire2SettingsType: "cyan",
    e_device_settings_type.DeviceRADGigastarSettingsType: "radgigastar",
    e_device_settings_type.DeviceRADMoon2SettingsType: "radmoon2",
    e_device_settings_type.DeviceVCAN412SettingsType: "vcan412",
    e_device_settings_type.DeviceFire3SettingsType: "fire3",
    e_device_settings_type.DeviceRed2SettingsType: "red2",
}

channel_order_b = (1, 8, *range(2, 8), *range(9, 17))

SettingMapA = Enum("SettingMap", [f"DWCAN_{channel:02}" for channel in range(1, 17)])
SettingMapB = IntEnum(
    "SettingMap", [f"DWCAN_{channel:02}" for channel in channel_order_b]
)

device_settings_to_netid_map = {
    ics.svcan412_settings.svcan412_settings: SettingMapA,
    ics.s_fire3_settings.s_fire3_settings: SettingMapB,
    ics.s_red2_settings.s_red2_settings: SettingMapA,
    ics.srad_gigastar_settings.srad_gigastar_settings: SettingMapB,
}


def get_device_specific_settings(s: s_device_settings) -> object:
    if s.DeviceSettingType not in setting_map:
        raise KeyError(
            f"Error: {s.DeviceSettingType} is not a known type in setting_map"
        )
    return getattr(s.Settings, setting_map[s.DeviceSettingType])


def main():
    devices = ics.find_devices()

    for device in devices:
        ics.open_device(device)
        print(
            f"Opened Device {device} (Open Client handles: {device.NumberOfClients})..."
        )
        try:
            print("Loading default settings...")
            ics.load_default_settings(device)

            print("Reading settings...")
            settings = ics.get_device_settings(device)
            device_specific_settings = get_device_specific_settings(settings)

            net_id_map = device_settings_to_netid_map.get(
                type(device_specific_settings), Enum("SettingMap", [])
            )


            # Trying to display TqSeg1 for DWCAN_02 and DWCAN_08
            for net_id in ("DWCAN_02", "DWCAN_08"):
                if net_id not in net_id_map.__members__:
                    print(f"{net_id} not found in net_id_map.")
                    continue

                channel_id = net_id_map[net_id].value
                channel_attr = f"can{channel_id}"

                if not hasattr(device_specific_settings, channel_attr):
                    print(f"{net_id} not found in device settings.")
                    continue

                channel_settings = getattr(device_specific_settings, channel_attr)
                print(f"{net_id} ({channel_attr}) TqSeg1: {channel_settings.TqSeg1}")

        finally:
            print(f"Closing Device {device}...")
            device.close()


if __name__ == "__main__":
    main()

Benefit

Providing this mapping internally would:

  • Simplify device-independent applications.
  • Reduce duplicated code across projects.
  • Eliminate fragile hard-coded mappings.
  • Improve forward compatibility with future device types.
  • Make the API easier to discover and use.

Question: Is there already an internal API capable of resolving a network identifier (e.g. DWCAN_02) to the corresponding settings structure, or would the maintainers be open to exposing this functionality?

Activity

  1. pierreluctg commented on Oct 7, 2026

    @pierreluctg
    ContributorAuthor
  2. drebbe-intrepid commented on Oct 21, 2026

    @drebbe-intrepid
    Collaborator

    @pierreluctg sorry for the late reply but this is a huge pain point of icsneo40 and python_ics. icsneopy essentially takes care of this for us already so I recommend switching to that. I'm going to close this out as won't fix so we aren't reproducing the work already done in icsneopy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions