How I Control My Home While Reading My Kindle Book with a Cup of Hot Chocolate

I created a basic HTML remote control to run on my Kindle Voyager eBook that triggers Hassio events via the RESTful integration API to control my Harmony Entertainment Hub.

Using a PI-4B device with Ubuntu Server, Dockers, and Hassio installed on it:

With a logitec Harmony Hub configured for my entertainment center:

And my Kindle Voyage eBook reader:

HTML Remote I destined for Kindle’s Web Browser:

Every button pressed triggers a “keyboard_remote_command_received”. Examle:

Event 8 fired 9:42 AM:
{
    "event_type": "keyboard_remote_command_received",
    "data": {
        "key_code": 34,
        "device_descriptor": "/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd",
        "device_name": "httpRemote"
    },
    "origin": "REMOTE",
    "time_fired": "2019-11-25T17:42:54.714444+00:00",
    "context": {
        "id": "24f01d7c46684555a274f66990675af9",
        "parent_id": null,
        "user_id": "a92e7d11030d427a8462350d33be11cc"
    }
} 

HTML Code:
located in hassio file: hassio/homeassitant/www/httpRemotes.htm
url: http://192.168.0.140:8123/local/httpRemotes.htm

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Universal Http Remote</title>
  
<script language="javascript" type="text/javascript">
//##############################################
//### Use javascript's XMLHttpRequest Object
//### To Trigger HomeAssistant Events
//### Via the RESTful Integration API
//##############################################

  function sendKeyCode(event) {
    var xhttp = new XMLHttpRequest();
    var keyElement = event.currentTarget;
    var keyCode = keyElement.attributes['keyCode'].nodeValue;
    var location = document.getElementById("location").value;
    //alert("sendKeyCode: " + keyCode);

    xhttp.onreadystatechange = function() {
      if (this.readyState == 4) {
        if(this.status == 200) {
           //alert('<h2>Success, response: '+this.responseText+'</h2>');
        } else {
           alert('<h2>Failed, status: '+this.status+'</h2>');
        }
        
        keyElement.removeAttribute("sendingKeyCode");
      }
    };

    xhttp.open("POST", "http://192.168.0.140:8123/api/events/keyboard_remote_command_received");
    xhttp.setRequestHeader("Content-Type", "application/json");
    xhttp.setRequestHeader("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI4NzgzMWMwMGE0NGU0MGFkOWY3MThlNzhmNjg3MGJjZSIsImlhdCI6MTU3NDE4MTYxNywiZXhwIjoxODg5NTQxNjE3fQ.wzOT8BaZrN_Z38T_2RoJpT9sjtg5pelxIQaWJafUmgI");
    xhttp.send('{"key_code": '+keyCode+', "device_descriptor": "'+location+'", "device_name": "IpRemote"}');
  }

  function run(message)
  {
    var buttons = document.getElementsByTagName("td");
    for(button in buttons){
      if(buttons[button].attributes == undefined) continue;
      if(buttons[button].attributes.keyCode == undefined) continue;
      
      buttons[button].addEventListener("click", function(event){
        //alert("Hello World: ");
        sendKeyCode(event);
      }); 
    };  
  }
   
//################
//### MAIN
//################
  window.addEventListener("load", run, false);
</script>
  
<style>
  body {
  }
  #power {
    font-size: 120%;
    display: table-cell;
    vertical-align: middle;
  }
  table#buttons {
    width: 1060px;
    height: 1180px;
    border-top: 40px solid #3366FF;
    border-bottom: 40px solid #3366FF;
    border-left: 40px solid #3366FF;
    border-right: 40px solid #3366FF;
    border-radius: 3em;
    border-collapse: separate;
    border-spacing: 20px 20px;"
    //margin-left: 10%;
  }
  col {
    span: 12;
  }
  select {
    text-align-last: center;
    font-size: 140%;
  }
  tr {
    //height: 20px;
    //padding-top: 10px;
  }
  td.line {
    height: 10px;
    background-color: #3366FF;
  }
  td.list {
    height: 80px;
    font-size: 160%;
    color: #FFFFFF;
    background-color: #3366FF;
  }
  td.button {
    font-size: 160%;
    width: 8.2%;
    //margin: 30px;
    border: 1px dashed black;
    border-radius: 10em;
    //background-color: yellow;
  }
  td.button:hover, td.button:focus, td.button:active {
    background-color: grey;
  }
  td[keyCode]{
    cursor: pointer;
  }
  td[sendingKeyCode]{
    border: 10px solid black;
  }
