Hisense U6G (and possibly other) Android TV Control


Hey all, I wanted to share my working configuration for Hisense MQTT control with a 2021 U6G Android TV. As of early 2023 this communication method works for all Android OS Hisense TVs, here is the discrepences reported from other users:

For A7HQ TVs, see this MQTT topic found by Wingnut: Hisense U6G (and possibly other) Android TV Control - #36 by Wingnut ***

For U8G TVs, see this MQTT topic by JasonLee Hisense U6G (and possibly other) Android TV Control - #23 by JasonLee

I want to give credit to ReDaLeRt who’s write up at https://github.com/tiagofreire-pt/Home_Assistant_Hisense_TV got me most of the way, 95% of this is their work, with me figuring out the 5% that has changed.

This was done on a Hisense U6G TV, Home Assistant version is core-2021.10.6 with Mosquito Brooker add-on, this has been updated and is working on 20221213.1


  • You will need to download the app RemoteNow to your Android phone, I do not know if there is an iOS app for this (or if it will work the same).
    FYI, if available, use an older android device that pre-dates the revolving mac address feature (where your phone gives a new mac to the router each time you connect to wifi). On a Pixel 5 (running Android 12) set to send its real MAC to the router, this would not work; however using an older LG G7 (running Android 10) worked just fine.

  • If not already configured, you will need the Mosquito Brooker and Samba addon installed to Home Assistant (under Supervisor).

  • Having Mosquito Explorer installed on a Windows PC will also help with troubleshooting.

Now that all of the pre stuff is out of the way:

  1. Set a static IP for your TV either in the TV GUI or via static lease on your router.
    Take note of both the IP and the MAC of the TV for the steps bellow.

  2. Open the RemoteNow app, find and connect to your TV and then input the pair code. Test that the remote can control the TV.
    Now write down the MAC address of the phone/tablet you used to connect the RemoteNow app to the TV. This should be in WiFi settings, but may be different since every OEM tweaks things different.
    The purpose of this is to authorize/authenticate the MAC of a device to control your TV, which we can now spoof in Home Assistant (or other MQTT brokers)

  3. On a PC, access your Home Assistant Samba share:
    * Windows: \\YOUR_HA_LAN_IP\
    * Linux: smb://YOUR_HA_LAN_IP/

  4. Create a file called ‘hisense.conf’, and save it to ‘/share/mosquitto/’. Paste the code bellow into the file and only change the IP_OF_TV and the MAC_OF_REMOTENOW_ANDROID fields (MAC is in AA:BB:CC:DD:EE:FF format).

connection hisensemqtt
address IP_OF_TV:36669
username hisenseservice
password multimqttservice
bridge_cafile /ssl/hisense.crt
bridge_insecure true
bridge_tls_version tlsv1.2
try_private false
start_type automatic
topic +/remoteapp/# both
  1. In Home Assistant, go to Supervisor, and then Mosquitto Brooker, then configuration tab, make sure your config matches the following (username and password is redacted):
  - username: ********
    password: ********
  active: true
  folder: mosquitto
certfile: fullchain.pem
keyfile: privkey.pem
require_certificate: false
anonymous: false
retain: true
  1. Now from a terminal of a linux system run the following command (inputting your TV IP address):

openssl s_client -host TV_IP_ADDRESS -port 36669 -showcerts

  1. Paste the output into a notepad.

  2. Create a new file called ‘hisense.crt’ and copy ONLY the two certs in the previous step, now save it to /ssl/ folder of Home Assistant Samba share. The file should like like this:


  1. Create an entry for your TV in the ‘known_devices.yaml’ file in ‘/config/KD/’ (input the MAC of your TV).
  icon: 'mdi:television-classic'
  name: 'Hisense TV'
  track: true
  1. Now we will edit the ‘configuration.yaml’ file (in ‘/config/’ folder). Copy the following code into the file.

    - name: "TV - Source"
      state_topic: "/remoteapp/mobile/broadcast/ui_service/state"
      value_template: "{{ value_json.sourceid }}"
    - name: "TV - VOL"
      state_topic: "/remoteapp/mobile/broadcast/platform_service/actions/volumechange"
      value_template: "{{ value_json.volume_value }}"

