npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@senzil/cec-monitor

v2.1.0

Published

HDMI-CEC library with a simple monitor written on ES6 to make cec enabled apps.

Downloads

24

Readme

cec-monitor

HDMI-CEC library with a simple monitor written on ES6 to make cec enabled apps.

Install

npm install --save @senzil/cec-monitor

Examples

Events

import {CEC, CECMonitor} from 'cec-monitor';

//All config options are optionals
//the values are the deafults
let monitor = new CECMonitor('custom-osdname', {
  com_port: '',            //set com port to use (see cec-client -l)
  debug: false,           // enable/disabled debug events from cec-client
  hdmiport: 1,            // set inital hdmi port
  processManaged: false,  // set/unset handlers to avoid unclear process exit.
  recorder: true,         //enable cec-client as recorder device
  player: false,          //enable cec-client as player device
  tuner: false,           //enable cec-client as tuner device
  audio: false,           //enable cec-client as audio system device
  autorestart: true,      //enable autrestart cec-client to avoid some wierd conditions
  no_serial: {            //controls if the monitor restart cec-client when that stop after the usb was unplugged
    reconnect: false,       //enable reconnection attempts when usb is unplugged
    wait_time: 30,          //in seconds - time to do the attempt
    trigger_stop: false     //false to avoid trigger stop event
  },
  cache: {
    enable: false,  //treats the state like a cache, and enable _EXPIREDCACHE event.
    autorefresh: false, //enable the cache refresh (currently only power status), and enable _UPDATEDCACHE event.
    timeout: 30  //value greater than 0 (in seconds) enable cache invalidation timeout and request new values if autorefresh is enabled
  },         
  command_timeout: 3,       //An value greater than 0 (in secconds) meaning the timeout time for SendCommand function
  user_control_hold_interval: 1000 //An value greater than 0 (in miliseconds) meaning the interval for emit the special _USERCONTROLHOLD event
});


monitor.once(CECMonitor.EVENTS._READY, function() {
  console.log( ' -- READY -- ' );
  // Low-level
  monitor.WriteMessage(CEC.LogicalAddress.BROADCAST, CEC.LogicalAddress.TV, CEC.Opcode.GIVE_DEVICE_POWER_STATUS);
  // High-level
  monitor.SendMessage(null,null,CEC.Opcode.SET_OSD_NAME,'Plex'); // Broadcast my OSD Name
  monitor.SendMessage(null, CEC.LogicalAddress.TV, CEC.Opcode.GIVE_OSD_NAME); // Ask TV for OSD Name
});

monitor.on(CECMonitor.EVENTS.REPORT_POWER_STATUS, function (packet) {
  console.log('POWER STATUS CODE:',packet.data.val);
  console.log('POWER STATUS:',packet.data.str);
});

monitor.on(CECMonitor.EVENTS.ROUTING_CHANGE, function(packet) {
  console.log( 'Routing changed from ' + packet.data.from.str + ' to ' + packet.data.to.str + '.' );
});

monitor.on(CECMonitor.EVENTS.SET_OSD_NAME, function(packet) {
  console.log( 'Logical address ' + packet.source + 'has OSD name ' + packet.data.str);
});

// Any packet with an opcode (excludes debug, notify and other message types from cec-client
monitor.on(CECMonitor.EVENTS._OPCODE, function(packet) {
  console.log(packet);
});

Opcode-based events emitted provide a single parameter packet to the callback. The value is an object of the form:

{
  "type": "TRAFFIC", "number": "82784", "flow": "IN", 
  "source": 1, "target": 4, "opcode": 144, "args": [0],
  "event": "REPORT_POWER_STATUS", 
  "data": {"val": 0, "str": "ON"}
}

Packets containing the following opcodes that are received are parsed, with the results added to a data property.

  • CEC.Opcode.ACTIVE_SOURCE
  • CEC.Opcode.CEC_VERSION
  • CEC.Opcode.DECK_STATUS
  • CEC.Opcode.DEVICE_VENDOR_ID
  • CEC.Opcode.REPORT_PHYSICAL_ADDRESS
  • CEC.Opcode.REPORT_POWER_STATUS
  • CEC.Opcode.ROUTING_CHANGE
  • CEC.Opcode.SET_OSD_NAME
  • CEC.Opcode.USER_CONTROL_PRESSED
  • CEC.Opcode.USER_CONTROL_RELEASE

The data property contains the raw value, and a string representation of the parsed results stored in the arg property, based on the event type / opcode value. Where multiple values are parsed from args, a substructure is created in the data property, as shown below for ROUTING_CHANGE.

{
  "type": "TRAFFIC", "number": "23553258", "flow": "IN",
  "source": 0, "target": "1 5", "opcode": 128, "args": [0, 0, 16, 0],
  "event": "ROUTING_CHANGE",
  "data": {
    "from": {"val": 0, "str": "0.0.0.0"},
    "to": {"val": 4096, "str": "1.0.0.0"}
  }
}

Sending CEC Messages

Before send messages to the adapter, you must to know if the adapter is ready using WaitForReady function.