</style
</head>
      
<body>
  <table id="buttons" class="buttons">
    <colgroup>
      <col class="button">
    </colgroup>
    <tbody>
      <tr>
        <td class="button" keyCode="60" colspan="2"><center><b>PWR</b></center></td>
        <td class="list" colspan="8"><center><b>HTTP Remote Location</b></center>
          <center><b><select id="location">
            <option value="/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd">Bedroom</option>
            <option value="/dev/input/by-id/usb-flirc.tv_flirc-event-kbd">Living Room</option>
          </select></b></center>      
        </td>
        <td class="button" keyCode="27" colspan="2"><center><b>INPUT</b></center></td>
      </tr>
      <tr>
        <td class="button"              colspan="3"><center><b>|<<</b></center></td>
        <td class="button" keyCode="57" colspan="3"><center><b>REC</b></center></td>
        <td class="button" keyCode="58" colspan="3"><center><b>STOP</b></center></td>
        <td class="button"              colspan="3"><center><b>>>|</b></center></td>
      </tr>
      <tr>
        <td class="button" keyCode="50" colspan="3"><center><b><<</b></center></td>
        <td class="button" keyCode="51" colspan="3"><center><b><></b></center></td>
        <td class="button" keyCode="52" colspan="3"><center><b>||</b></center></td>
        <td class="button" keyCode="53" colspan="3"><center><b>>></b></center></td>
      </tr>
      <tr><td colspan="12" class="line"></td></tr>
      <tr>
        <td class="button" keyCode="40" colspan="4"><center><b>+</b></center></td>
        <td class="button" keyCode="35" colspan="4"><center><b>LIST</b></center></td>
        <td class="button" keyCode="44" colspan="4"><center><b>^</b></center></td>
      </tr>
      <tr>
        <td class="button"              colspan="4"><center><b>VOL</b></center></td>
        <td class="button" keyCode="37" colspan="4"><center><b>GUIDE</b></center></td>
        <td class="button"              colspan="4"><center><b>CHAN</b></center></td>
      </tr>
      <tr>
        <td class="button" keyCode="41" colspan="4"><center><b>-</b></center></td>
        <td class="button" keyCode="36" colspan="4"><center><b>MENU</b></center></td>
        <td class="button" keyCode="45" colspan="4"><center><b>V</b></center></td>
      </tr>
      <tr><td colspan="12" class="line"></td></tr>
      <tr>
        <td                             colspan="4"><center><b>&nbsp</b></center></td>
        <td class="button" keyCode="30" colspan="4"><center><b>^</b></center></td>
        <td                             colspan="4"><center><b>&nbsp</b></center></td>
      </tr>
      <tr>
        <td                             colspan="2"><center><b>&nbsp</b></center></td>
        <td class="button" keyCode="32" colspan="2"><center><b><</b></center></td>
        <td class="button" keyCode="34" colspan="4"><center><b>OK</b></center></td>
        <td class="button" keyCode="33" colspan="2"><center><b>></b></center></td>
        <td                             colspan="2"><center><b>&nbsp</b></center></td>
      </tr>
      <tr>
        <td  keyCode="35" colspan="4"><center><b>&nbsp</b></center></td>
        <td class="button" keyCode="31" colspan="4"><center><b>V</b></center></td>
        <td keyCode="35" colspan="4"><center><b>&nbsp</b></center></td>
      </tr>
      <tr><td colspan="12" class="line"></td></tr>
      <tr>
        <td class="button" keyCode="38" colspan="3"><center><b>EXIT</b></center></td>
        <td class="button" keyCode="46" colspan="3"><center><b><< CHAN</b></center></td>
        <td class="button" keyCode="59" colspan="3"><center><b>DELETE</b></center></td>
        <td class="button" keyCode="43" colspan="3"><center><b>MUTE</b></center></td>
      </tr>
      <tr>
        <td class="button" keyCode="10" colspan="3"><center><b>0</b></center></td>
        <td class="button" keyCode="1" colspan="3"><center><b>1</b></center></td>
        <td class="button" keyCode="2" colspan="3"><center><b>2</b></center></td>
        <td class="button" keyCode="3" colspan="3"><center><b>3</b></center></td>
      </tr>
      <tr>
        <td class="button" keyCode="4" colspan="3"><center><b>4</b></center></td>
        <td class="button" keyCode="5" colspan="3"><center><b>5</b></center></td>
        <td class="button" keyCode="6" colspan="3"><center><b>6</b></center></td>
        <td class="button" keyCode="7" colspan="3"><center><b>7</b></center></td>
     </tr>
      <tr>
        <td class="button" keyCode="8" colspan="3"><center><b>8</b></center></td>
        <td class="button" keyCode="9" colspan="3"><center><b>9</b></center></td>
        <td class="button" keyCode="11" colspan="3"><center><b>.</b></center></td>
        <td class="button" keyCode="12" colspan="3"><center><b>Enter</b></center></td>
     </tr>
      <tr>
        <td class="button" keyCode="20" colspan="3"><center><b>YELLOW</b></center></td>
        <td class="button" keyCode="21" colspan="3"><center><b>BLUE</b></center></td>
        <td class="button" keyCode="22" colspan="3"><center><b>RED</b></center></td>
        <td class="button" keyCode="23" colspan="3"><center><b>GREEN</b></center></td>
      </tr>
   </tbody>
   </table>