(OPTIONAL) You can use this to create an on-off switch in Home Assistant.
You will need to input the MAC of your TV for the WOL portion to turn TV on(do not remote the ’ 's), and the MAC of the android you used RemoteNow for the MQTT payload string to turn the TV Off.

  - platform: template
        icon_template: >
          {% if is_state('switch.hisense_tv','on') %}
            {{ 'mdi:television-classic' }}
          {% else %}
            {{ 'mdi:television-classic-off' }}
          {% endif %}
        friendly_name: 'Hisense TV'
        value_template: >
          {{ is_state('device_tracker.hisense_tv', 'home') }}
          service: wake_on_lan.send_magic_packet
            mac: 'MAC_OF_TV'
          service: mqtt.publish
            topic: '/remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey'
            payload: 'KEY_POWER' 
  1. Here is some common commands you can send via scripts or buttons or REST API calls. The example is from my scripts.yaml file
    You need to change the REMOTENOW_MAC to the MAC address of the Android device you connected to the TV via RemoteNow.
  alias: TV - Input TV
  - service: mqtt.publish
      topic: /remoteapp/tv/ui_service/REMOTENOW_MAC$normal/actions/changesource
      payload: '{"displayname":"Channels","hotel_mode":"","httpIcon":"","isDemo":false,"is_lock":"","is_signal":"","sourceid":"1","sourcename":"Tuner"}
  mode: single
  alias: TV - Input HDMI 1
  - service: mqtt.publish
      topic: /remoteapp/tv/ui_service/REMOTENOW_MAC$normal/actions/changesource
      payload: '{"displayname":"HDMI 1","hotel_mode":"","httpIcon":"","isDemo":false,"is_lock":"","is_signal":"","sourceid":"2","sourcename":"HDMI
  mode: single
  alias: TV - Input HDMI 2
  - service: mqtt.publish
      topic: /remoteapp/tv/ui_service/REMOTENOW_MAC$normal/actions/changesource
      payload: '{"displayname":"HDMI 2","hotel_mode":"","httpIcon":"","isDemo":false,"is_lock":"","is_signal":"","sourceid":"3","sourcename":"HDMI
  mode: single
  alias: TV - Input HDMI 3
  - service: mqtt.publish
      topic: /remoteapp/tv/ui_service/REMOTENOW_MAC$normal/actions/changesource
      payload: '{"displayname":"HDMI 3","hotel_mode":"","httpIcon":"","isDemo":false,"is_lock":"","is_signal":"","sourceid":"4","sourcename":"HDMI
  mode: single
  - service: mqtt.publish
      topic: /remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey
      payload: KEY_MUTE
  mode: single
  alias: TV -  Mute
  alias: TV - Volume up
  - service: mqtt.publish
      topic: /remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey
      payload: KEY_VOLUME_UP
  mode: single
  alias: TV - Volume down
  - service: mqtt.publish
      topic: /remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey
      payload: KEY_VOLUME_DOWN
  alias: TV - Channel up
  - service: mqtt.publish
      topic: /remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey
      payload: KEY_CHANNELUP
  alias: TV - Channel down
  - service: mqtt.publish
      topic: /remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey
      payload: KEY_CHANNELDOWN
  alias: TV - Home
  - service: mqtt.publish
      topic: /remoteapp/tv/remote_service/REMOTENOW_MAC$normal/actions/sendkey
      payload: KEY_HOME

Using MQTT broker and the RemoteNow app, you should be able to see the MQTT topic for streaming app inputs and any other buttons I did not list

You can also check out ReDaLeRt’s lovelace setup in the github link above.
I have my own custom-made solution for TV remote control so I did not get too deep into setting up lovelace cards for this aspect, hence why I did not include any lovelace configuration in my writeup.


It works! Thank you so much! I was stuck for hours. It could grab the volume and the tv source, but it couldn’t send any commands. Turns out my MAC address wasn’t entered with the right format


Did you ever come up with a better way for establish whether the TV is on? the device tracker would be ok but my TV is WOL via wifi so it always appears home.

Great add-on this though.

To make Home Assistant aware of when the TV is ON vs OFF I have it change an input helper (i use text but you could use binary).
When I want to turn it on or off I have it run a script that performs the action (WOL for ON, MQTT command for off) as well as change the said input helper variable
Now this works all good IF the TV control is done exclusively through home assistant, however this is useless to determine if the TV got turned on via IR remote control (or the RemoteNow app)

Unfortunately the only MQTT topics I could find that updated even when the IR remote is used are $SYS topics… which continue to update even with the TV turned off, so that is a no go.
So I ended up using a ping sensor (binary sensor) with automations. The ping is set to 30 second intervals which means the sensor is not instantaneously alert … but reduces network traffic.
if ping sensor = on AND your switch or input helper is off then change to ON.
If ping sensor = off AND tv input_text shows on, then set input_text to off

1 Like

brilliant thanks

Would it be possible to use the picture settings to indicate when the tv was on or off? @sehaas

I’m noticing when the TV is on there are three menu flags with value ‘-1’ (Overscan, Aspect Ratio and Panoramic). When switching the TV off, those three flags flip to ‘1’.

Topic: /remoteapp/mobile/broadcast/platform_service/data/picturesetting

I’m using a U8G, but assuming something similar is happening with the U6G

I didn’t read the whole thread, so maybe it was mentioned earlier.
The TV publishes to /remoteapp/mobile/broadcast/platform_service/actions/tvsleep before shutting down.

Maybe that helps?

I do see tvsleep get published on power off, but I don’t see a related publish to when the TV is powered on.

Topic: /remoteapp/mobile/broadcast/platform_service/data/picturesetting

This topic updates when the TV is powered off and on, with the flipping of those three flags from -1 to 1 (Overscan, Aspect Ratio and Panoramic).

We can also use the following action to request the current picturesetting information, and therefore the on/off state

Topic: /remoteapp/tv/platform_service/MY_PHONE_MAC$normal/actions/picturesetting
action: { "action": "get_menu_info" }

I don’t know how to pull the picturesetting information to use as a switch in HA?

And I’m not sure how the current TV device tracker implementation is supposed to be working, mine always shows as away, whether the TV is on or off.

From what I have seen, only the # MQTT topics still TX after the TV is off, you can not talk to the /remoteapp/ topics once the TV is off.
If the tvsleep state changes (not just gets republished) then you can put that topic as a sensor (like in my example for volume), otherwise using the picturesetting flag should also work.
Then use an automation with that as a trigger to then set the switch to off (or whatever you want to use as an indicator).

I use NMAP integration to scan my network for device tracker, however I wanted a faster update exclusively for the TV. Thus I used a ping binary sensor:

  - platform: ping
    host: 192.168.x.y
    name: "device name"
    count: 2
    scan_interval: 30

I am not at home right now so I cant do any testing in regards to those MQTT topics.
I have actually been fighting a different battle with this TV. I bought a second U6G TV for another room and set up a second bridge in HA (the .conf file in mosquitto). Now, when both TVs are on, it causes a mqtt flood between them that DOS’s both TVs (even IR control wont work, have to unplug one from network). I finally tracked the issue down to HA bridging both TVs.
My new plan is to setup another HA and use it specifically to control the second TV (gonna first try doing a second HA docker instance, otherwise I will run it on a spare R-Pi).

There is probably variation from Hisense model to model. I’m guessing the U6G and U8G are fairly similar, at least more so than any of the other Hisense models. I’ve noticed with the U8G, when I press the power button and it goes into standby, that it’s still eating up 10W/hr. It seems to be pretty active when ‘off’

While off, I’m still able to send mqtt remote actions, including KEY_POWER to turn the screen back on. This seems to be different from what I’ve seen a lot of others post with Hisense TVs.

I’m also still able to send “get_menu_info” action while the TV is in standby. Maybe this is because the TV comes with both the RemoteNowServer.apk and RemoteNow.apk installed. And it’s running it’s own remoteapp instance that can still be used to send commands?

I’ve been wondering about the 10W power consumption, and if this is normal. I have almost everything turned off on the TV (google assistant, mic) and use it as a dumb TV with a connected streaming device.

I will try to use the picturesettings info as my on/off sensor, I just don’t know how to pull the info out of the topic in HA and use that in a template. I’m new to making sensors and switches with MQTT.

You will need to add the sensor into configuration.yaml for that topic as I showed with input/volume.
Once you restart HA, and power on/off the TV, show me what that sensor shows in states (under developer tools). Might be able to just do an automation trigger off that, but will likely need an input_helper that uses a value_template off of the sensor

You must be right about variations between models, the U6G does not send KEY_POWER when off.
The nic is not 100% off because it gets some of the (i think it was called) SYS topics, but nothing to/from remoteapp/ topics after it is off. Hence for the U6G you have to use WOL to turn on.

Are you using wifi or wired for connection? The 10w is a little higher then I would have imagined but not that surprising since smart TVs are a computer with a UHF/VHF tuner, even with assistant and other things off). To keep wifi radio on, IR on, and OS in a lower power state likely takes some juice (i also think some USB ports are wired to always provide power).

