Closed Mariusmssj closed 4 years ago
any idea what could be causing this?
You would have to provide full logs, but the exception is caused by GetDevicePowerStatus()
returning unexpected value, so the power status is not known at that particular moment.
Can't you simply handle the exception?
That being said, I'd suggest taking advantage of CEC_OPCODE_GIVE_DEVICE_POWER_STATUS (if your TV responds to it), that way the TV will send you back its power status when it's ready, even if it's busy at the moment of the request.
Thank you, will do that and will wrap it with an exception handling as well
That being said, I'd suggest taking advantage of CEC_OPCODE_GIVE_DEVICE_POWER_STATUS (if your TV responds to it), that way the TV will send you back its power status when it's ready, even if it's busy at the moment of the request.
Sorry to be asking more questions.
Using CEC_OPCODE_GIVE_DEVICE_POWER_STATUS gives a wrong reading. When I run this with the TV off:
import cec
cec.init()
status = cec.Device(cec.CECDEVICE_TV).transmit(cec.CEC_OPCODE_GIVE_DEVICE_POWER_STATUS)
print("Transmit Status: {0}".format(status))
d = cec.Device(5)
print("Is on Status: {0}".format(d.is_on()))
I get the following output:
Transmit Status: True Is on Status: False
Am I doing something wrong?
First of all, you have a device mismatch. cec.CECDEVICE_TV
is equal to zero, if your TV has a different logical address, you have to change that. But in the other issue you indicated that logical address 5 is your AV receiver, so, what device are you actually trying to monitor?
Second, transmit()
returns True
because it was successful, you successfully sent the request. But that doesn't tell you anything about the power status of the device, you have to wait for its response (in the command handler).
ahh I see, thank you and sorry about this, I am new to python and I am just trying to figure things out. I got a smart switch that I want to turn on/off based on if the receiver has been turned on or off. And I came across this library which has helped a lot, but I did make some mistakes. It does work but I wanted to know why I was getting the error and if can be made more efficient by using callback calls. Got my code below if interested:
import cec
import time
import configparser
from tuya.devices import TuyaSmartSwitch
cec.init()
#get config from the file
CONFIG = configparser.ConfigParser()
CONFIG.read("config.ini")
try: #connect to the smart switch
device = TuyaSmartSwitch(
username=CONFIG["TUYA"]["username"],
password=CONFIG["TUYA"]["password"],
location=CONFIG["TUYA"]["location"],
device=CONFIG["TUYA"]["device"],
)
except:
print("Could not connect to the switch")
quit()
current_status = True
receiver_state = True
print("Script started successfully")
def main():
while True:
if check_status_change():
if receiver_state: #if the receiver is on turn on smart switch
device.turn_on()
else: #if the receiver is off turn off smart switch
device.turn_off()
time.sleep(5) #delay the checks to every 2 seconds
#Check if receiver has been turned on or off
def check_status_change():
global current_status
global receiver_state
try:
receiver_state = cec.Device(5).is_on() #check if the receiver is on
except:
print ("Failed power state check for receiver @:{0}".format(datetime.datetime.now()))
if current_status is not receiver_state: #if the state has changed
current_status = receiver_state
return True #something has changed
else:
return False
if __name__ == "__main__":
main()
Thank you for your help @nforro :)
Ok, I'd do something like this:
import sys
import time
import cec
class Receiver:
def __init__(self, address, callback, log=False):
self.address = address
self.callback = callback
self.device = cec.Device(self.address)
cec.add_callback(self._command_event, cec.EVENT_COMMAND)
if log:
cec.add_callback(self._log_event, cec.EVENT_LOG)
cec.init()
def loop(self, interval):
while True:
self.device.transmit(cec.CEC_OPCODE_GIVE_DEVICE_POWER_STATUS)
time.sleep(interval)
def _command_event(self, event, command):
if command['initiator'] == self.address and \
command['opcode'] == cec.CEC_OPCODE_REPORT_POWER_STATUS:
status = command['parameters'][0]
if status == 0x00:
self.callback('STANDBY')
elif status == 0x01:
self.callback('RUNNING')
def _log_event(self, event, level, time, message):
sys.stderr.write('CEC [{0}]: {1}\n'.format(time, message))
sys.stderr.flush()
def power_status_callback(status):
if status == 'STANDBY':
# turn off the switch
pass
elif status == 'RUNNING':
# turn on the switch
pass
def main():
receiver = Receiver(5, power_status_callback, log=True)
try:
receiver.loop(2)
except KeyboardInterrupt:
return
if __name__ == '__main__':
main()
I suggest that you keep logging active until you figure out exactly what's going on. It's possible your AV receiver doesn't support CEC_OPCODE_GIVE_DEVICE_POWER_STATUS
, but you should see that in the logs. It's also possible it does send something when it turns off and on, so no polling might be necessary. Again, you would see that in the logs.
That's brilliant thank you. Seems to work really well :)
When extracting details about found devices the code below:
gives the following output:
However, just checking if they are active works fine:
Output:
I got a script that checks for TV being turned on or off every 2 seconds and it seems to work for for few hours or so but then always crashes with an error OSError: Power status not found any idea what could be causing this? Thank you