</body>
</html>

To process the events triggered by my httpRemote, I reuse a script using the “Python Script” I wrote to handle my Flirc IR remote device events. How I control my Harmony Hub with an $8 remote

"automations.yaml" snippet":

- alias: Remote Key Pressed
  id: '1571938694985'
  description: ''
  trigger:
  - event_data: {}
    event_type: keyboard_remote_command_received
    platform: event
  condition: []
  action:
    - service: python_script.control_hub
      data_template:
        key_code: '{{ trigger.event.data.key_code }}'
        key_source: '{{ trigger.event.data.device_descriptor }}'
        current_activity: "{{ state_attr('remote.hub_3911_master_bedroom', 'current_activity') }}"
        log_level: 'warn'

Python script code for service: python_script.control_hub

'''
Get Harmony Hub Command
'''

########################
# Parameters
########################
entity = data.get('entity_id', "remote.hub_3911_master_bedroom")
activity = data.get('current_activity')
code = data.get('key_code')
source = data.get('key_source')
loglevel = data.get('log_level', 'warn')

indent="     "
logs = {'warn': logger.warn}
logger = logs[loglevel]

########################
# keyMap for Flirc 'keyboard_remote_command_received' event key_codes
########################

keyMap = {
  ### GROUP1 ###
  "60": "tv|o",
  "61": "bluray|o",
  "62": "aux|o",
  "63": "cable|o",
  "64": "stream|o",
  "65": "audio|o",
  ### GROUP2 ###
  "20": "yel",
  "21": "blu",
  "22": "red",
  "23": "grn",
  "24": "app1",
  "25": "app2",
  "26": "app3",
  "27": "input",
  "28": "enter",
  ### GROUP3 ###
  "30": "up",
  "31": "down",
  "32": "left",
  "33": "right",
  "34": "ok",
  "35": "list",
  "36": "menu",
  "37": "guide",
  "38": "back",
  ### GROUP4 ###
  "40": "vol+",
  "41": "vol-",
  "43": "vol><",
  "44": "chan+",
  "45": "chan-",
  "46": "chan<",
  ### GROUP5 ###
  "50": "<<",
  "51": "<>",
  "52": "><",
  "53": ">>",
  "57": "rec",
  "58": "stop",
  "59": "eject",
  ### GROUP6 ###
  "1" : "1",
  "2" : "2",
  "3" : "3",
  "4" : "4",
  "5" : "5",
  "6" : "6",
  "7" : "7",
  "8" : "8",
  "9" : "9",
  "10": "0",
  "11": ".",
  "12": "enter"
}

