Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to "television service" #5

Open
Samfox2 opened this issue Mar 26, 2019 · 17 comments
Open

Switch to "television service" #5

Samfox2 opened this issue Mar 26, 2019 · 17 comments

Comments

@Samfox2
Copy link

Samfox2 commented Mar 26, 2019

As IOS 12.2 is finally released, would it be possible to implement the new television service into this plugin instead of switch service? Volume and source selection could also be implemented over cec protocol.

@dominick-han
Copy link
Owner

This repo got renamed to homebridge-tv-cec and yes it definitely is using the TV service :)

@dominick-han
Copy link
Owner

dominick-han commented Mar 26, 2019

Just published new version on NPM (v0.5.0), let me know if it works great for you :) There might be bugs depends on your TV's implementation of CEC, please feedback and we can work upon them

@Samfox2
Copy link
Author

Samfox2 commented Mar 26, 2019

Sounds great.
I installed it but got the following error message:

[2019-03-26 20:24:18] [TV] Initializing TV-CEC accessory...
/usr/local/lib/node_modules/homebridge-tv-cec/index.js:23
 this.inputs = Object.entries(this.config.devices).map(([port, name]) => {
                      ^

TypeError: Object.entries is not a function
    at new TV (/usr/local/lib/node_modules/homebridge-tv-cec/index.js:23:25)
    at Server._loadAccessories (/usr/local/lib/node_modules/homebridge/lib/server.js:297:29)
    at Server.run (/usr/local/lib/node_modules/homebridge/lib/server.js:87:38)
    at module.exports (/usr/local/lib/node_modules/homebridge/lib/cli.js:45:10)
    at Object.<anonymous> (/usr/local/lib/node_modules/homebridge/bin/homebridge:17:22)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)

@Samfox2
Copy link
Author

Samfox2 commented Mar 26, 2019

This ist the accessory part of my config:

 "accessories": [
        {
            "accessory": "PiTemperature",
            "name": "Raspberry PI Temperature"
        },
        {
            "accessory": "Hyperion",
            "name": "Test-TV Backlight",
            "ambilight_name": "Ambilight",
            "description": "Control the Hyperion TV backlight server. https://github.com/tvdzwan/hyperion",
            "host": "192.168.2.xxx",
            "port": "xxxx"
        },
        {
      "accessory": "TV-CEC",
      "name": "TV",
      "devices": {
        "1": "Sat Receiver",
        "2": "Raspberry Pi",
        "3": "Apple TV"
      }
    }
    ]

@dominick-han
Copy link
Owner

Object.entries() requires at least node 7, which version are you running? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Browser_compatibility

@Samfox2
Copy link
Author

Samfox2 commented Mar 26, 2019

I was on node 6.x. Upgraded to 11 and the plugin starts now, however, TV does not react and after a few seconds I get the following error message:

[TV]Checking TV power status
events.js:173
throw er; // Unhandled 'error' event
^

Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed
at doWrite (_stream_writable.js:411:19)
at writeOrBuffer (_stream_writable.js:399:5)
at Socket.Writable.write (_stream_writable.js:299:11)
at TV.getPowerStatus (/usr/local/lib/node_modules/homebridge-tv-cec/index.js:89:20)
at Characteristic.Active.emit (events.js:197:13)
    at Characteristic.Active.Characteristic.getValue (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Characteristic.js:164:10)
    at Bridge.<anonymous> (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:762:20)
at Array.forEach (<anonymous>)
    at Bridge.Accessory._handleGetCharacteristics (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:726:8)
at HAPServer.emit (events.js:197:13)
Emitted 'error' event at:
at errorOrDestroy (internal/streams/destroy.js:107:12)
at onwriteError (_stream_writable.js:430:5)
at onwrite (_stream_writable.js:461:5)
at doWrite (_stream_writable.js:411:11)
at writeOrBuffer (_stream_writable.js:399:5)
[... lines matching original stack trace ...]
at Bridge.<anonymous> (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:762:20)

@Samfox2
Copy link
Author

Samfox2 commented Mar 26, 2019

Ok, I re-installed the cec client and did a restart and I can now switch the TV on - cool. However - the small rotating wheel at the home app tv icon indicates that the action is not finished. So nothing can be changed after the first signal. Could this mean that there is a callback missing?

@dominick-han
Copy link
Owner

dominick-han commented Mar 27, 2019

Send me the exact model of your TV, and
if you can do this so I can see your CEC streams:

  • Make sure your TV is off
  • Manually run cec-client -d 8
  • Wait for it to be ready
  • Type in tx 10:04 then enter
  • Wait for TV to turn on
  • Copy paste the whole console output from cec-client -d 8 until TV turns on

Then I can debug what's going on with your specific TV :)

@Samfox2
Copy link
Author

Samfox2 commented Mar 27, 2019

I think it is a Toshiba 42X3000PG

This is what the console output looks like:

cec-client -s -d 1

requesting CEC bus information ...
CEC bus information
===================
device #0: TV
address:       0.0.0.0
active source: yes
vendor:        Toshiba
osd string:    TV
CEC version:   1.3a
power status:  on
language:      eng



cec-client -d 8

log level set to 8
No device type given. Using 'recording device'
CEC Parser created - libCEC version 4.0.2
no serial port given. trying autodetect: 
 path:     Raspberry Pi
 com port: RPI

opening a connection to the CEC adapter...
TRAFFIC: [              37]     << e0
TRAFFIC: [              97]     << e0:8c
TRAFFIC: [             268]     >> 0e:00:8c:01
TRAFFIC: [            1158]     << e0:8c
TRAFFIC: [            1328]     >> 0e:00:8c:01
TRAFFIC: [            2218]     << 11
TRAFFIC: [            2489]     << 11
TRAFFIC: [            2760]     << 1f:84:20:00:01
TRAFFIC: [            2911]     << 10:47:43:45:43:54:65:73:74:65:72
TRAFFIC: [            3211]     << 10:8f
TRAFFIC: [            3392]     >> 01:00:47:01
TRAFFIC: [            3461]     >> 01:90:01
waiting for input
tx 10:04
TRAFFIC: [           90249]     << 10:04
waiting for input
TRAFFIC: [           93761]     >> 0f:87:00:00:39
TRAFFIC: [           93762]     << 1f:87:00:15:82
TRAFFIC: [           93912]     << 1f:87:00:00:39
TRAFFIC: [           95134]     >> 01:a0:00:00:39:02
TRAFFIC: [           95135]     << 10:00:a0:03
TRAFFIC: [           98389]     >> 01:46
TRAFFIC: [           98390]     << 10:47:43:45:43:54:65:73:74:65:72

@dominick-han
Copy link
Owner

Can you wait a little longer after sending in tx 10:04? For about 30-40 seconds until there are no additional outputs on console
(I'm not seeing any traffic regarding power status from the TV)

@Samfox2
Copy link
Author

Samfox2 commented Mar 27, 2019

Sure, this is the complete traffic:

cec-client -d 8
log level set to 8
No device type given. Using 'recording device'
CEC Parser created - libCEC version 4.0.2
no serial port given. trying autodetect: 
 path:     Raspberry Pi
 com port: RPI

opening a connection to the CEC adapter...
TRAFFIC: [              55]     << e0
TRAFFIC: [             116]     << e0:8c
TRAFFIC: [             288]     >> 0e:00:8c:01
TRAFFIC: [            1176]     << e0:8c
TRAFFIC: [            1348]     >> 0e:00:8c:01
TRAFFIC: [            2237]     << 11
TRAFFIC: [            2507]     << 11
TRAFFIC: [            2779]     << 1f:84:20:00:01
TRAFFIC: [            2929]     << 10:47:43:45:43:54:65:73:74:65:72
TRAFFIC: [            3230]     << 10:8f
TRAFFIC: [            3410]     >> 01:00:47:01
TRAFFIC: [            3479]     >> 01:90:01
waiting for input
tx 10:04
TRAFFIC: [           16413]     << 10:04
waiting for input
TRAFFIC: [           19921]     >> 0f:87:00:00:39
TRAFFIC: [           19921]     << 1f:87:00:15:82
TRAFFIC: [           20071]     << 1f:87:00:00:39
TRAFFIC: [           21254]     >> 4f:a6:06:10:56:10
TRAFFIC: [           21422]     >> 01:a0:00:00:39:02
TRAFFIC: [           21423]     << 10:00:a0:03
TRAFFIC: [           21813]     >> 4f:84:30:00:04
TRAFFIC: [           21850]     >> 4f:85
TRAFFIC: [           21943]     >> 4f:90:00
TRAFFIC: [           22341]     >> 0f:84:00:00:00
TRAFFIC: [           22342]     << 1f:84:20:00:01
TRAFFIC: [           22963]     >> 0f:82:00:00
TRAFFIC: [           24595]     >> 0f:87:00:00:39
TRAFFIC: [           24597]     << 1f:87:00:00:39
TRAFFIC: [           25046]     >> 01:a0:00:00:39:02
TRAFFIC: [           25048]     << 10:00:a0:03
TRAFFIC: [           25850]     >> 01:46
TRAFFIC: [           25851]     << 10:47:43:45:43:54:65:73:74:65:72

@Samfox2
Copy link
Author

Samfox2 commented Mar 27, 2019

This is the traffic with a higher debug level:

cec-client -d 31
log level set to 31
No device type given. Using 'recording device'
CEC Parser created - libCEC version 4.0.2
no serial port given. trying autodetect: 
 path:     Raspberry Pi
 com port: RPI

opening a connection to the CEC adapter...
DEBUG:   [              57]     Broadcast (F): osd name set to 'Broadcast'
DEBUG:   [              58]     Open - vc_cec initialised
DEBUG:   [              58]     logical address changed to Free use (e)
NOTICE:  [              58]     connection opened
DEBUG:   [              59]     processor thread started
DEBUG:   [              59]     << Broadcast (F) -> TV (0): POLL
DEBUG:   [              59]     initiator 'Broadcast' is not supported by the CEC adapter. using 'Free use' instead
TRAFFIC: [              59]     << e0
DEBUG:   [             119]     >> POLL sent
DEBUG:   [             120]     TV (0): device status changed into 'present'
DEBUG:   [             120]     << requesting vendor ID of 'TV' (0)
TRAFFIC: [             120]     << e0:8c
TRAFFIC: [             292]     >> 0e:00:8c:01
DEBUG:   [            1180]     expected response not received (87: device vendor id)
TRAFFIC: [            1180]     << e0:8c
TRAFFIC: [            1352]     >> 0e:00:8c:01
DEBUG:   [            2241]     expected response not received (87: device vendor id)
NOTICE:  [            2241]     registering new CEC client - v4.0.2
DEBUG:   [            2241]     detecting logical address for type 'recording device'
DEBUG:   [            2241]     trying logical address 'Recorder 1'
DEBUG:   [            2242]     << Recorder 1 (1) -> Recorder 1 (1): POLL
TRAFFIC: [            2242]     << 11
TRAFFIC: [            2512]     << 11
DEBUG:   [            2783]     >> POLL not sent
DEBUG:   [            2783]     using logical address 'Recorder 1'
DEBUG:   [            2783]     Recorder 1 (1): device status changed into 'handled by libCEC'
DEBUG:   [            2783]     Recorder 1 (1): power status changed from 'unknown' to 'on'
DEBUG:   [            2784]     Recorder 1 (1): vendor = Pulse Eight (001582)
DEBUG:   [            2784]     Recorder 1 (1): CEC version 1.4
DEBUG:   [            2784]     AllocateLogicalAddresses - device '0', type 'recording device', LA '1'
DEBUG:   [            2784]     logical address changed to Recorder 1 (1)
DEBUG:   [            2784]     Recorder 1 (1): osd name set to 'CECTester'
DEBUG:   [            2784]     Recorder 1 (1): menu language set to 'eng'
DEBUG:   [            2784]     GetPhysicalAddress - physical address = 2000
DEBUG:   [            2785]     AutodetectPhysicalAddress - autodetected physical address '2000'
DEBUG:   [            2785]     Recorder 1 (1): physical address changed from ffff to 2000
DEBUG:   [            2785]     << Recorder 1 (1) -> broadcast (F): physical address 2000
TRAFFIC: [            2785]     << 1f:84:20:00:01
NOTICE:  [            2935]     CEC client registered: libCEC version = 4.0.2, client version = 4.0.2, firmware version = 1, logical address(es) = Recorder 1 (1) , physical address: 2.0.0.0, git revision: libcec-4.0.2+30-8adc786~dirty, compiled on Mon Aug 21 09:41:41 UTC 2017 by root@hostname: Name or service not known on Linux 4.4.0-92-generic (armv7l), features: P8_USB, DRM, P8_detect, randr, RPi
DEBUG:   [            2935]     << Recorder 1 (1) -> TV (0): OSD name 'CECTester'
TRAFFIC: [            2935]     << 10:47:43:45:43:54:65:73:74:65:72
DEBUG:   [            3235]     << requesting power status of 'TV' (0)
TRAFFIC: [            3236]     << 10:8f
TRAFFIC: [            3416]     >> 01:00:47:01
DEBUG:   [            3417]     >> TV (0) -> Recorder 1 (1): feature abort ( 0)
TRAFFIC: [            3483]     >> 01:90:01
DEBUG:   [            3483]     >> TV (0) -> Recorder 1 (1): report power status (90)
DEBUG:   [            3484]     TV (0): power status changed from 'unknown' to 'standby'
DEBUG:   [            3484]     expected response received (90: report power status)
waiting for input
tx 10:04
TRAFFIC: [           37861]     << 10:04
waiting for input
DEBUG:   [           41059]     GetPhysicalAddress - physical address = 2000
DEBUG:   [           41060]     physical address unchanged (2000)
TRAFFIC: [           41370]     >> 0f:87:00:00:39
DEBUG:   [           41371]     >> TV (0) -> Broadcast (F): device vendor id (87)
DEBUG:   [           41371]     TV (0): vendor = Toshiba (000039)
DEBUG:   [           41371]     << Recorder 1 (1) -> Broadcast (F): vendor id Pulse Eight (1582)
TRAFFIC: [           41372]     << 1f:87:00:15:82
DEBUG:   [           41520]     replacing the command handler for device 'TV' (0)
DEBUG:   [           41521]     Recorder 1 (1): vendor = Toshiba (000039)
DEBUG:   [           41521]     replacing the command handler for device 'Recorder 1' (1)
DEBUG:   [           41522]     << Recorder 1 (1) -> Broadcast (F): vendor id Toshiba (39)
TRAFFIC: [           41522]     << 1f:87:00:00:39
WARNING: [           41820]     unhandled response received: opcode=87 initiator=1 destination=f response=0
TRAFFIC: [           42761]     >> 01:a0:00:00:39:02
DEBUG:   [           42762]     >> TV (0) -> Recorder 1 (1): vendor command with id (A0)
DEBUG:   [           42762]     sending abort with opcode a0 and reason 'invalid operand' to TV
DEBUG:   [           42762]     << transmitting abort message
TRAFFIC: [           42762]     << 10:00:a0:03
NOTICE:  [           42882]     Unmapped code detected. Please send an email to support@pulse-eight.com with the following details, and if you pressed a key, tell us which one you pressed, and we'll add support for this it.
CEC command: >> 01:a0:00:00:39:02
Vendor ID: Toshiba (000039)
WARNING: [           43002]     unhandled response received: opcode=0 initiator=1 destination=0 response=0
TRAFFIC: [           46267]     >> 01:46
DEBUG:   [           46267]     >> TV (0) -> Recorder 1 (1): give osd name (46)
DEBUG:   [           46268]     << Recorder 1 (1) -> TV (0): OSD name 'CECTester'
TRAFFIC: [           46268]     << 10:47:43:45:43:54:65:73:74:65:72
WARNING: [           46868]     unhandled response received: opcode=47 initiator=1 destination=0 response=0

@Samfox2
Copy link
Author

Samfox2 commented Mar 28, 2019

Ok, I got it 2 work by deactivating the handler stuff in the setPowerStatus routine (not nice but ok for now):

setPowerStatus(value, callback) {
	this.log.info(`Turning TV ${value ? 'on' : 'off'}`);
	if (value === this.tvService.getCharacteristic(Characteristic.Active).value) {
		callback();
		this.log.info(`TV is already ${value ? 'on' : 'off'}`);
		return;
	}

	// const handler = () => {
	// 	handler.activated = true;
	// 	callback();
	// 	this.log.info(`TV is turned ${value ? 'on' : 'off'}`);
	// };						
	// tvEvent.once(value ? 'POWER_ON' : 'POWER_OFF', handler);
	// setTimeout(() => {
	// 	tvEvent.removeListener(value ? 'POWER_ON' : 'POWER_OFF', handler);
	// 	if (!handler.activated) {
	// 		callback(`TV is not turning ${value ? 'on' : 'off'}`);
	// 		this.log.info(`TV is not turning ${value ? 'on' : 'off'}`);
	// 	}
	// }, 30000);

	// Send on or off signal
	cecClient.stdin.write(value ? 'tx 10:04\n' : 'tx 10:36\n');
	callback();
}

Just to mention it, thanks for your help and for the nice plugin :-)

@dominick-han
Copy link
Owner

The issue is that your TV never sent traffic on the CEC bus to declare that it had turned on
I used my TV as a reference to implement, and it might be different especially in older TVs
I'll probably add an option in the next release to disable these callbacks (The spinner while turning on/off)

@Samfox2
Copy link
Author

Samfox2 commented Mar 29, 2019

If some TV‘s don‘t report the state back, maybe a delayed check would be possible like: user changes state -> wait 2 sec -> check state?

Volume control would also be nice (up/down) :-)

@alexisteleco
Copy link

What happened with this issue? Is the project dead?

I also think volume control would be nice, but I am not sure if it is better to open a new issue or leave it, as the project has not been changed for more than a year.

@Samfox2
Copy link
Author

Samfox2 commented Apr 16, 2020

I forked it and added basic volume control up/down here: https://github.com/Samfox2/homebridge-tv-cec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants