After integrating the infrared receiver, the nest activity for the media center remote is adding automations for reacting to infrared signals by dispatching JSON-RPC calls to Kodi.

The goals of this stage are to:

Kodi RPC endpoint

The Kodi JSON-RPC API supports a huge variety of method calls, notifications and batch requests. The Input.ExecuteAction method is the best way to simulate actions from a remote controller.

For example, this call simulates pressing "down" on a remote controller:

curl --request POST \
  --url http://kodi-instance:8080/jsonrpc \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "Input.ExecuteAction",
    "params": {
      "action": "down"
    },
    "id": "0"
  }'

ESPHome configuration

Highlighting the differences from before, this configuration:

  1. Runs an automation when an "lg" infrared signal is received that updates a "command_for_kodi" sensor to track the command to be sent to Kodi
  2. Runs an automation when the "command_for_kodi" is updated, which dispatches a JSON-RPC command to Kodi

media-center-remote.yaml

# ...

http_request:
  useragent: esphome/device
  timeout: 10s

text_sensor:
# This platform sensor gets updated when a signal is decoded that
# should be used to trigger a JSON-RPC call on Kodi.
- platform: template
  id: command_for_kodi
  internal: true # Do not expose to Home Assistant
  on_value:
  - http_request.post:
      url: !secret kodi_http_request_url
      headers:
        Content-Type: application/json
      # Using a lambda to generate this body, as the yaml doesn't support nested JSON
      json: |-
        root["jsonrpc"] = "2.0";
        root["id"] = 0;
        root["method"] = "Input.ExecuteAction";
        JsonObject& params = root.createNestedObject("params");
        params["action"] = x;
        
remote_receiver:
  pin:
    number: GPIO2
    inverted: true
  # The Car MP3 remote controller signals can be interpreted as LG codes,
  # so let's just pretend it's an LG remote controller.
  dump: 
  - lg
  on_lg:
  # In this lambda, x is an LGData. x.data is a uint32_t that identifies the button pressed.
  - lambda: |-
      switch (x.data) {
        // ...
        case 0x00FF22DD: // 03
          id(command_for_kodi).publish_state("left");
          break;
        case 0x00FF02FD: // 04
          id(command_for_kodi).publish_state("select");
          break;
        case 0x00FFC23D: // 05
          id(command_for_kodi).publish_state("right");
          break;
        // ...
        }

Log output

Powering up the device and pressing buttons on the remote controller yields logs similar to the following:

...
[22:32:05][D][text_sensor:015]: 'Command for Kodi': Sending state 'left'
[22:32:05][D][http_request:074]: HTTP Request completed; URL: http://kodi-instance:8080/jsonrpc; Code: 200
[22:32:06][D][text_sensor:015]: 'Command for Kodi': Sending state 'right'
[22:32:06][D][http_request:074]: HTTP Request completed; URL: http://kodi-instance:8080/jsonrpc; Code: 200

Next steps

Controlling Kodi is good, but we can go one step further and control the television in Stage 3: Television integration.

This article is part of the Media center remote set. If you have any feedback or questions related to this article, please reply to my post on Twitter.