########################
# hubCommands
########################
hubCommands = {
  'Bedroom': {
    'Watch DirecTV': {
      "vol+" : {"device": "Sonos PLAYBAR", "command": "VolumeUp"},
      "vol-" : {"device": "Sonos PLAYBAR", "command": "VolumeDown"},
      "vol><": {"device": "Sonos PLAYBAR", "command": "Mute"},
      "<<"   : {"device": "DirecTV Genie", "command": "Rewind"},
      "<>"   : {"device": "DirecTV Genie", "command": "Play"},
      "><"   : {"device": "DirecTV Genie", "command": "Pause"},
      ">>"   : {"device": "DirecTV Genie", "command": "FastForward"},
      "chan+": {"device": "DirecTV Genie", "command": "ChannelUp"},
      "chan-": {"device": "DirecTV Genie", "command": "ChannelDown"},
      "chan<": {"device": "DirecTV Genie", "command": "ChannelPrev"},
      "up"   : {"device": "DirecTV Genie", "command": "DirectionUp"},
      "down" : {"device": "DirecTV Genie", "command": "DirectionDown"},
      "left" : {"device": "DirecTV Genie", "command": "DirectionLeft"},
      "right": {"device": "DirecTV Genie", "command": "DirectionRight"},
      "ok"   : {"device": "DirecTV Genie", "command": "Select"},
      "list" : {"device": "DirecTV Genie", "command": "List"},
      "menu" : {"device": "DirecTV Genie", "command": "Menu"},
      "guide": {"device": "DirecTV Genie", "command": "Guide"},
      "back" : {"device": "DirecTV Genie", "command": "Exit"},
      "rec"  : {"device": "DirecTV Genie", "command": "Record"},
      "stop" : {"device": "DirecTV Genie", "command": "Stop"},
      "eject": {"device": "DirecTV Genie", "command": "Red"},
      "."    : {"device": "DirecTV Genie", "command": "-"},
      "enter": {"device": "DirecTV Genie", "command": "enter"},
      "num"  : {"device": "DirecTV Genie", "command": "0"}
    },
    'Watch Fire TV': {
      "vol+" : {"device": "Sonos PLAYBAR", "command": "VolumeUp"},
      "vol-" : {"device": "Sonos PLAYBAR", "command": "VolumeDown"},
      "mute" : {"device": "Sonos PLAYBAR", "command": "Mute"},
      "<<"   : {"device": "Amazon Fire TV Stick", "command": "Rewind"},
      "<>"   : {"device": "Amazon Fire TV Stick", "command": "Play"},
      "><"   : {"device": "Amazon Fire TV Stick", "command": "Pause"},
      ">>"   : {"device": "Amazon Fire TV Stick", "command": "FastForward"},
      "rec"  : {"device": "Amazon Fire TV Stick", "command": "Record"},
      "stop" : {"device": "Amazon Fire TV Stick", "command": "Stop"},
      "eject": {"device": "Amazon Fire TV Stick", "command": "Red"},
      "up"   : {"device": "Amazon Fire TV Stick", "command": "DirectionUp"},
      "down" : {"device": "Amazon Fire TV Stick", "command": "DirectionDown"},
      "left" : {"device": "Amazon Fire TV Stick", "command": "DirectionLeft"},
      "right": {"device": "Amazon Fire TV Stick", "command": "DirectionRight"},
      "ok"   : {"device": "Amazon Fire TV Stick", "command": "OK"},
      "list" : {"device": "Amazon Fire TV Stick", "command": "Home"},
      "menu" : {"device": "Amazon Fire TV Stick", "command": "Menu"},
      "back" : {"device": "Amazon Fire TV Stick", "command": "Back"}
    },
    'Watch Antenna TV': {
      "vol+" : {"device": "Sonos PLAYBAR", "command": "VolumeUp"},
      "vol-" : {"device": "Sonos PLAYBAR", "command": "VolumeDown"},
      "mute" : {"device": "Sonos PLAYBAR", "command": "Mute"},
      "chan+": {"device": "Vizio TV", "command": "ChannelUp"},
      "chan-": {"device": "Vizio TV", "command": "ChannelDown"},
       "."   : {"device": "Vizio TV", "command": "-"},
      "num"  : {"device": "Vizio TV", "command": "0"}
    },
    'PowerOff': {
      "vol+" : {"device": "Sonos PLAYBAR", "command": "VolumeUp"},
      "vol-" : {"device": "Sonos PLAYBAR", "command": "VolumeDown"},
      "mute" : {"device": "Sonos PLAYBAR", "command": "Mute"}
    }
  },
  'LivingRoom': {
    'Watch DirecTV': {
      "vol+" : {"device": "JBL Amp", "command": "VolumeUp"},
      "vol-" : {"device": "JBL Amp", "command": "VolumeDown"},
      "vol><": {"device": "JBL Amp", "command": "Mute"},
      "<<"   : {"device": "DirecTV Mini-Genie Client", "command": "Rewind"},
      "<>"   : {"device": "DirecTV Mini-Genie Client", "command": "Play"},
      "><"   : {"device": "DirecTV Mini-Genie Client", "command": "Pause"},
      ">>"   : {"device": "DirecTV Mini-Genie Client", "command": "FastForward"},
      "chan+": {"device": "DirecTV Mini-Genie Client", "command": "ChannelUp"},
      "chan+": {"device": "DirecTV Mini-Genie Client", "command": "ChannelUp"},
      "chan-": {"device": "DirecTV Mini-Genie Client", "command": "ChannelDown"},
      "chan<": {"device": "DirecTV Mini-Genie Client", "command": "ChannelPrev"},
      "up"   : {"device": "DirecTV Mini-Genie Client", "command": "DirectionUp"},
      "down" : {"device": "DirecTV Mini-Genie Client", "command": "DirectionDown"},
      "left" : {"device": "DirecTV Mini-Genie Client", "command": "DirectionLeft"},
      "right": {"device": "DirecTV Mini-Genie Client", "command": "DirectionRight"},
      "ok"   : {"device": "DirecTV Mini-Genie Client", "command": "Select"},
      "list" : {"device": "DirecTV Mini-Genie Client", "command": "List"},
      "menu" : {"device": "DirecTV Mini-Genie Client", "command": "Menu"},
      "guide": {"device": "DirecTV Mini-Genie Client", "command": "Guide"},
      "back" : {"device": "DirecTV Mini-Genie Client", "command": "Exit"},
      "back" : {"device": "DirecTV Mini-Genie Client", "command": "Exit"},
      "eject": {"device": "DirecTV Mini-Genie Client", "command": "Red"},
      "."    : {"device": "DirecTV Mini-Genie Client", "command": "-"},
      "enter": {"device": "DirecTV Mini-Genie Client", "command": "enter"},
      "num"  : {"device": "DirecTV Mini-Genie Client", "command": "0"}
    },
    'Watch Fire TV': {
      "vol+" : {"device": "JBL Amp", "command": "VolumeUp"},
      "vol-" : {"device": "JBL Amp", "command": "VolumeDown"},
      "mute" : {"device": "JBL Amp", "command": "Mute"},
      "<<"   : {"device": "Amazon Gen3 Fire TV", "command": "Rewind"},
      "<>"   : {"device": "Amazon Gen3 Fire TV", "command": "Play"},
      "><"   : {"device": "Amazon Gen3 Fire TV", "command": "Pause"},
      ">>"   : {"device": "Amazon Gen3 Fire TV", "command": "FastForward"},
      "rec"  : {"device": "Amazon Gen3 Fire TV", "command": "Record"},
      "stop" : {"device": "Amazon Gen3 Fire TV", "command": "Stop"},
      "eject": {"device": "Amazon Gen3 Fire TV", "command": "Red"},
      "up"   : {"device": "Amazon Gen3 Fire TV", "command": "DirectionUp"},
      "down" : {"device": "Amazon Gen3 Fire TV", "command": "DirectionDown"},
      "left" : {"device": "Amazon Gen3 Fire TV", "command": "DirectionLeft"},
      "right": {"device": "Amazon Gen3 Fire TV", "command": "DirectionRight"},
      "ok"   : {"device": "Amazon Gen3 Fire TV", "command": "OK"},
      "list" : {"device": "Amazon Gen3 Fire TV", "command": "Home"},
      "menu" : {"device": "Amazon Gen3 Fire TV", "command": "Menu"},
      "back" : {"device": "Amazon Gen3 Fire TV", "command": "Back"}
    },
    'Watch HTPC': {
      "vol+" : {"device": "JBL Amp", "command": "VolumeUp"},
      "vol-" : {"device": "JBL Amp", "command": "VolumeDown"},
      "mute" : {"device": "JBL Amp", "command": "Mute"},
      "num"  : {"device": "LG TV", "command": "0"},
       "."   : {"device": "LG TV", "command": "-"}
    },
    'PowerOff': {
      "vol+" : {"device": "JBL Amp", "command": "VolumeUp"},
      "vol-" : {"device": "JBL Amp", "command": "VolumeDown"},
      "mute" : {"device": "JBL Amp", "command": "Mute"}
    }
  }
}

