Core Framework: Common Remote - rdkcentral/python_raft GitHub Wiki

Common Remote Module

This document describes the commonRemote module, a Python module designed to provide a consistent interface for interacting with various remote control devices. It abstracts away the low-level details of different remote technologies, allowing you to write test scripts that work seamlessly with different remote types.

Key Features

  • Remote Control Abstraction: Offers a unified way to send commands to different types of remotes, such as Olimex, SkyProc, and Arduino.
  • Key Mapping: Translates standardized key names used in test scripts to the specific key codes required by each remote.
  • Configuration-Driven: Remote type and key map are defined in a configuration file for easy switching and customization.

Classes

remoteControllerMapping

  • Purpose: Manages the translation of standard key names (e.g., "POWER", "VOLUME_UP") to the corresponding key codes for the currently active remote.
  • Key Methods:
    • getMappedKey(key): Returns the mapped key code for the given standard key name.
    • getKeyMap(): Returns the currently active key map.
    • setKeyMap(newMapName): Switches to a different key map.

commonRemoteClass

  • Purpose: The primary interface for interacting with remote control devices. It encapsulates the remoteControllerMapping class and handles communication with the specific remote implementation.
  • Key Methods:
    • sendKey(keycode, delay=1, repeat=1, randomRepeat=0):
      • Translates the keycode using the active key map.
      • Sends the translated key code to the remote.
      • Optionally adds delays and repeats.
    • setKeyMap(name): Switches to the specified key map.
    • getKeyMap(): Returns the currently active key map.

Configuring the Remote Control Class

The remote control interface is configured from the main framework wide config.yaml using the subsection YAML snippet:

remoteController:
    # [ type: "olimex" ip: "192.168.0.17" port: 7 map: "rc6"]
    # [ type: "skyProc" map: "skyq_map" ]
    # [ type: "arduino" map: "arduino" port: 'COM8' baudrate: 9600]
    # [ type: "None" ]
    type: "olimex"
    map: "xmp_a"
    port: 7
    ip: "192.168.0.103"
    config: "commander_maps.yaml"

This configuration specifies that:

  • type: "olimex": An Olimex remote control device is used for sending commands.
  • map: "xmp_a": The key map named "xmp_a" will be used to translate standardized key names to the specific codes required by the Olimex remote. This map should be defined as per the Key Mapping Metchanism below.
  • port: 7: The port number used to communicate with the Olimex device.
  • ip: "192.168.0.103": The IP address of the Olimex remote control device.
  • config: "commander_maps.yaml": This explicitly specifies the YAML file that contains the definitions of the key maps.

Supported Remote Types

The commonRemote module supports the following remote control types:

  • olimex: For Olimex remote control devices. Requires ip and port in the configuration.
  • skyProc: For SkyProc remote control devices.
  • arduino: For Arduino based remote control solutions. Requires port and baudrate in the configuration.
  • None: For simulating remote control actions or using alternative control mechanisms.

Key Mapping Mechanism

  1. Remote Configuration: A configuration file (remoteConfig) defines the type of remote and the map to use.

  2. Key Map Files: YAML files (e.g., olimex_map.yml) store the key mappings for each remote type:

    - name: "MyOlimexMap"
      prefix: "OLIMEX_" # Optional prefix for translated keys
      codes:
        UP: "0x20"
        DOWN: "0x21"
        POWER: "0x0C"
    
  3. Key Translation: When sendKey(rc.POWER) is called:

    • The commonRemoteClass retrieves the active key map.
    • It looks up enum "rc.POWER" in the map and finds its corresponding code (e.g., "0x0C").
    • If a prefix is defined (e.g., "OLIMEX_"), it's added to the code.
    • The final command (e.g., "OLIMEX_0x0C") is sent to the remote device.

Usage Example

from framework.core.webpageModules.commonRemote import commonRemoteClass

# ... your test setup ...

my_remote = commonRemoteClass(my_logger, remote_config)  # Initialize with remote configuration

# Send the "OK" key (which might be mapped to "ENTER" on the remote)
my_remote.setKeyMap("rc6")
my_remote.sendKey(rc.ENTER) 

# Switch to a different remote
my_remote.setKeyMap("tpv")
my_remote.sendKey(rc.ENTER) 

Benefits

  • Simplified Test Scripts: Test scripts remain independent of specific remote control implementations.
  • Maintainability: Key mappings are centralized in configuration files, making updates and modifications easier.
  • Flexibility: Supports various remote types and allows for custom key mappings.

Key Map Files

Key map files are YAML files that define the mapping between enum test key names and remote-specific key codes. Each file can contain multiple key maps, each with a unique name.

Example olimex_map.yml:

remoteMaps:
  remoteCommanderMap0:
    name: "MyOlimexMap"
    prefix: "OLIMEX_" # Optional prefix for translated keys
    codes:
      UP: "0x20"
      DOWN: "0x21"
      POWER: "0x0C"
      SELECT: "select"

Example multi remote commander maps