Alright, I figured out what’s going on. If you toggle USB debugging on (developer options), the TV will never go into full sleep. It will stay in a more active mode (don’t know the name for this) keeping system processes alive, including the MQTT server. This is why I could still send MQTT commands to power the TV on and check the screen status topics. The downside to this is that even when off, the TV is still consuming 10W/hr.

Toggling USB debugging off, the TV goes into full sleep using 0.3-0.5W/hr.

So I guess I’m back to trying to make WOL work across VLANs and relying on pings for on/off status.

EDIT: When the TV is off, just having a device plugged into the eARC port causes the TV to go from 0.3W to 40-50W for ~30s every minute. I also noticed that with the TV in full sleep I can no longer keep my streaming device playing audio. The U8Gs native audio only mode with screen off uses 33W/hr. Long story short, I prefer the way the TV behaves with USB debugging on, even if it’s always consuming 10W.

That makes sense on both the MQTT topics and the power aspect.

Does it still only consume the 10w in debugging mode even with device plugged into eARC port?

Leaving it on debug mode would certainly remove the WOL over VLAN headache.
Was going to say may just be easier to put another HA instance (or at least some other device on the other VLAN that you could send a command over TCP to) that could then be coded to send your WOL

EDIT: going through the settings under USB debugging, I think the change is specifically due to USB configuration. Turning on USB debugging defaults USB into MTP configuration. having that on stops the TV from going to full sleep. Changing the USB configuration to charging lets the TV fully sleep while also keeping USB debugging enabled. This may be useful for anyone that wants to use ADB.