########################
# sendCommand
########################
def sendCommand(hass, logger, location, hub):
  global activity, code, keyMap, hubCommands, indent

  indent = '         '
  logger(indent)
  logger("    ## Send '{} TV Remote' Command to: '{}'".format(location, hub))

# Validate Data
  if hub is None:
    return logger(indent+"Abort: enityId is missing")
  elif activity is None:
    return logger(indent+"Abort: activityName is missing")
  elif code is None:
    return logger(indent+"Abort: keyCode is missing")
  elif keyMap.get(code) is None:
    return logger(indent+"Abort: keyMap is missing for remote code: {}".format(code))
    
# Determine service action and service data values
  service_action = 'send_command'
  service_data = {'entity_id' : hub}

  if location == "Bedroom" and keyMap[code] == "tv|o":
    logger(indent+"media_player called: 'volume_set'")
    hass.services.call('media_player', 'volume_set', {'entity_id': 'media_player.master_bedroom', 'volume_level': 0.1}, False)
    logger(indent+"media_player called: 'select_source'")
    hass.services.call('media_player', 'select_source', {'entity_id': 'media_player.master_bedroom', 'source': 'Classic Rock Radio'}, False)
    logger(indent+"media_player called: 'set_sleep_timer'")
    hass.services.call('sonos', 'set_sleep_timer', {'entity_id': 'media_player.master_bedroom', 'sleep_time': 3600}, False)
    service_action = 'turn_off'
  elif keyMap[code] is "input":
    # toggle activities
    service_action = 'turn_on'
    if activity == 'Watch DirecTV':
      service_data.update({'activity': 'Watch Fire TV'})
    elif activity == 'Watch Fire TV':            
      service_data.update({'activity': 'Watch Antenna TV'})
    else:
      service_data.update({'activity': 'Watch DirecTV'})
  elif int(code) >= 1 and int(code) <= 10 and hubCommands[location].get(activity,{}).get('num') is not None:
    # Numeric Key Pressed on supported device
    service_action = 'send_command'
    service_data.update(hubCommands[location][activity]['num'])
    if int(code) != 10:
      service_data['command'] = code
    else:
      service_data['command'] = '0'
  elif hubCommands[location].get(activity,{}).get(keyMap[code]) is not None:
    # Get device command
    service_action = 'send_command'
    service_data.update(hubCommands[location][activity][keyMap[code]])
  else:
    return logger(indent+"Abort: hubCommand is invalid for activity: '{}' or keyMap: '{}'".format(activity, keyMap[code]))

  if service_action == 'send_command' and service_data['command'] == 'FastForward':
     service_data.update({'hold_secs': 1})
     
  logger(indent+"remote called: '{}'".format(service_action))
  hass.services.call('remote', service_action, service_data, False)
  logger(indent+"Service Called, service_data: {}".format(service_data))

  if location == 'Bedroom' and service_action == 'turn_on':
    # Stop Sleep timer and set initial volume  
    logger(indent+"media_player called: 'volume_set'")
    hass.services.call('media_player', 'volume_set', {'entity_id': 'media_player.master_bedroom', 'volume_level': 0.25}, False)
  
  return logger(indent+"Exit SendCommand")

