From baa8b7b7cc294dcdb418c47566ce540359a24178 Mon Sep 17 00:00:00 2001 From: daptek Date: Fri, 22 Aug 2025 12:29:19 -0400 Subject: [PATCH 1/3] Fix adapter selection and add --adapter flag - Fix bug where last CEC adapter was used instead of first - Add --adapter/-a flag to specify CEC device path explicitly - Addresses dual HDMI port issues on Raspberry Pi 4 - Use first adapter by default instead of last Fixes adapter selection on systems with multiple CEC adapters (/dev/cec0, /dev/cec1) where TV is typically on primary port. Usage: python -m pycec # Uses first adapter (fixed) python -m pycec --adapter /dev/cec0 # Uses specified adapter --- pycec/__main__.py | 8 +++++++- pycec/cec.py | 28 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/pycec/__main__.py b/pycec/__main__.py index c4558e8..042f411 100644 --- a/pycec/__main__.py +++ b/pycec/__main__.py @@ -27,7 +27,8 @@ def main(): transports = set() loop = asyncio.get_event_loop() - network = HDMINetwork(CecAdapter("pyCEC", activate_source=False), + network = HDMINetwork(CecAdapter("pyCEC", activate_source=False, + adapter_path=config['DEFAULT']['adapter']), loop=loop) class CECServerProtocol(asyncio.Protocol): @@ -109,6 +110,10 @@ def configure(): default=DEFAULT_PORT, help=("Port to bind to. Default is '%s'." % DEFAULT_PORT)) + parser.add_option("-a", "--adapter", dest="adapter", action="store", + type="string", default=None, + help="CEC adapter path to use (e.g., '/dev/cec0'). " + "If not specified, uses first adapter found.") parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0, help="Increase verbosity.") parser.add_option("-q", "--quiet", dest="quiet", action="count", @@ -117,6 +122,7 @@ def configure(): script_dir = os.path.dirname(os.path.realpath(__file__)) config = configparser.ConfigParser() config['DEFAULT'] = {'host': options.host, 'port': options.port, + 'adapter': options.adapter, 'logLevel': logging.INFO + ( (options.quiet - options.verbose) * 10)} paths = ['/etc/pycec.conf', script_dir + '/pycec.conf'] diff --git a/pycec/cec.py b/pycec/cec.py index 3d9db52..55e7f27 100644 --- a/pycec/cec.py +++ b/pycec/cec.py @@ -13,10 +13,11 @@ class CecAdapter(AbstractCecAdapter): def __init__(self, name: str = None, monitor_only: bool = None, activate_source: bool = None, - device_type=ADDR_RECORDINGDEVICE1): + device_type=ADDR_RECORDINGDEVICE1, adapter_path: str = None): super().__init__() self._adapter = None self._io_executor = ThreadPoolExecutor(1) + self._adapter_path = adapter_path import cec self._cecconfig = cec.libcec_configuration() if monitor_only is not None: @@ -68,15 +69,22 @@ def _init(self, callback: callable = None): adapter = cec.ICECAdapter.Create(self._cecconfig) _LOGGER.debug("Created adapter") a = None - adapters = adapter.DetectAdapters() - for a in adapters: - _LOGGER.info("found a CEC adapter:") - _LOGGER.info("port: " + a.strComName) - _LOGGER.info("vendor: " + ( - VENDORS[a.iVendorId] if a.iVendorId in VENDORS else hex( - a.iVendorId))) - _LOGGER.info("product: " + hex(a.iProductId)) - a = a.strComName + if self._adapter_path: + a = self._adapter_path + _LOGGER.info("Using specified adapter: %s", a) + else: + first_adapter = None + adapters = adapter.DetectAdapters() + for adapter_info in adapters: + _LOGGER.info("found a CEC adapter:") + _LOGGER.info("port: " + adapter_info.strComName) + _LOGGER.info("vendor: " + ( + VENDORS[adapter_info.iVendorId] if adapter_info.iVendorId in VENDORS else hex( + adapter_info.iVendorId))) + _LOGGER.info("product: " + hex(adapter_info.iProductId)) + if first_adapter is None: + first_adapter = adapter_info.strComName + a = first_adapter if a is None: _LOGGER.warning("No adapters found") else: From bc718376294ebcdf3733b8d1ef5c7be582ab0a3f Mon Sep 17 00:00:00 2001 From: daptek Date: Fri, 22 Aug 2025 12:51:42 -0400 Subject: [PATCH 2/3] Fix TypeError when no --adapter flag is provided --- pycec/__main__.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pycec/__main__.py b/pycec/__main__.py index 042f411..2ff889b 100644 --- a/pycec/__main__.py +++ b/pycec/__main__.py @@ -27,8 +27,9 @@ def main(): transports = set() loop = asyncio.get_event_loop() + adapter_path = config['DEFAULT']['adapter'] if config['DEFAULT']['adapter'] else None network = HDMINetwork(CecAdapter("pyCEC", activate_source=False, - adapter_path=config['DEFAULT']['adapter']), + adapter_path=adapter_path), loop=loop) class CECServerProtocol(asyncio.Protocol): @@ -121,10 +122,10 @@ def configure(): (options, args) = parser.parse_args() script_dir = os.path.dirname(os.path.realpath(__file__)) config = configparser.ConfigParser() - config['DEFAULT'] = {'host': options.host, 'port': options.port, - 'adapter': options.adapter, - 'logLevel': logging.INFO + ( - (options.quiet - options.verbose) * 10)} + config['DEFAULT'] = {'host': options.host, 'port': str(options.port), + 'adapter': options.adapter or '', + 'logLevel': str(logging.INFO + ( + (options.quiet - options.verbose) * 10))} paths = ['/etc/pycec.conf', script_dir + '/pycec.conf'] if 'HOME' in os.environ: paths.append(os.environ['HOME'] + '/.pycec') From d6fc5be95739567df18e4f2aab86298922cffc61 Mon Sep 17 00:00:00 2001 From: daptek Date: Wed, 21 Jan 2026 10:34:34 -0500 Subject: [PATCH 3/3] feat: modernize packaging with pyproject.toml and release workflow - Replace setup.py with pyproject.toml (hatchling build system) - Add GitHub Actions workflow to build wheel on tags - Supports Markdown README (was the original install issue) --- .github/workflows/release.yml | 31 +++++++++++++++++++++++ pyproject.toml | 39 +++++++++++++++++++++++++++++ setup.py | 46 ----------------------------------- 3 files changed, 70 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/release.yml delete mode 100755 setup.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3dce03f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,31 @@ +name: Build and Release + +on: + push: + tags: + - 'v*' + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install build tools + run: pip install build + + - name: Build wheel + run: python -m build --wheel + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + files: dist/*.whl + generate_release_notes: true diff --git a/pyproject.toml b/pyproject.toml index a8f43fe..8f42cd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,41 @@ +[project] +name = "pycec" +version = "0.6.1" +description = "Provide HDMI CEC devices as objects, especially for use with Home Assistant" +readme = "README.md" +requires-python = ">=3.9" +license = "MIT" +keywords = ["cec", "hdmi", "home-assistant"] +authors = [ + { name = "Petr Vraník", email = "hpa@suteren.net" } +] +classifiers = [ + "Development Status :: 4 - Beta", + "Topic :: Utilities", + "Topic :: Home Automation", + "Topic :: Multimedia", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [] + +[project.scripts] +pycec = "pycec.__main__:main" + +[project.urls] +Repository = "https://github.com/daptify14/pyCEC" +Upstream = "https://github.com/konikvranik/pyCEC" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["pycec"] + [tool.black] line-length = 79 diff --git a/setup.py b/setup.py deleted file mode 100755 index 71a00d8..0000000 --- a/setup.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from setuptools import setup, find_packages -import os - -this_dir = os.path.dirname(os.path.abspath(__file__)) -with open(os.path.join(this_dir, "README.rst"), "r") as f: - long_description = f.read() - -PACKAGES = find_packages(exclude=["tests", "tests.*", "build"]) - -setup( - name="pyCEC", - version="0.6.0", - author="Petr Vraník", - author_email="hpa@suteren.net", - description=( - "Provide HDMI CEC devices as objects," - " especially for use with Home Assistant" - ), - license="MIT", - keywords="cec hdmi home-assistant", - url="https://github.com/konikvranik/pycec/", - packages=PACKAGES, - install_requires=[], - long_description=long_description, - test_suite="tests", - classifiers=[ - "Development Status :: 4 - Beta", - "Topic :: Utilities", - "Topic :: Home Automation", - "Topic :: Multimedia", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - ], - entry_points={ - "console_scripts": [ - "pycec=pycec.__main__:main", - ], - }, -)