monitor.WaitForReady().then(() => monitor.SendMessage(...))

if (monitor.ready) {
  monitor.SendMessage(...)
}

Or you can catch the error CECAdapterNotReadyError and CECTimeoutError

try {
  await monitor.SendMessage(...)
} catch (e) {
  console.warn(e)
}

monitor.SendMessage(...).catch(console.warn)

There are four APIs to choose from to send a message on the bus. This section discusses each of these methods, with examples.

The message used in the examples broadcasts a SET_OSD_NAME message on the bus, setting playbackdevice1 (logical address 04) on screen name to 'Frisbee'.

WriteRawMessage

WriteRawMessage(raw)

WriteRawMessage writes the low-level commands to cec-client. Use this method as you type commands directly to cec-client itself at the command line.

monitor.WriteRawMessage('tx 0F:46:46:72:69:73:62:65:65');

WriteMessage

WriteMessage(source, target, opcode, args)

WriteMessage is used to write tx messages to cec-client. These are messages containing a low-level protocol opcode. Unlike WriteRawMessage which takes a string, and is sent unchanged, WriteMessage has a parameter list, and constructs a raw command from these parameters to send to cec-client.

monitor.WriteMessage(CEC.LogicalAddress.PLAYBACKDEVICE1, CEC.LogicalAddress.BROADCAST, CEC.Opcode.SET_OSD_NAME,[0x46,0x72,0x69,0x73,0x62,0x65,0x65]);

SendMessage

SendMessage(source, target, opcode, args)

SendMessage is a high-level API of the same form as WriteMessage, but accepts a range of different data types and formats as input. This is useful when sending messages from user input. The following examples illustrate how to use SendMessage

monitor.SendMessage(CEC.LogicalAddress.PLAYBACKDEVICE1, CEC.LogicalAddress.BROADCAST, CEC.Opcode.SET_OSD_NAME,[0x46,0x72,0x69,0x73,0x62,0x65,0x65]);

monitor.SendMessage(4, 15, 70, [70,114,105,115,98,101,101]);

monitor.SendMessage('0x4', '0xF', '0x46', [0x46,0x72,0x69,0x73,0x62,0x65,0x65]);

monitor.SendMessage('PLAYBACKDEVICE1','BROADCAST','SET_OSD_NAME','Frisbee');

monitor.SendMessage('playbackdevice1', 'broadcast', 'set_osd_name','Frisbee');

// Can specify physical address as string, using dot notation
monitor.SendMessage(CEC.LogicalAddress.UNREGISTERED, CEC.LogicalAddress.BROADCAST, CEC.Opcode.ACTIVE_SOURCE,'2.0.0.0');

// Or as an array of bytes
monitor.SendMessage(CEC.LogicalAddress.UNREGISTERED, CEC.LogicalAddress.BROADCAST, CEC.Opcode.ACTIVE_SOURCE,[0x20,0x0]);

// Default source is the client - default destination is broadcast
monitor.SendMessage(null,null, 'set_osd_name','Frisbee');

SendCommand

SendCommand(source, target, opcode, event, args)

SendCommand is a high-level API of the same form as SendMessage, but adds an event parameter to wait for for a message as response. This is useful when sending messages from user input and expects a response from the device. The following examples illustrate how to use SendCommand

monitor.SendCommand(CEC.LogicalAddress.PLAYBACKDEVICE1, CEC.LogicalAddress.TV, CEC.Opcode.GIVE_DEVICE_POWER_STATUS, CECMonitor.EVENTS.REPORT_POWER_STATUS)
.then(packet => {
  console.log(packet)
//{
//  "type": "TRAFFIC", "number": "82784", "flow": "IN", 
//  "source": 1, "target": 4, "opcode": 144, "args": [0],
//  "event": "REPORT_POWER_STATUS", 
//  "data": {"val": 0, "str": "ON"}
//}
})
.catch(e => {
  console.error(e);
//Error: CEC monitor hasn't gotten response in some time (3000 ms) from 0
});

cli.js

You can experiment with how cec-monitor works and the codes generated with your HDMI connected equipment by experimenting with the bin/cli.js script. This script implements a simple readline command interface where you can execute instructions and see how cec-monitor responds, allowing you to adapt to your requirements. Press TAB for autocompletion of commands to see what it does and how to use it.

Roadmap

  • ~~Improve constructor to improve cec-client configuration~~
  • ~~Implement more events with more context info~~
  • ~~Implement RPI support~~
  • Implement more and more events with more context info
  • ~~Implement some user control actions as special events (combining USER_CONTROL_PRESSED and USERCONTROL RELEASE events)~~
  • Implement a ceclib adapter to avoid use a cec-client wrapper
  • Implement HDMI 2.0

Credits

nanos gigantum humeris insidentes

This work was based over the work of

  • http://www.cec-o-matic.com/
  • https://github.com/patlux/node-cec

#Contributors *Damien Clark (https://damos.world)

License

The MIT License (MIT)

Copyright 2017 SENZIL SRL

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.