Just a bit of explanation of what will follow:
- sensor.media_station_w is a sensor which measure the power consumption of the TV
- media_player.sony_bravia_tv is the TV itself with bravia integration
- media_player.bravia_4k_gb_atv3 is the TV with android integration (is not required, I added this later for other meanings)
- 172.31.31.145 is the IP of my TV
This is my appdaemon app:
import appdaemon.plugins.hass.hassapi as hass
import json
import requests
from bravia_tv import BraviaRC
class SonyPowerManagement(hass.Hass):
def initialize(self):
self.log("***** Sony Power Management *****")
self._host = self.args["host"]
self._pin = self.args["pin"]
self._policy = None
self.tv = BraviaRC(self._host)
self.msw = self.get_entity("sensor.media_station_w")
self.mps = self.get_entity("media_player.sony_bravia_tv")
self.mps.listen_state(self.on_turnoff, new="off", duration=300)
self.msw.listen_state(self.on_powerup)
def on_turnoff(self, entity, attribute, old, new, kwargs):
if not self.tv.is_connected():
try:
self.tv.connect(self._pin, 'my_device_id', 'my device name')
except:
self.log('TV not connected!!')
return
self.disable_wol()
self.reboot()
self.network('DROP')
def on_powerup(self, entity, attribute, old, new, kwargs):
if float(old) < 90 < float(new):
self.network('ALLOW')
self.call_service("homeassistant/reload_config_entry", entity_id="media_player.bravia_4k_gb_atv3")
def disable_wol(self):
self.tv.setWolMode(False)
self.log('WOL disabled')
def reboot(self):
jdata = self.tv._jdata_build('requestReboot')
self.tv.bravia_req_json('system', jdata)
self.log('TV rebooted.')
def network(self, policy):
if policy == self._policy:
return
url = 'http://172.31.31.31:6667/sony/network'
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
jdata = json.dumps({'action': policy.upper()})
if requests.post(url, jdata, headers=headers):
self._policy = policy.upper()
self.log('NET policy changed to {}'.format(policy.upper()))
My appdaemon config:
sony_bravia:
module: sony
class: SonyPowerManagement
host: '172.31.31.145'
pin: '1234'
On the host I have the port tcp/6667 opened by this:
import subprocess
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route('/sony/network', methods=['POST'])
def allow_traffic():
action = request.json['action']
cmd = ['/usr/local/bin/sony.sh', action]
print(cmd)
try:
subprocess.run(cmd, check=True)
return jsonify(request.json)
except Exception as e:
return jsonify({"error": str(e)})
if __name__ == "__main__":
app.run()
Finally the script it launches:
#!/bin/bash
IPT=/usr/sbin/iptables
if [ "$1" == "DROP" ];
then
$IPT -L OUTPUT 1 -n | grep 145 || $IPT -I OUTPUT 1 -d 172.31.31.145 -j DROP
fi
if [ "$1" == "ALLOW" ];
then
$IPT -L OUTPUT 1 -n | grep 145 && $IPT -D OUTPUT 1
fi