Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjiU authored Jul 31, 2024
2 parents af9c564 + e040590 commit 9933683
Show file tree
Hide file tree
Showing 39 changed files with 1,348 additions and 283 deletions.
23 changes: 16 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.7, 3.8]
python-version: [3.8]

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -67,14 +67,14 @@ jobs:
TAG_NAME=${GITHUB_REF##*/}
# Change slashes to hyphens
TAG_NAME=${TAG_NAME//\//-}
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t flyte/mqtt-io:${TAG_NAME} -t flyte/mqtt-io:latest --push --build-arg BUILDX_QEMU_ENV=true .
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t flyte/mqtt-io:${TAG_NAME} -t flyte/mqtt-io:latest --push .
- if: github.event_name == 'push'
run: |
# Remove prefix push
TAG_NAME=${GITHUB_REF##*/}
# Change slashes to hyphens
TAG_NAME=${TAG_NAME//\//-}
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t flyte/mqtt-io:${TAG_NAME} --push --build-arg BUILDX_QEMU_ENV=true .
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 -t flyte/mqtt-io:${TAG_NAME} --push .
generate_docs:
name: Generate Documentation
Expand All @@ -85,19 +85,28 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- id: branch-name
uses: tj-actions/[email protected]
- name: Ensure we can checkout gh-pages
- name: Get branch names
id: branch-names
uses: tj-actions/branch-names@v8
- name: Ensure we can checkout gh-pages for release (${{ steps.branch-names.outputs.tag }})
if: steps.branch-names.outputs.is_tag == 'true'
run: |
git checkout gh-pages
git checkout ${{ steps.branch-name.outputs.current_branch }}
git checkout ${{ steps.branch-names.outputs.tag }}
- name: Ensure we can checkout gh-pages for pr (${{ steps.branch-names.outputs.current_branch }})
if: steps.branch-names.outputs.is_tag == 'false'
run: |
git checkout gh-pages
git checkout ${{ steps.branch-names.outputs.current_branch }}
- name: Setup Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies and generate docs
run: |
pip install poetry
ls
git status
poetry install
poetry run python docs_src/generate_docs.py
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,34 @@ Unreleased
==========
- Nothing!

.v2.4.0 - 2024-07-20
====================
- Bump tj-actions/branch-names from 2.2 to 7.0.7 in /.github/workflows by @dependabot in https://github.com/flyte/mqtt-io/pull/339
- # Fix for poetry/docutils related bug by @BenjiU in https://github.com/flyte/mqtt-io/pull/367
- upgrade DHT11/DHT22 backing library by @pansila in https://github.com/flyte/mqtt-io/pull/297
- Install gcc for slim docker to build rpi.gpio on demand by @BenjiU in https://github.com/flyte/mqtt-io/pull/368
- Remove lint warnings from bmp085.py by @BenjiU in https://github.com/flyte/mqtt-io/pull/375
- Add support for YF-S201 flow rate sensor by @linucks in https://github.com/flyte/mqtt-io/pull/370
- Support for ENS160 digital multi-gas sensor with multiple IAQ data (TVOC, eCO2, AQI) by @linucks in https://github.com/flyte/mqtt-io/pull/371
- feat: add MH-Z19 sensor module by @kleest in https://github.com/flyte/mqtt-io/pull/365
- Add Support for Sunxi Linux Boards by @fabys77 in https://github.com/flyte/mqtt-io/pull/100

.v2.3.0 - 2024-03-01
====================
- 324 pinned pyyaml version incompatible with latest cython 300 by @BenjiU in #325
- fix pipeline for tagging by @BenjiU in #323
- pin pyyaml to v6.0.1 by @BenjiU in #326
- Add new module for sensor adxl345 by @birdie1 in #223
- Sensor INA219: Use optional i2c_bus_num by @mschlenstedt in #328
- Update ads1x15.py by @maxthebuch in #329
- repeat subscribe when reconnected to MQTT broker by @JohannesHennecke in #337
- Fix non-unique identifiers reporting to HA by @dolai1 in #345
- docker: use a "slim" base image by @chatziko in #342
- Fix applying mqtt.reconnect_count by reordering except clauses by @zzeekk in #331
- Add PMS5003 Particulate Sensor by @johnwang16 in #346
- gpiod: enable pullup/pulldown by @chatziko in #341
- docker: slim image, use rustup, build deps only on armv7 by @chatziko in #352

.v2.2.9d - 2023-07-18
====================
- new sensors
Expand Down
36 changes: 19 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,49 @@
# when building multiarch using buildx, then try this:
# https://github.com/docker/buildx/issues/495#issuecomment-761562905

FROM python:3.8-buster AS base
FROM python:3.8-slim-buster AS base

ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8


FROM base AS requirements

ARG BUILDX_QEMU_ENV
RUN apt-get update && \
apt-get install -y lsb-release rustc libssl-dev libffi-dev python3-venv && \
apt-get clean && \
rm -rf /var/lib/apt-/lists/*
# On linux/arm/v7 the cryptography package has no binary wheel, so we need its build
# dependencies. For rust, install the latest from rustup to avoid issues.
ARG TARGETPLATFORM
RUN if [ "${TARGETPLATFORM}" = "linux/arm/v7" ]; then \
apt-get update && \
apt-get install -y lsb-release curl g++ pkg-config libssl-dev libffi-dev && \
\
(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y) \
fi
ENV PATH="/root/.cargo/bin:${PATH}"

# This nonsense is required for this reason:
# https://github.com/JonasAlfredsson/docker-nginx-certbot/issues/30

RUN pip install --no-cache-dir wheel setuptools-rust && \
if [ "${BUILDX_QEMU_ENV}" = "true" -a "$(getconf LONG_BIT)" = "32" ]; then \
pip install --no-cache-dir cryptography==3.3.2; \
fi && \
pip install --no-cache-dir poetry

COPY pyproject.toml ./
RUN poetry export -o /requirements.txt && \
RUN pip install --no-cache-dir poetry && \
poetry export -o /requirements.txt && \
mkdir -p /home/mqtt_io && \
python -m venv /home/mqtt_io/venv && \
/home/mqtt_io/venv/bin/pip install wheel


FROM base

# Install gcc so packages installed durring runtime may be build
RUN apt-get update && apt-get install -y gcc && gcc --version

RUN useradd -m -s /bin/bash mqtt_io
USER mqtt_io
WORKDIR /home/mqtt_io

COPY --from=requirements --chown=mqtt_io /home/mqtt_io/venv ./venv
COPY --from=requirements /requirements.txt ./
RUN venv/bin/python -m pip install --upgrade pip
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/python -m pip install --no-cache-dir --upgrade pip
RUN venv/bin/pip install --no-cache-dir -r requirements.txt

COPY --chown=mqtt_io mqtt_io mqtt_io
RUN gcc --version

CMD [ "venv/bin/python", "-m", "mqtt_io", "/config.yml" ]
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ Hardware support is provided by specific GPIO, Sensor and Stream modules. It's e
- BME680 temperature, humidity and pressure sensor (`bme680`)
- DHT11/DHT22/AM2302 temperature and humidity sensors (`dht22`)
- DS18S20/DS1822/DS18B20/DS1825/DS28EA00/MAX31850K temperature sensors (`ds18b`)
- ENS160 digital multi-gas sensor with multiple IAQ data (TVOC, eCO2, AQI) (`ens160`)
- HCSR04 ultrasonic range sensor (connected to the Raspberry Pi on-board GPIO) (`hcsr04`)
- INA219 DC current sensor (`ina219`)
- LM75 temperature sensor (`lm75`)
- MCP3008 analog to digital converter (`mcp3008`)
- ADXl345 3-axis accelerometer up to ±16g (`adxl345`)
- PMS5003 particulate sensor (`pms5003`)
- SHT40/SHT41/SHT45 temperature and humidity sensors (`sht4x`)
- YF-S201 flow rate sensor (`yfs201`)
- FLOWSENSOR generic flow rate sensor like YF-S201 or YF-DN50 (`flowsensor`)

### Streams

Expand Down
11 changes: 11 additions & 0 deletions config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ sensor_modules:
type: DS18S20
address: 000803702e49

- name: mhz19
module: mhz19
device: "/dev/ttyS1"
range: 5000

digital_inputs:
- name: button
module: raspberrypi
Expand Down Expand Up @@ -89,3 +94,9 @@ stream_modules:
ha_discovery:
unique_id: mmwave_uart
name: MMWave UART
- name: co2_mhz19
module: mhz19
interval: 30
ha_discovery:
name: CO2 MH-Z19
device_class: carbon_dioxide
2 changes: 1 addition & 1 deletion mqtt_io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Top level of MQTT IO package.
"""

VERSION = "2.2.9"
VERSION = "2.5.1"
10 changes: 5 additions & 5 deletions mqtt_io/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ def custom_validate_main_config(config: ConfigType) -> ConfigType:
bad_configs: Dict[str, Dict[str, List[str]]] = {}

# Make sure each of the IO configs refer to an existing module config
module_and_io_sections = dict(
gpio_modules=("digital_inputs", "digital_outputs"),
sensor_modules=("sensor_inputs",),
stream_modules=("stream_reads", "stream_writes"),
)
module_and_io_sections = {
"gpio_modules": ("digital_inputs", "digital_outputs"),
"sensor_modules": ("sensor_inputs",),
"stream_modules": ("stream_reads", "stream_writes"),
}
for module_section, io_sections in module_and_io_sections.items():
validate_gpio_module_names(bad_configs, config, module_section, io_sections)

Expand Down
4 changes: 2 additions & 2 deletions mqtt_io/config/config.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ mqtt:
description: MQTT Client implementation module path.
extra_info: |
There's currently only one implementation, which uses the
[asyncio-mqtt](https://github.com/sbtinstruments/asyncio-mqtt/) client.
[aiomqtt](https://github.com/sbtinstruments/aiomqtt/) client.
type: string
required: no
default: mqtt_io.mqtt.asyncio_mqtt
default: mqtt_io.mqtt.aiomqtt
ha_discovery:
type: dict
required: no
Expand Down
2 changes: 1 addition & 1 deletion mqtt_io/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
STREAM_TOPIC = "stream"

MODULE_IMPORT_PATH = "mqtt_io.modules"
MODULE_CLASS_NAMES = dict(gpio="GPIO", sensor="Sensor", stream="Stream")
MODULE_CLASS_NAMES = {"gpio": 'GPIO', "sensor": 'Sensor', "stream": 'Stream'}

MQTT_SUB_PRIORITY = 1
MQTT_ANNOUNCE_PRIORITY = 2
Expand Down
12 changes: 12 additions & 0 deletions mqtt_io/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ class StreamDataSentEvent(Event):
stream_name: str
data: bytes

@dataclass
class StreamDataSubscribeEvent(Event):
"""
Trigger MQTT subscribe
"""

@dataclass
class DigitalSubscribeEvent(Event):
"""
Trigger MQTT subscribe
"""


class EventBus:
"""
Expand Down
58 changes: 29 additions & 29 deletions mqtt_io/home_assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ def get_common_config(
Return config that's common across all HQ discovery announcements.
"""
disco_conf: ConfigType = mqtt_conf["ha_discovery"]
config = dict(name=io_conf["name"])
config = {"name": io_conf['name']}
config.update(
dict(
availability_topic="/".join(
{
"availability_topic": '/'.join(
(mqtt_conf["topic_prefix"], mqtt_conf["status_topic"])
),
payload_available=mqtt_conf["status_payload_running"],
payload_not_available=mqtt_conf["status_payload_dead"],
device=dict(
manufacturer="MQTT IO",
model=f"v{VERSION}",
identifiers=["mqtt-io", mqtt_options.client_id],
name=disco_conf["name"],
),
)
"payload_available": mqtt_conf["status_payload_running"],
"payload_not_available": mqtt_conf["status_payload_dead"],
"device": {
"manufacturer": 'MQTT IO',
"model": f'v{VERSION}',
"identifiers": [mqtt_options.client_id],
"name": disco_conf["name"],
},
}
)
config.update(io_conf.get("ha_discovery", {}))
return config
Expand All @@ -56,12 +56,12 @@ def hass_announce_digital_input(
disco_prefix: str = disco_conf["prefix"]
sensor_config = get_common_config(in_conf, mqtt_conf, mqtt_options)
sensor_config.update(
dict(
unique_id=f"{mqtt_options.client_id}_{in_conf['module']}_input_{name}",
state_topic="/".join((mqtt_conf["topic_prefix"], INPUT_TOPIC, name)),
payload_on=in_conf["on_payload"],
payload_off=in_conf["off_payload"],
)
{
"unique_id": f'{mqtt_options.client_id}_{in_conf["module"]}_input_{name}',
"state_topic": '/'.join((mqtt_conf["topic_prefix"], INPUT_TOPIC, name)),
"payload_on": in_conf["on_payload"],
"payload_off": in_conf["off_payload"],
}
)
return MQTTMessageSend(
"/".join(
Expand Down Expand Up @@ -92,13 +92,13 @@ def hass_announce_digital_output(
disco_prefix: str = disco_conf["prefix"]
switch_config = get_common_config(out_conf, mqtt_conf, mqtt_options)
switch_config.update(
dict(
unique_id=f"{mqtt_options.client_id}_{out_conf['module']}_output_{name}",
state_topic="/".join((prefix, OUTPUT_TOPIC, name)),
command_topic="/".join((prefix, OUTPUT_TOPIC, name, SET_SUFFIX)),
payload_on=out_conf["on_payload"],
payload_off=out_conf["off_payload"],
)
{
"unique_id": f'{mqtt_options.client_id}_{out_conf["module"]}_output_{name}',
"state_topic": '/'.join((prefix, OUTPUT_TOPIC, name)),
"command_topic": '/'.join((prefix, OUTPUT_TOPIC, name, SET_SUFFIX)),
"payload_on": out_conf["on_payload"],
"payload_off": out_conf["off_payload"],
}
)
return MQTTMessageSend(
"/".join(
Expand Down Expand Up @@ -129,10 +129,10 @@ def hass_announce_sensor_input(
disco_prefix: str = disco_conf["prefix"]
sensor_config = get_common_config(sens_conf, mqtt_conf, mqtt_options)
sensor_config.update(
dict(
unique_id=f"{mqtt_options.client_id}_{sens_conf['module']}_sensor_{name}",
state_topic="/".join((prefix, SENSOR_TOPIC, name)),
)
{
"unique_id": f'{mqtt_options.client_id}_{sens_conf["module"]}_sensor_{name}',
"state_topic": '/'.join((prefix, SENSOR_TOPIC, name)),
}
)
if "expire_after" not in sensor_config:
sensor_config["expire_after"] = sens_conf["interval"] * 2 + 5
Expand Down
4 changes: 2 additions & 2 deletions mqtt_io/modules/gpio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import asyncio
import logging
from concurrent.futures import ThreadPoolExecutor
from enum import Enum, Flag, auto
from enum import Enum, Flag, IntFlag, auto
from typing import Any, Callable, Dict, Iterable, List, Optional

from ...types import ConfigType, PinType
Expand Down Expand Up @@ -48,7 +48,7 @@ class InterruptEdge(Enum):
BOTH = auto()


class InterruptSupport(Flag):
class InterruptSupport(IntFlag):
"""
Classifies the kind of support a GPIO module has for interrupts.
Expand Down
Loading

0 comments on commit 9933683

Please sign in to comment.