########################
####### MAIN ###########
########################
logger("\n")
logger('#### Running Python_Script: "control_hub"')
logger(indent+"using input data:")
logger(indent+"entity: '{}'".format(entity))
logger(indent+"activity: '{}'".format(activity))
logger(indent+"key: '{}'".format(code))
logger(indent+"loglevel: '{}'".format(loglevel))

hass.bus.fire('control_hub_event', { "entity_id": entity, "state": "send_command", "key_code": code, "current_activity": activity })

if source == '/dev/input/by-id/usb-flirc.tv_flirc-event-kbd':
  sendCommand(hass, logger, 'LivingRoom', 'remote.hub_3911_living_room')
elif source == '/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd':
  sendCommand(hass, logger, 'Bedroom', 'remote.hub_3911_master_bedroom')
else:
  logger(indent+"Abort: Invalid key-source: '{}'".format(source))
  
hass.bus.fire('control_hub_event', { "entity_id": entity, "state": "command_sent", "key_code": code, "current_activity": activity })

Summary:
Overalll, it works quite well and because regular HTML is used, endless modifications can be made to suit your needs with some basic HTML tweaking.

It runs fairly slow on my 6 year old Kindle Voyage eBook. But I attribute that to the speed my old Kindle doesn’t have and think newer Kindles will be more responsive. The big advantage for me is that the battery works for weeks and has a great soft backlight for night time use and can be used in direct sunlight too.