10W seems to be the minimum power consumption of the OS when it’s active (65U8G), but screen is completely off. USB debugging just appears to keep the system from going to sleep. HDMI inputs have a small impact, as well as WiFi. With no WiFi or ethernet, and no HDMI inputs, the TV is at ~9.8W/hr. Using WiFi and one HDMI input for my FireTV, I’m at about 10.7W. In this TV state I don’t see the power cycle between 0 and 50W every minute when using the eARC port, I’m not sure what that is about.

So getting back to pulling the TV on/off status. With your volumechange topic, it seems much more straight forward. For picture settings there is 50menus of data returned, and I only want to pull the menu_flag status (-1 = on, 1 = off) of menu_id 11 (Aspect Ratio). How do I only grab that bit for HA.

This is an example of the picturesettings topic:

{"action":"notify_value_changed","menu_info":[{"menu_flag":0,"menu_id":1,"menu_name":"Dynamic Backlight control","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":2,"menu_name":"Backlight Level","menu_value":35,"menu_value_type":"int"},{"menu_flag":1,"menu_id":3,"menu_name":"Mode","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":4,"menu_name":"Pciture Mode","menu_value":3,"menu_value_type":"int"},{"menu_flag":1,"menu_id":5,"menu_name":"Game","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":6,"menu_name":"Contrast","menu_value":20,"menu_value_type":"int"},{"menu_flag":1,"menu_id":7,"menu_name":"Brightness","menu_value":50,"menu_value_type":"int"},{"menu_flag":1,"menu_id":8,"menu_name":"color","menu_value":55,"menu_value_type":"int"},{"menu_flag":1,"menu_id":9,"menu_name":"Tint","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":10,"menu_name":"Sharpness","menu_value":10,"menu_value_type":"int"},{"menu_flag":-1,"menu_id":11,"menu_name":"AspectRatio","menu_value":3,"menu_value_type":"int"},{"menu_flag":1,"menu_id":12,"menu_name":"Direct","menu_value":0,"menu_value_type":"int"},{"menu_flag":-1,"menu_id":13,"menu_name":"Dot-By-Dot","menu_value":0,"menu_value_type":"int"},{"menu_flag":-1,"menu_id":14,"menu_name":"Panoramic","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":15,"menu_name":"Cinema","menu_value":0,"menu_value_type":"int"},{"menu_flag":-1,"menu_id":16,"menu_name":"Overscan","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":17,"menu_name":"ColorTemperature","menu_value":1,"menu_value_type":"int"},{"menu_flag":191,"menu_id":18,"menu_name":"Motion Enhancement","menu_value":2,"menu_value_type":"int"},{"menu_flag":1,"menu_id":19,"menu_name":"Judder Reduction","menu_value":5,"menu_value_type":"int"},{"menu_flag":1,"menu_id":20,"menu_name":"Blur Reduction","menu_value":5,"menu_value_type":"int"},{"menu_flag":1,"menu_id":21,"menu_name":"Noise Reduction","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":22,"menu_name":"Digital Noise Reduction","menu_value":0,"menu_value_type":"int"},{"menu_flag":-1,"menu_id":23,"menu_name":"Hdmi Dynamic Range","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":24,"menu_name":"Active Contrast","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":25,"menu_name":"color space","menu_value":1,"menu_value_type":"int"},{"menu_flag":1,"menu_id":26,"menu_name":"color(colorTuneColor)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":27,"menu_name":"Hue(colorTuneHue)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":28,"menu_name":"Saturation(ColorTunerSaturation)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":29,"menu_name":"Brightness(ColorTunerBrightness)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":30,"menu_name":"Reset(ResetColorTuner)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":31,"menu_name":"R-offset","menu_value":-1,"menu_value_type":"int"},{"menu_flag":1,"menu_id":32,"menu_name":"G-offset","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":33,"menu_name":"B-offset","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":34,"menu_name":"R-Gain","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":35,"menu_name":"G-Gain","menu_value":-6,"menu_value_type":"int"},{"menu_flag":1,"menu_id":36,"menu_name":"B-Gain","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":37,"menu_name":"Reset(2 point)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":38,"menu_name":"20 point","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":39,"menu_name":"level","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":40,"menu_name":"Red","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":41,"menu_name":"Green","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":42,"menu_name":"Blue","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":43,"menu_name":"Reset(2o point)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":44,"menu_name":"Gamma","menu_value":1,"menu_value_type":"int"},{"menu_flag":1,"menu_id":45,"menu_name":"Input level","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":46,"menu_name":"Gain","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":47,"menu_name":" Restore Gamma Calibration","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":48,"menu_name":"RGB only","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":49,"menu_name":"Apply Picture Settings","menu_value":1,"menu_value_type":"int"},{"menu_flag":1,"menu_id":50,"menu_name":"Reset(ResetPictureSettings)","menu_value":0,"menu_value_type":"int"},{"menu_flag":1,"menu_id":51,"menu_name":"Local Dimming","menu_value":3,"menu_value_type":"int"}],"pic_setting_version":"U4"}