remoteMaps:
  remoteCommanderMap0:
    name : "rc6"
    prefix: "RC6="
    codes:
     #-------------PORTABLE:--------------
     NUM_0 : "0"
     NUM_1 : "1"
     NUM_2 : "2"
     NUM_3 : "3"
     NUM_4 : "4"
     NUM_5 : "5"
     NUM_6 : "6"
     NUM_7 : "7"
     NUM_8 : "8"
     NUM_9 : "9"
     # PREVPROG = "0x0A" # No action
     POWER : "OnOff"
     MUTE  : "Mute"
     VOL_UP : "VolUp"
     VOL_DOWN : "VolDown"
     PAUSE : "Pause"
     DOWN : "NavDown"
     LEFT : "NavLeft"
     RIGHT : "NavRight"
     SELECT : "NavEnter"
     HOME : "Home"
     #---------NON-PORTABLE:--------------
     BACK : "Back"
     CROSS : "Cross"
     MIC : "Mic"
     RGYB : "Rgyb"
     MENU : "Menu"
     PICK_UP : "PickUp"
     EXIT: "Back"
     EXIT_WAIT: "Back DURATION=5000 COR0=10 COR1=-5"
     #------------------------------------

remoteCommanderMap1:
  name : "tpv"
  prefix: "TPV="
  codes:
    #-------------PORTABLE:--------------
    NUM_0 : "0"
    NUM_1 : "1"
    NUM_2 : "2"
    NUM_3 : "3"
    NUM_4 : "4"
    NUM_5 : "5"
    NUM_6 : "6"
    NUM_7 : "7"
    NUM_8 : "8"
    NUM_9 : "9"
    MUTE  : "Mute"
    CHANNEL_UP  : "Ch+"
    CHANNEL_DOWN : "Ch-"
    UP : "NavUp"
    DOWN : "NavDown"
    LEFT : "NavLeft"
    RIGHT : "NavRight"
    SELECT : "NavEnter"
    #---------NON-PORTABLE:--------------
    TEST : "Test"
    RST : "Rst"
    FAC : "Fac"
    CSM : "Csm"
    PATTERN : "Pattern"
    ANTENNA_CABLE : "AntennaCable"
    PRE_CH : "PreCh"
    VOL_MAX : "VolMax"
    CTC : "Ctc"
    VOL_BUZZ : "VolBuzz"
    MENU : "Menu"
    BI : "BI"
    CH_SCAN : "ChScan"
    CCTT : "Cctt"
    PIC : "Pic"
    LOG_LED : "LogLed"
    AUDIO : "Audio"
    D2D3 : "D2D3"
    ARC : "Arc"
    CIP : "Ci+"
    VIRGIN : "Virgin"
    CVBS : "Cvbs"
    YPBPR_SCART : "YpbprScart"
    HDMI : "Hdmi"
    VGA : "Vga"
    REGIN : "Regin"
    CLONE : "Clone"
    RESERVE1 : "Reserve1"
    DCR : "Dcr"
    WIFI_SSID : "WifiSsid"
    BLK : "Blk"
    WP : "Wp"
    LIGHT_SENSOR : "LightSensor"
    USB : "Usb"
    RJ45 : "Rj45"
    RS232 : "Rs232"
    RESERVE2 : "Reserve2"
    EXIT_WAIT: "Back DURATION=5000 COR0=10 COR1=-5"
    #------------------------------------

remoteCommanderMap2:
  name: "xmp_d" # Works with XR100)
  prefix: "XMP_d="
  codes:
    POWER: "OnOff"
    HOME: "Home"
    CROSS: "Cross"
    MENU: "Menu" # ... on remote
    UP: "NavUp"
    DOWN: "NavDown"
    RIGHT: "NavRight"
    LEFT: "NavLeft"
    SELECT: "NavEnter"
    BACK: "Back"
    EXIT: "Back"
    NUM_1: "1"
    NUM_2: "2"
    NUM_3: "3"
    NUM_4: "4"
    NUM_5: "5"
    NUM_6: "6"
    NUM_7: "7"
    NUM_8: "8"
    NUM_9: "9"
    NUM_0: "0"
    INPUT : "Input"
    OPTIONS : "Options"
    EXIT_WAIT: "Back DURATION=5000 COR0=10 COR1=-5"
    INPUT_HOLD : "Input DURATION=2000 COR0=10 COR1=-5"

remoteCommanderMap3:
  name: "xmp_e"
  prefix: "XMP_e="
  codes:
    POWER: "OnOff"
    HOME: "Home"
    CROSS: "Cross"
    MENU: "Menu" # ... on remote
    UP: "NavUp"
    DOWN: "NavDown"
    RIGHT: "NavRight"
    LEFT: "NavLeft"
    SELECT: "NavEnter"
    BACK: "Back"
    EXIT: "Back"
    NETFLIX: "Netflix"
    PRIME_VIDEO: "PrimeVideo"
    PEACOCK: "Peacock"
    DISNEY: "Disney"
    NUM_1: "1"
    NUM_2: "2"
    NUM_3: "3"
    NUM_4: "4"
    NUM_5: "5"
    NUM_6: "6"
    NUM_7: "7"
    NUM_8: "8"
    NUM_9: "9"
    NUM_0: "0"
    INPUT : "Input"
    OPTIONS : "Options"
    EXIT_WAIT: "Back DURATION=5000 COR0=10 COR1=-5"
    INPUT_HOLD : "Input DURATION=2000 COR0=10 COR1=-5"