Since my httpRemote only uses standard HTML this will run great on any smart device that implements the new “run as HTML app” in their browser.

I tested on my android tablet and the FireStick ‘Silk’ Browser and they both look great and the response is pretty speedy and quite useable.

-Regards

,

6 Likes

I have no kindle book.

but I want to buy it for your project

It can make seemless life style with Kindle without voice command.

I’ll buy kindle…

1 Like

I’ll never use voice command bots. Alexa go talk to yourself.

Hi, this really works fine. Thanks.

I tried to read sensor values too, but I have had no success so far.

  function getState(sensorentity,htmlobject,jsonelement = 'state' ) {
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", "http://192.168.178.46:8123/api/states/"+sensorentity);
    xhttp.setRequestHeader("Content-Type", "application/json");
    xhttp.setRequestHeader("Authorization", "Bearer  ABCDEFG");
    xhttp.addEventListener('load', function(event) {
      if (xhttp.status >= 200 && xhttp.status < 300) {
          document.getElementById(htmlobject).innerHTML =  JSON.parse(xhttp.responseText)[jsonelement];
      } else {
          console.warn(xhttp.statusText, xhttp.responseText);
      }
    });
    xhttp.send();
  };

This works in Firefox but not on the Kindle-Browser. Any idea?

1 Like

This is very useful, as I was just thinking about creating a static HTML for media player control from mobile phone. I will try to copy/adjust your code to create a set of buttons (kitchen volume up, bedroom mute, etc).

1 Like

did you succeed?

@HeadHodge could you provide a documentation or something like a step by step instruction for people that cannot overlook the design?
I Really want to create a Panel for my iPod Touch 1g, lol

if you could give me a smsll example of what your looking for, i could.

I still use this everyday, and have ‘refined’ it much over the years

Im trying to make a minimalistic UI for my potato-device/s.
My HTML-Skills are low-tier basic. Therefore I would really appreciate if you could provide minimalistic code for e.g. one button only if you do not mind. No problem if this is too much of a hasstle for you though.

Thanks in advance.

If youre ablle to spend some time testing and are not in a hurry, ill behappy to help.

i just started a new project and helping you would be beneficisl to my project.

if you want to get started just go to my new forum and message me there http://minionLogic.com Let me know if you have any problems

1 Like

Gonna have a look and report to you via dm.