Wow that is a mess, all the templating I have done it is nested with different labels for each layer.

Try adding this to your sensor:

value_template: "{{ value_json.menu_info[10].menu_name }}"

The filter is saying to get the menu_name from line 10 (starting at 0) from the output of menu_info.

If it works, it should output “AspectRatio”. If that works then change menu_name to menu_flag. Then do an automation for when sensor changes from 1 to -1, and another for when it goes from -1 to 1

1 Like
value_template: "{{ value_json.menu_info[10].menu_name }}"

This works perfectly to return Aspect Ratio. But there is a problem with menu_flag

value_template: "{{ value_json.menu_info[10].menu_flag }}"

Nothing is returned. I think this may be because the topic does not include quotes around the menu_flag value. Its just 1 and -1, rather than “1” and “-1”. Is it possible to pull in a value not in quotes?

I checked on my U6G and even with USB debugging on I dont get that specific MQTT message so I can not test it directly.

However, using Template in develop tools I took your JSON data and tried the value template and it worked fine there

Check for typo error, here is what I used:

value_template: "{{ value_json.menu_info[10].menu_flag }}"

Otherwise my next suggestion is to layer 2 sensors. Have the first sensor get your menu_id line using this:

value_template: "{{ value_json.menu_info[10] }}"

then the second senor get the specific data out of it. This also allows you to show on or off:

  - platform: template
      value template: >-
        {% if is_state('1ST_SENSOR_NAME.menu_flag', '1') %} ON
        {% else %} OFF
        {% endif %} 

You could make automations with change from on to off (and another of off to on) as trigger, and then have it change your switch state appropriately.

1 Like

EDIT: I accidentally overwrote my previous post. I figured out that the problem was that there was other json being published to the topic other than the full menu array. That published data doesn’t include “menu_info”, so the filter was not able to return the AspectRatio menu_flag state.

I changed the sensor to a binary sensor and used this if/else statement. This will ignore any JSON that doesn’t return either a 1 or -1

  - platform: mqtt
    name: "TV - Power"
    state_topic: "/remoteapp/mobile/broadcast/platform_service/data/picturesetting"
    value_template: >-
      {% if value_json.menu_info[10].menu_flag == -1 %}
      {% elif value_json.menu_info[10].menu_flag == 1 %}
      {% endif %}

Thank you for that example in the developers tools menu. I was wondering how to debut the json filter, this helped a lot.

Ok good, that was going to be my suggestion to use elseif instead of just if/else.

Yea, that JSON output is completely void of structure. Usually they are nested with unique identifiers so it is WAY easier to pick out the data you need. The menu_info[10] is the “cheat” way to get the data, but it 100% assumes the data structure is the same every single time.
So be willing to bet at some point an update in the TV is going to change the JSON layout of that topic.