<article-heading
title="Media center remote: Kodi integration"
is-published="true"
updated-date="2021-09-04"
/>
<p class="article-description">
After integrating the <a data-article="media-center-remote/infrared-receiver">infrared receiver</a>, the nest
activity for the <a data-article="media-center-remote">media center remote</a> is adding automations for
reacting to infrared signals by dispatching JSON-RPC calls to Kodi.
</p>
<p>The goals of this stage are to:</p>
<ul>
<li>Use a HTTP Request integration to POST to a JSON-RPC endpoint on Kodi.</li>
<li>Send different RPC calls depending on the incoming infrared signal received.</li>
</ul>
<h2>Kodi RPC endpoint</h2>
<p>
The <a href="https://kodi.wiki/view/JSON-RPC_API/v12">Kodi JSON-RPC API</a> supports a huge variety of method calls,
notifications and batch requests. The <code class="inline">Input.ExecuteAction</code> method is the best way to simulate
actions from a remote controller.
</p>
<p>For example, this call simulates pressing "down" on a remote controller:</p>
<pre class="prettyprint" v-pre="v-pre">
<code class="lang-sh">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"
}'</code>
</pre>
<h2>ESPHome configuration</h2>
<p>
Highlighting the differences from before, this configuration:
</p>
<ol>
<li>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</li>
<li>Runs an automation when the "command_for_kodi" is updated, which dispatches a
JSON-RPC command to Kodi</li>
</ol>
<h3><code class="inline">media-center-remote.yaml</code></h3>
<pre class="prettyprint" v-pre="v-pre">
<code class="lang-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;
// ...
}</code>
</pre>
<h3>Log output</h3>
<p>
Powering up the device and pressing buttons on the remote controller yields logs similar to the following:
</p>
<pre class="prettyprint" v-pre="v-pre"><code>...
[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</code></pre>
<h2>Next steps</h2>
<p>
Controlling Kodi is good, but we can go one step further and control the television in
Stage 3: <a data-article="media-center-remote/television-integration">Television integration</a>.
</p>
<p>
This article is part of the <a data-article="media-center-remote">Media center remote</a> set.
If you have any feedback or questions related to this article, please reply to <a
href="https://twitter.com/TassSinclair/status/1434156531663048707">my post on Twitter</a>.
</p>