From 8a9d09bfb88aba832085202177a411c715bb3818 Mon Sep 17 00:00:00 2001 From: builderjer Date: Tue, 28 May 2024 06:41:57 -0600 Subject: [PATCH 1/8] first commit --- .gitignore | 21 +++ README.md | 33 ++++ ovos_PHAL_plugin_mk2_fan_control/__init__.py | 182 +++++++++++++++++++ setup.py | 39 ++++ 4 files changed, 275 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 ovos_PHAL_plugin_mk2_fan_control/__init__.py create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f17a28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +dev.env +.dev_opts.json +.idea +*.code-workspace +*.pyc +*.swp +*~ +*.egg-info/ +build +dist +.coverage +/htmlcov +.installed +.mypy_cache +.vscode +.theia +.venv/ +__pycache__ + +# Created by unit tests +.pytest_cache/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a59e29 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# ovos-PHAL-plugin-mk2-v6-fan-control + +**Compatible with** +* Mycroft Mark2 dev kit + +# Usage + +There are a few ways for this plugin to get enabled. + +* Enable manually + +Add this to your `~/.config/mycroft/mycroft.conf` + +```json +{ + "PHAL": { + "ovos-PHAL-plugin-mk2-v6-fan-control": { + "enabled": true + } + } +} +``` +With this configuration, no other validation checks are made. It is assuming you have a compatible HAT installed. + +* Automatically with [ovos-i2csound](https://github.com/OpenVoiceOS/ovos-i2csound) + +When `ovos-i2csound` is installed and running, it creates a file at `/etc/OpenVoiceOS/i2c_platform` with the HAT name it detected. This plugin then checks that file and if a compatible HAT is detected, the plugin is activated. + +* Automatically with hardware detection + +If the above two options don't work, the plugin tries to detect a compatible HAT using `i2c-detect`. If a compatible device address is found, the plugin will activate. + +From this point, if you are running OVOS on a Mark2 dev kit, your fan should be automatically controlled. diff --git a/ovos_PHAL_plugin_mk2_fan_control/__init__.py b/ovos_PHAL_plugin_mk2_fan_control/__init__.py new file mode 100644 index 0000000..08b38a7 --- /dev/null +++ b/ovos_PHAL_plugin_mk2_fan_control/__init__.py @@ -0,0 +1,182 @@ +from ovos_plugin_manager.phal import PHALPlugin +from ovos_plugin_manager.templates.phal import PHALValidator +from ovos_utils.log import LOG +from ovos_PHAL.detection import is_mycroft_sj201 + +I2C_PLATFORM_FILE = "/etc/OpenVoiceOS/i2c_platform" + + +class Mk2Rev6FanValidator(PHALValidator): + @staticmethod + def validate(config=None): + config = config or {} + # If the user enabled the plugin no need to go further + if config.get("enabled"): + return True + # Check for a file created by ovos-i2csound + # https://github.com/OpenVoiceOS/ovos-i2csound/blob/dev/ovos-i2csound#L76 + LOG.debug(f"checking file {I2C_PLATFORM_FILE}") + if exists(I2C_PLATFORM_FILE): + with open(I2C_PLATFORM_FILE) as f: + platform = f.readline().strip().lower() + LOG.debug(f"detected platform {platform}") + if platform == "sj201v6": + return True + # Try a direct hardware check + if is_mycroft_sj201(): + LOG.debug("direct hardware check found v6") + return True + LOG.debug("No Validation") + return False + + +class Mk2Rev6FanControls(PHALPlugin): + validator = Mk2Rev6FanValidator + + def __init__(self, bus=None, config=None): + super().__init__(bus=bus, name="ovos-phal-plugin-mk2-devkit-fan", config=config) + self.fan = R6FanControl() + self.exit_flag = Event() + self._max_fanless_temp = 60.0 # Highest fan-less temp allowed + self._max_fan_temp = 80.0 # Thermal throttle temp max fan + + if self.config.get("min_fan_temp"): + self.set_min_fan_temp(float(self.config.get("min_fan_temp"))) + + def get_cpu_temp(self): + cmd = ["cat", "/sys/class/thermal/thermal_zone0/temp"] + out, err = self.execute_cmd(cmd) + return float(out.strip()) / 1000 + + def set_min_fan_temp(self, new_temp: float): + """ + Set the temperature at which the fan will turn on. + @param new_temp: Float temperature in degrees Celsius at which the fan + will start running. Recommended values are 30.0-60.0 + """ + if new_temp > 80.0: + LOG.error("Fan will run at maximum speed at 80C; " + "min temp must be lower. Setting unchanged.") + return + if new_temp < 0.0: + LOG.error("Requested temperature is below operating range; " + "min temp must be more than 0C. Setting unchanged.") + return + LOG.info(f"Set fan to turn on at {new_temp}C") + self._max_fanless_temp = new_temp + + def run(self): + LOG.debug("temperature monitor thread started") + while not self.exit_flag.wait(30): + LOG.debug(f"CPU temperature is {self.get_cpu_temp()}") + + current_temp = self.get_cpu_temp() + if current_temp < self._max_fanless_temp: + # Below specified fanless temperature + fan_speed = 0 + LOG.debug(f"Temp below {self._max_fanless_temp}") + elif current_temp > self._max_fan_temp: + LOG.warning(f"Thermal Throttling, temp={current_temp}C") + fan_speed = 100 + else: + # Specify linear fan curve inside normal operating temp range + speed_const = 100 / (self._max_fan_temp - + self._max_fanless_temp) + fan_speed = speed_const * (current_temp - + self._max_fanless_temp) + LOG.debug(f"temp={current_temp}") + + LOG.debug(f"Setting fan speed to: {fan_speed}") + self.fan.set_fan_speed(fan_speed) + LOG.debug("Fan thread received exit signal") + + def shutdown(self): + self.exit_flag.set() + self.fan.shutdown() + try: + # Turn on Mark2 fan to prevent thermal throttling + import RPi.GPIO as GPIO + GPIO.output(self.fan.fan_pin, 0) + except Exception as e: + LOG.debug(e) + + +class R6FanControl: + # hardware speed range is appx 30-255 + # we convert from 0 to 100 + HDW_MIN = 0 + HDW_MAX = 255 + SFW_MIN = 0 + SFW_MAX = 100 + + def __init__(self): + self.fan_speed = 0 + # self.set_fan_speed(self.fan_speed) + + @staticmethod + def execute_cmd(cmd): + process = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, ) + out, err = process.communicate() + try: + out = out.decode("utf8") + except Exception as e: + LOG.exception(e) + + try: + err = err.decode("utf8") + except Exception as e: + LOG.exception(e) + + return out, err + + @staticmethod + def celcius_to_fahrenheit(temp): + return (temp * 1.8) + 32 + + def speed_to_hdw_val(self, speed): + out_steps = self.HDW_MAX - self.HDW_MIN + in_steps = self.SFW_MAX - self.SFW_MIN + ratio = out_steps / in_steps + # force compliance + if speed > self.SFW_MAX: + speed = self.SFW_MAX + if speed < self.SFW_MIN: + speed = self.SFW_MIN + + return int((speed * ratio) + self.HDW_MIN) + + def hdw_val_to_speed(self, hdw_val): + out_steps = self.SFW_MAX - self.SFW_MIN + in_steps = self.HDW_MAX - self.HDW_MIN + ratio = out_steps / in_steps + # force compliance + if hdw_val > self.HDW_MAX: + hdw_val = self.HDW_MAX + if hdw_val < self.HDW_MIN: + hdw_val = self.HDW_MIN + + return int(round(((hdw_val - self.HDW_MIN) * ratio) + self.SFW_MIN, 0)) + + def hdw_set_speed(self, hdw_speed): + # force compliance + if hdw_speed > self.HDW_MAX: + hdw_speed = self.HDW_MAX + if hdw_speed < self.HDW_MIN: + hdw_speed = self.HDW_MIN + + hdw_speed = str(hdw_speed) + cmd = ["i2cset", "-a", "-y", "1", "0x04", "101", hdw_speed, "i"] + out, err = self.execute_cmd(cmd) + LOG.debug(f'out={out}') + LOG.debug(f'err={err}') + + def set_fan_speed(self, speed): + self.fan_speed = self.speed_to_hdw_val(speed) + self.hdw_set_speed(self.fan_speed) + + def get_fan_speed(self): + return self.hdw_val_to_speed(self.fan_speed) + + def shutdown(self): + self.set_fan_speed(0) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..32241da --- /dev/null +++ b/setup.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import os + +from setuptools import setup + + +def package_files(directory): + paths = [] + for (path, directories, filenames) in os.walk(directory): + for filename in filenames: + paths.append(os.path.join('..', path, filename)) + return paths + + +PLUGIN_ENTRY_POINT = 'ovos-PHAL-plugin-mk2-v6-fan-control=ovos_PHAL_plugin_mk2_v6_fan_control:Mk2Rev6FanControls' +setup( + name='ovos-PHAL-plugin-mk2-fan-control', + version='0.0.1', + description='An OVOS PHAL plugin to control the fan on the mark2 dev kit', + url='https://github.com/builderjer/ovos-PHAL-plugin-mk2-v6-fan-control', + author='builderjer', + author_email='builderjer@gmail.com', + license='MIT', + packages=['ovos_PHAL_plugin_mk2_v6_fan_control'], + package_data={'': package_files('ovos_PHAL_plugin_mk2_v6_fan_control')}, + install_requires=["ovos-plugin-manager>=0.0.1"], + zip_safe=True, + include_package_data=True, + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'Topic :: Text Processing :: Linguistic', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11' + ], + entry_points={'ovos.plugin.phal': PLUGIN_ENTRY_POINT} +) From 4d9c0c6bd282e70b613e5002cd113ae378ce4fd4 Mon Sep 17 00:00:00 2001 From: builderjer Date: Tue, 28 May 2024 06:44:00 -0600 Subject: [PATCH 2/8] fix directory name --- .../__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {ovos_PHAL_plugin_mk2_fan_control => ovos_PHAL_plugin_mk2_v6_fan_control}/__init__.py (100%) diff --git a/ovos_PHAL_plugin_mk2_fan_control/__init__.py b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py similarity index 100% rename from ovos_PHAL_plugin_mk2_fan_control/__init__.py rename to ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py From 9125d9fd0a08df27c257b5b22e18f5fba97c5988 Mon Sep 17 00:00:00 2001 From: builderjer Date: Wed, 29 May 2024 05:56:09 -0600 Subject: [PATCH 3/8] Fix imports add config for temp --- README.md | 18 ++++++++++++++++++ .../__init__.py | 6 ++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3a59e29..5ab0a68 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,21 @@ When `ovos-i2csound` is installed and running, it creates a file at `/etc/OpenVo If the above two options don't work, the plugin tries to detect a compatible HAT using `i2c-detect`. If a compatible device address is found, the plugin will activate. From this point, if you are running OVOS on a Mark2 dev kit, your fan should be automatically controlled. + +### Configuration + +The temperature at which the fan turns on can be configured + +```json +{ + "PHAL": { + "ovos-PHAL-plugin-mk2-v6-fan-control": { + "max_fanless_temp": 60.0, + "max_fan_temp": 80.0 + } + } +} +``` + +`"max_fanless_temp"` -> This is where the fan turns on +`"max_fan_temp"` -> At this temp, the fan runs at 100% diff --git a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py index 08b38a7..05b5a5a 100644 --- a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py +++ b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py @@ -1,3 +1,5 @@ +from threading import Event + from ovos_plugin_manager.phal import PHALPlugin from ovos_plugin_manager.templates.phal import PHALValidator from ovos_utils.log import LOG @@ -37,8 +39,8 @@ def __init__(self, bus=None, config=None): super().__init__(bus=bus, name="ovos-phal-plugin-mk2-devkit-fan", config=config) self.fan = R6FanControl() self.exit_flag = Event() - self._max_fanless_temp = 60.0 # Highest fan-less temp allowed - self._max_fan_temp = 80.0 # Thermal throttle temp max fan + self._max_fanless_temp = self.config.get("max_fanless_temp", 60.0) # Highest fan-less temp allowed + self._max_fan_temp = self.config.get("max_fan_temp", 80.0) # Thermal throttle temp max fan if self.config.get("min_fan_temp"): self.set_min_fan_temp(float(self.config.get("min_fan_temp"))) From 011614006200e45716419a8bcdf260e3a4c3741d Mon Sep 17 00:00:00 2001 From: Denix Date: Wed, 29 May 2024 22:00:51 +0200 Subject: [PATCH 4/8] added missing import (#1) --- ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py index 05b5a5a..8c16067 100644 --- a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py +++ b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py @@ -1,4 +1,5 @@ from threading import Event +from os.path import exists from ovos_plugin_manager.phal import PHALPlugin from ovos_plugin_manager.templates.phal import PHALValidator From af16c134c590faa111f98590793262150cce171d Mon Sep 17 00:00:00 2001 From: Denix Date: Thu, 30 May 2024 22:28:56 +0200 Subject: [PATCH 5/8] added initialization and right class name (and one missing import) (#3) --- ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py index 8c16067..871bee9 100644 --- a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py +++ b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py @@ -1,3 +1,4 @@ +import subprocess from threading import Event from os.path import exists @@ -48,7 +49,7 @@ def __init__(self, bus=None, config=None): def get_cpu_temp(self): cmd = ["cat", "/sys/class/thermal/thermal_zone0/temp"] - out, err = self.execute_cmd(cmd) + out, err = self.fan.execute_cmd(cmd) return float(out.strip()) / 1000 def set_min_fan_temp(self, new_temp: float): @@ -69,6 +70,7 @@ def set_min_fan_temp(self, new_temp: float): self._max_fanless_temp = new_temp def run(self): + self.exit_flag = False LOG.debug("temperature monitor thread started") while not self.exit_flag.wait(30): LOG.debug(f"CPU temperature is {self.get_cpu_temp()}") From 6f5096128cee802803664bae30dcd9bc98fc6a4d Mon Sep 17 00:00:00 2001 From: builderjer <34875857+builderjer@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:51:48 -0600 Subject: [PATCH 6/8] Update imports (#4) * updated to use ovos-i2c-detection * added automations * chore:automations --------- Co-authored-by: miro --- .github/workflows/build_tests.yml | 49 +++++++ .github/workflows/conventional-label.yml | 10 ++ .github/workflows/license_tests.yml | 39 ++++++ .github/workflows/publish_stable.yml | 72 +++++++++++ .github/workflows/release_workflow.yml | 122 ++++++++++++++++++ .github/workflows/unit_tests.yml | 10 ++ .../__init__.py | 10 +- .../version.py | 7 + requirements.txt | 2 + setup.py | 46 ++++++- 10 files changed, 361 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/build_tests.yml create mode 100644 .github/workflows/conventional-label.yml create mode 100644 .github/workflows/license_tests.yml create mode 100644 .github/workflows/publish_stable.yml create mode 100644 .github/workflows/release_workflow.yml create mode 100644 .github/workflows/unit_tests.yml create mode 100644 ovos_PHAL_plugin_mk2_v6_fan_control/version.py create mode 100644 requirements.txt diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml new file mode 100644 index 0000000..b857af1 --- /dev/null +++ b/.github/workflows/build_tests.yml @@ -0,0 +1,49 @@ +name: Run Build Tests +on: + push: + branches: + - master + pull_request: + branches: + - dev + workflow_dispatch: + +jobs: + build_tests: + strategy: + max-parallel: 2 + matrix: + python-version: [ 3.7, 3.8, 3.9, "3.10" ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Python + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install Build Tools + run: | + python -m pip install build wheel + - name: Install System Dependencies + run: | + sudo apt-get update + sudo apt install python3-dev swig libssl-dev + - name: Build Source Packages + run: | + python setup.py sdist + - name: Build Distribution Packages + run: | + python setup.py bdist_wheel + - name: Install repo + run: | + pip install . + - uses: pypa/gh-action-pip-audit@v1.0.8 + with: + # Ignore irrelevant Mercurial vulnerability + # Ignore `requests` and `urllib3` vulnerabilities as they are not used in this package + # Ignore `setuptools` and `pip` vulnerabilities I don't think they apply here + ignore-vulns: | + PYSEC-2023-228 + GHSA-9wx4-h78v-vm56 + GHSA-34jh-p97f-mpxf + PYSEC-2022-43012 diff --git a/.github/workflows/conventional-label.yml b/.github/workflows/conventional-label.yml new file mode 100644 index 0000000..9894c1b --- /dev/null +++ b/.github/workflows/conventional-label.yml @@ -0,0 +1,10 @@ +# auto add labels to PRs +on: + pull_request_target: + types: [ opened, edited ] +name: conventional-release-labels +jobs: + label: + runs-on: ubuntu-latest + steps: + - uses: bcoe/conventional-release-labels@v1 diff --git a/.github/workflows/license_tests.yml b/.github/workflows/license_tests.yml new file mode 100644 index 0000000..e101270 --- /dev/null +++ b/.github/workflows/license_tests.yml @@ -0,0 +1,39 @@ +name: Run License Tests +on: + push: + branches: + - master + pull_request: + branches: + - dev + workflow_dispatch: + +jobs: + license_tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Python + uses: actions/setup-python@v3 + with: + python-version: 3.8 + - name: Install Build Tools + run: | + python -m pip install build wheel + - name: Install System Dependencies + run: | + sudo apt-get update + sudo apt install python3-dev swig libssl-dev + - name: Install core repo + run: | + pip install . + - name: Check python + id: license_check_report + uses: pilosus/action-pip-license-checker@v0.5.0 + with: + fail: 'Copyleft,Other,Error' + fails-only: true + exclude-license: '^(Mozilla).*$' + - name: Print report + if: ${{ always() }} + run: echo "${{ steps.license_check_report.outputs.report }}" diff --git a/.github/workflows/publish_stable.yml b/.github/workflows/publish_stable.yml new file mode 100644 index 0000000..fddda35 --- /dev/null +++ b/.github/workflows/publish_stable.yml @@ -0,0 +1,72 @@ +name: Stable Release +on: + push: + branches: [master] + workflow_dispatch: + +jobs: + publish_stable: + uses: TigreGotico/gh-automations/.github/workflows/publish-stable.yml@master + secrets: inherit + with: + branch: 'master' + version_file: 'ovos_PHAL_plugin_mk2_v6_fan_control/version.py' + setup_py: 'setup.py' + publish_release: true + + publish_pypi: + needs: publish_stable + if: success() # Ensure this job only runs if the previous job succeeds + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: dev + fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. + - name: Setup Python + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - name: Install Build Tools + run: | + python -m pip install build wheel + - name: version + run: echo "::set-output name=version::$(python setup.py --version)" + id: version + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: V${{ steps.version.outputs.version }} + release_name: Release ${{ steps.version.outputs.version }} + body: | + Changes in this Release + ${{ steps.changelog.outputs.changelog }} + draft: false + prerelease: true + commitish: dev + - name: Build Distribution Packages + run: | + python setup.py sdist bdist_wheel + - name: Publish to Test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{secrets.PYPI_TOKEN}} + + + sync_dev: + needs: publish_stable + if: success() # Ensure this job only runs if the previous job succeeds + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. + ref: master + - name: Push master -> dev + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: dev \ No newline at end of file diff --git a/.github/workflows/release_workflow.yml b/.github/workflows/release_workflow.yml new file mode 100644 index 0000000..021ac2c --- /dev/null +++ b/.github/workflows/release_workflow.yml @@ -0,0 +1,122 @@ +name: Release Alpha and Propose Stable + +on: + pull_request: + types: [closed] + branches: [dev] + +jobs: + publish_alpha: + if: github.event.pull_request.merged == true + uses: TigreGotico/gh-automations/.github/workflows/publish-alpha.yml@master + secrets: inherit + with: + branch: 'dev' + version_file: 'ovos_PHAL_plugin_mk2_v6_fan_control/version.py' + setup_py: 'setup.py' + update_changelog: true + publish_prerelease: true + changelog_max_issues: 100 + + notify: + if: github.event.pull_request.merged == true + needs: publish_alpha + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Send message to Matrix bots channel + id: matrix-chat-message + uses: fadenb/matrix-chat-message@v0.0.6 + with: + homeserver: 'matrix.org' + token: ${{ secrets.MATRIX_TOKEN }} + channel: '!WjxEKjjINpyBRPFgxl:krbel.duckdns.org' + message: | + new ${{ github.event.repository.name }} PR merged! https://github.com/${{ github.repository }}/pull/${{ github.event.number }} + + publish_pypi: + needs: publish_alpha + if: success() # Ensure this job only runs if the previous job succeeds + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: dev + fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. + - name: Setup Python + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - name: Install Build Tools + run: | + python -m pip install build wheel + - name: version + run: echo "::set-output name=version::$(python setup.py --version)" + id: version + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: V${{ steps.version.outputs.version }} + release_name: Release ${{ steps.version.outputs.version }} + body: | + Changes in this Release + ${{ steps.changelog.outputs.changelog }} + draft: false + prerelease: true + commitish: dev + - name: Build Distribution Packages + run: | + python setup.py sdist bdist_wheel + - name: Publish to Test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{secrets.PYPI_TOKEN}} + + + propose_release: + needs: publish_alpha + if: success() # Ensure this job only runs if the previous job succeeds + runs-on: ubuntu-latest + steps: + - name: Checkout dev branch + uses: actions/checkout@v3 + with: + ref: dev + + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + + - name: Get version from setup.py + id: get_version + run: | + VERSION=$(python setup.py --version) + echo "VERSION=$VERSION" >> $GITHUB_ENV + + - name: Create and push new branch + run: | + git checkout -b release-${{ env.VERSION }} + git push origin release-${{ env.VERSION }} + + - name: Open Pull Request from dev to master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Variables + BRANCH_NAME="release-${{ env.VERSION }}" + BASE_BRANCH="master" + HEAD_BRANCH="release-${{ env.VERSION }}" + PR_TITLE="Release ${{ env.VERSION }}" + PR_BODY="Human review requested!" + + # Create a PR using GitHub API + curl -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + -d "{\"title\":\"$PR_TITLE\",\"body\":\"$PR_BODY\",\"head\":\"$HEAD_BRANCH\",\"base\":\"$BASE_BRANCH\"}" \ + https://api.github.com/repos/${{ github.repository }}/pulls + diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..3e380f3 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,10 @@ +name: Unit Tests +on: + push: + workflow_dispatch: + +jobs: + py_build_tests: + uses: neongeckocom/.github/.github/workflows/python_build_tests.yml@master + with: + python_version: "3.8" diff --git a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py index 871bee9..2ca98c3 100644 --- a/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py +++ b/ovos_PHAL_plugin_mk2_v6_fan_control/__init__.py @@ -5,7 +5,7 @@ from ovos_plugin_manager.phal import PHALPlugin from ovos_plugin_manager.templates.phal import PHALValidator from ovos_utils.log import LOG -from ovos_PHAL.detection import is_mycroft_sj201 +from ovos_i2c_detection import is_sj201_v6 I2C_PLATFORM_FILE = "/etc/OpenVoiceOS/i2c_platform" @@ -27,7 +27,7 @@ def validate(config=None): if platform == "sj201v6": return True # Try a direct hardware check - if is_mycroft_sj201(): + if is_sj201_v6(): LOG.debug("direct hardware check found v6") return True LOG.debug("No Validation") @@ -41,8 +41,10 @@ def __init__(self, bus=None, config=None): super().__init__(bus=bus, name="ovos-phal-plugin-mk2-devkit-fan", config=config) self.fan = R6FanControl() self.exit_flag = Event() - self._max_fanless_temp = self.config.get("max_fanless_temp", 60.0) # Highest fan-less temp allowed - self._max_fan_temp = self.config.get("max_fan_temp", 80.0) # Thermal throttle temp max fan + self._max_fanless_temp = self.config.get( + "max_fanless_temp", 60.0) # Highest fan-less temp allowed + self._max_fan_temp = self.config.get( + "max_fan_temp", 80.0) # Thermal throttle temp max fan if self.config.get("min_fan_temp"): self.set_min_fan_temp(float(self.config.get("min_fan_temp"))) diff --git a/ovos_PHAL_plugin_mk2_v6_fan_control/version.py b/ovos_PHAL_plugin_mk2_v6_fan_control/version.py new file mode 100644 index 0000000..79d91ab --- /dev/null +++ b/ovos_PHAL_plugin_mk2_v6_fan_control/version.py @@ -0,0 +1,7 @@ +# The following lines are replaced during the release process. +# START_VERSION_BLOCK +VERSION_MAJOR = 0 +VERSION_MINOR = 0 +VERSION_BUILD = 0 +VERSION_ALPHA = 1 +# END_VERSION_BLOCK diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a11a363 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +ovos-plugin-manager>=0.0.1 +ovos-i2c-detection>=0.0.0a5 diff --git a/setup.py b/setup.py index 32241da..fc4d068 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,48 @@ from setuptools import setup +import os +from os.path import join, dirname + +from setuptools import setup + +BASEDIR = os.path.abspath(os.path.dirname(__file__)) + + +def required(requirements_file): + """ Read requirements file and remove comments and empty lines. """ + with open(os.path.join(BASEDIR, requirements_file), 'r') as f: + requirements = f.read().splitlines() + if 'MYCROFT_LOOSE_REQUIREMENTS' in os.environ: + print('USING LOOSE REQUIREMENTS!') + requirements = [r.replace('==', '>=').replace('~=', '>=') for r in requirements] + return [pkg for pkg in requirements + if pkg.strip() and not pkg.startswith("#")] + + +def get_version(): + """ Find the version of this package""" + version_file = join(BASEDIR, 'ovos_PHAL_plugin_mk2_v6_fan_control/version.py') + major, minor, build, alpha = (None, None, None, None) + with open(version_file) as f: + for line in f: + if 'VERSION_MAJOR' in line: + major = line.split('=')[1].strip() + elif 'VERSION_MINOR' in line: + minor = line.split('=')[1].strip() + elif 'VERSION_BUILD' in line: + build = line.split('=')[1].strip() + elif 'VERSION_ALPHA' in line: + alpha = line.split('=')[1].strip() + + if ((major and minor and build and alpha) or + '# END_VERSION_BLOCK' in line): + break + version = f"{major}.{minor}.{build}" + if int(alpha): + version += f"a{alpha}" + return version + def package_files(directory): paths = [] @@ -15,7 +57,7 @@ def package_files(directory): PLUGIN_ENTRY_POINT = 'ovos-PHAL-plugin-mk2-v6-fan-control=ovos_PHAL_plugin_mk2_v6_fan_control:Mk2Rev6FanControls' setup( name='ovos-PHAL-plugin-mk2-fan-control', - version='0.0.1', + version=get_version(), description='An OVOS PHAL plugin to control the fan on the mark2 dev kit', url='https://github.com/builderjer/ovos-PHAL-plugin-mk2-v6-fan-control', author='builderjer', @@ -23,7 +65,7 @@ def package_files(directory): license='MIT', packages=['ovos_PHAL_plugin_mk2_v6_fan_control'], package_data={'': package_files('ovos_PHAL_plugin_mk2_v6_fan_control')}, - install_requires=["ovos-plugin-manager>=0.0.1"], + install_requires=required("requirements.txt"), zip_safe=True, include_package_data=True, classifiers=[ From 241e5f8433a4a33446467d6558d9770277af9239 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Mon, 9 Sep 2024 23:53:00 +0000 Subject: [PATCH 7/8] Increment Version to 0.0.1a1 --- ovos_PHAL_plugin_mk2_v6_fan_control/version.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ovos_PHAL_plugin_mk2_v6_fan_control/version.py b/ovos_PHAL_plugin_mk2_v6_fan_control/version.py index 79d91ab..45d5ec0 100644 --- a/ovos_PHAL_plugin_mk2_v6_fan_control/version.py +++ b/ovos_PHAL_plugin_mk2_v6_fan_control/version.py @@ -1,7 +1,6 @@ -# The following lines are replaced during the release process. # START_VERSION_BLOCK VERSION_MAJOR = 0 VERSION_MINOR = 0 -VERSION_BUILD = 0 +VERSION_BUILD = 1 VERSION_ALPHA = 1 -# END_VERSION_BLOCK +# END_VERSION_BLOCK \ No newline at end of file From 2a0c6da8797b9cbc5f2a815481b76c3246f32b22 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Mon, 9 Sep 2024 23:53:25 +0000 Subject: [PATCH 8/8] Update Changelog --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..64e1953 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## [0.0.1a1](https://github.com/OpenVoiceOS/ovos-PHAL-plugin-mk2-v6-fan-control/tree/0.0.1a1) (2024-09-09) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-PHAL-plugin-mk2-v6-fan-control/compare/0a2b20ffc5266a90761b663bffff777fc3f5b9ea...0.0.1a1) + +**Fixed bugs:** + +- added initialization and right class name \(and one missing import\) [\#3](https://github.com/OpenVoiceOS/ovos-PHAL-plugin-mk2-v6-fan-control/pull/3) ([denics](https://github.com/denics)) +- added missing import [\#1](https://github.com/OpenVoiceOS/ovos-PHAL-plugin-mk2-v6-fan-control/pull/1) ([denics](https://github.com/denics)) + +**Merged pull requests:** + +- Update imports [\#4](https://github.com/OpenVoiceOS/ovos-PHAL-plugin-mk2-v6-fan-control/pull/4) ([builderjer](https://github.com/builderjer)) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*