updates2mqtt 1.3.4__py3-none-any.whl → 1.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- updates2mqtt/app.py +15 -6
- updates2mqtt/config.py +34 -19
- updates2mqtt/mqtt.py +16 -4
- {updates2mqtt-1.3.4.dist-info → updates2mqtt-1.3.6.dist-info}/METADATA +10 -132
- {updates2mqtt-1.3.4.dist-info → updates2mqtt-1.3.6.dist-info}/RECORD +8 -8
- {updates2mqtt-1.3.4.dist-info → updates2mqtt-1.3.6.dist-info}/WHEEL +0 -0
- {updates2mqtt-1.3.4.dist-info → updates2mqtt-1.3.6.dist-info}/entry_points.txt +0 -0
- {updates2mqtt-1.3.4.dist-info → updates2mqtt-1.3.6.dist-info}/licenses/LICENSE +0 -0
updates2mqtt/app.py
CHANGED
|
@@ -39,7 +39,8 @@ class App:
|
|
|
39
39
|
self.last_scan_timestamp: str | None = None
|
|
40
40
|
app_config: Config | None = load_app_config(CONF_FILE)
|
|
41
41
|
if app_config is None:
|
|
42
|
-
log.error(f"Invalid configuration at {CONF_FILE},
|
|
42
|
+
log.error(f"Invalid configuration at {CONF_FILE}, edit config to fix missing or invalid values and restart")
|
|
43
|
+
log.error("Exiting app")
|
|
43
44
|
sys.exit(1)
|
|
44
45
|
self.cfg: Config = app_config
|
|
45
46
|
|
|
@@ -98,12 +99,17 @@ class App:
|
|
|
98
99
|
for scanner in self.scanners:
|
|
99
100
|
self.publisher.subscribe_hass_command(scanner)
|
|
100
101
|
|
|
101
|
-
while not self.stopped.is_set():
|
|
102
|
+
while not self.stopped.is_set() and self.publisher.is_available():
|
|
102
103
|
await self.scan()
|
|
103
|
-
if not self.stopped.is_set():
|
|
104
|
+
if not self.stopped.is_set() and self.publisher.is_available():
|
|
104
105
|
await asyncio.sleep(self.cfg.scan_interval)
|
|
105
106
|
else:
|
|
106
107
|
log.info("Stop requested, exiting run loop and skipping sleep")
|
|
108
|
+
|
|
109
|
+
if not self.publisher.is_available():
|
|
110
|
+
log.error("MQTT fatal connection error - check host,port,user,password in config")
|
|
111
|
+
self.shutdown(exit_code=1)
|
|
112
|
+
|
|
107
113
|
log.debug("Exiting run loop")
|
|
108
114
|
|
|
109
115
|
async def on_discovery(self, discovery: Discovery) -> None:
|
|
@@ -143,8 +149,8 @@ class App:
|
|
|
143
149
|
await asyncio.gather(*running_tasks, return_exceptions=True)
|
|
144
150
|
log.debug("Cancellation task completed")
|
|
145
151
|
|
|
146
|
-
def shutdown(self, *args) -> None: # noqa: ANN002
|
|
147
|
-
log.info("Shutting down
|
|
152
|
+
def shutdown(self, *args, exit_code: int = 143) -> None: # noqa: ANN002, ARG002
|
|
153
|
+
log.info("Shutting down, exit_code: %s", exit_code)
|
|
148
154
|
self.stopped.set()
|
|
149
155
|
for scanner in self.scanners:
|
|
150
156
|
scanner.stop()
|
|
@@ -154,8 +160,11 @@ class App:
|
|
|
154
160
|
self.publisher.stop()
|
|
155
161
|
log.debug("Interrupt: %s", interrupt_task.done())
|
|
156
162
|
log.info("Shutdown handling complete")
|
|
163
|
+
sys.exit(exit_code) # SIGTERM Graceful Exit = 143
|
|
157
164
|
|
|
158
165
|
async def healthcheck(self) -> None:
|
|
166
|
+
if not self.publisher.is_available():
|
|
167
|
+
return
|
|
159
168
|
self.publisher.publish(
|
|
160
169
|
topic=self.healthcheck_topic,
|
|
161
170
|
payload={
|
|
@@ -177,7 +186,7 @@ async def repeated_call(func: Callable, interval: int = 60, *args: Any, **kwargs
|
|
|
177
186
|
await func(*args, **kwargs)
|
|
178
187
|
await asyncio.sleep(interval)
|
|
179
188
|
except asyncio.CancelledError:
|
|
180
|
-
log.
|
|
189
|
+
log.debug("Periodic task cancelled")
|
|
181
190
|
except Exception:
|
|
182
191
|
log.exception("Periodic task failed")
|
|
183
192
|
|
updates2mqtt/config.py
CHANGED
|
@@ -4,17 +4,17 @@ from dataclasses import dataclass, field
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
|
-
from omegaconf import MISSING, MissingMandatoryValue, OmegaConf, ValidationError
|
|
7
|
+
from omegaconf import MISSING, DictConfig, MissingMandatoryValue, OmegaConf, ValidationError
|
|
8
8
|
|
|
9
9
|
log = structlog.get_logger()
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@dataclass
|
|
13
13
|
class MqttConfig:
|
|
14
|
-
host: str = "localhost"
|
|
15
|
-
user: str = MISSING
|
|
16
|
-
password: str = MISSING
|
|
17
|
-
port: int = 1883
|
|
14
|
+
host: str = "${oc.env:MQTT_HOST,localhost}"
|
|
15
|
+
user: str = f"${{oc.env:MQTT_USER,{MISSING}}}"
|
|
16
|
+
password: str = f"${{oc.env:MQTT_PASS,{MISSING}}}"
|
|
17
|
+
port: int = "${oc.decode:${oc.env:MQTT_PORT,1883}}" # type: ignore[assignment]
|
|
18
18
|
topic_root: str = "updates2mqtt"
|
|
19
19
|
|
|
20
20
|
|
|
@@ -96,6 +96,10 @@ class UpdateInfoConfig:
|
|
|
96
96
|
common_packages: dict[str, PackageUpdateInfo] = field(default_factory=lambda: {})
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
class IncompleteConfigException(BaseException):
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
|
|
99
103
|
def load_package_info(pkginfo_file_path: Path) -> UpdateInfoConfig:
|
|
100
104
|
if pkginfo_file_path.exists():
|
|
101
105
|
log.debug("Loading common package update info", path=pkginfo_file_path)
|
|
@@ -107,29 +111,40 @@ def load_package_info(pkginfo_file_path: Path) -> UpdateInfoConfig:
|
|
|
107
111
|
return typing.cast("UpdateInfoConfig", cfg)
|
|
108
112
|
|
|
109
113
|
|
|
110
|
-
def load_app_config(conf_file_path: Path) -> Config | None:
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
def load_app_config(conf_file_path: Path, return_invalid: bool = False) -> Config | None:
|
|
115
|
+
base_cfg: DictConfig = OmegaConf.structured(Config)
|
|
116
|
+
is_new: bool = False
|
|
113
117
|
if conf_file_path.exists():
|
|
114
|
-
cfg = OmegaConf.merge(base_cfg, OmegaConf.load(conf_file_path))
|
|
118
|
+
cfg: DictConfig = typing.cast("DictConfig", OmegaConf.merge(base_cfg, OmegaConf.load(conf_file_path)))
|
|
115
119
|
else:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
if not conf_file_path.parent.exists():
|
|
121
|
+
try:
|
|
122
|
+
log.debug(f"Creating config directory {conf_file_path.parent} if not already present")
|
|
123
|
+
conf_file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
124
|
+
except Exception:
|
|
125
|
+
log.exception("Unable to create config directory", path=conf_file_path.parent)
|
|
122
126
|
try:
|
|
123
127
|
conf_file_path.write_text(OmegaConf.to_yaml(base_cfg))
|
|
128
|
+
log.info(f"Auto-generated a new config file at {conf_file_path}")
|
|
129
|
+
log.info("The config has place holders for MQTT user and password")
|
|
130
|
+
is_new = True
|
|
124
131
|
except Exception:
|
|
125
132
|
log.exception("Unable to write config file", path=conf_file_path)
|
|
126
133
|
cfg = base_cfg
|
|
127
134
|
|
|
128
135
|
try:
|
|
129
136
|
# Validate that all required fields are present, throw exception now rather than when config first used
|
|
130
|
-
OmegaConf.to_container(cfg, throw_on_missing=
|
|
137
|
+
OmegaConf.to_container(cfg, throw_on_missing=True)
|
|
131
138
|
OmegaConf.set_readonly(cfg, True)
|
|
132
|
-
|
|
139
|
+
config: Config = typing.cast("Config", cfg)
|
|
140
|
+
if config.mqtt.user == MISSING or config.mqtt.password == MISSING:
|
|
141
|
+
if not is_new:
|
|
142
|
+
log.warning("MQTT connection configuration has place holders")
|
|
143
|
+
if not is_new and not return_invalid:
|
|
144
|
+
return None
|
|
145
|
+
return config
|
|
133
146
|
except (MissingMandatoryValue, ValidationError) as e:
|
|
134
|
-
log.error("Configuration error
|
|
135
|
-
|
|
147
|
+
log.error("Configuration error %s", e, path=conf_file_path.as_posix())
|
|
148
|
+
if return_invalid and cfg is not None:
|
|
149
|
+
return typing.cast("Config", cfg)
|
|
150
|
+
raise
|
updates2mqtt/mqtt.py
CHANGED
|
@@ -3,13 +3,14 @@ import json
|
|
|
3
3
|
import time
|
|
4
4
|
from collections.abc import Callable
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
|
+
from threading import Event
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
8
9
|
import paho.mqtt.client as mqtt
|
|
9
10
|
import paho.mqtt.subscribeoptions
|
|
10
11
|
import structlog
|
|
11
12
|
from paho.mqtt.client import MQTTMessage
|
|
12
|
-
from paho.mqtt.enums import CallbackAPIVersion
|
|
13
|
+
from paho.mqtt.enums import CallbackAPIVersion, MQTTErrorCode
|
|
13
14
|
from paho.mqtt.properties import Properties
|
|
14
15
|
from paho.mqtt.reasoncodes import ReasonCode
|
|
15
16
|
|
|
@@ -35,6 +36,7 @@ class MqttClient:
|
|
|
35
36
|
self.providers_by_topic: dict[str, ReleaseProvider] = {}
|
|
36
37
|
self.event_loop: asyncio.AbstractEventLoop | None = None
|
|
37
38
|
self.client: mqtt.Client | None = None
|
|
39
|
+
self.fatal_failure = Event()
|
|
38
40
|
self.log = structlog.get_logger().bind(host=cfg.host, integration="mqtt")
|
|
39
41
|
|
|
40
42
|
def start(self, event_loop: asyncio.AbstractEventLoop | None = None) -> None:
|
|
@@ -47,7 +49,8 @@ class MqttClient:
|
|
|
47
49
|
clean_session=True,
|
|
48
50
|
)
|
|
49
51
|
self.client.username_pw_set(self.cfg.user, password=self.cfg.password)
|
|
50
|
-
self.client.connect(host=self.cfg.host, port=self.cfg.port, keepalive=60)
|
|
52
|
+
rc: MQTTErrorCode = self.client.connect(host=self.cfg.host, port=self.cfg.port, keepalive=60)
|
|
53
|
+
self.log.info("Client connection requested", result_code=rc)
|
|
51
54
|
|
|
52
55
|
self.client.on_connect = self.on_connect
|
|
53
56
|
self.client.on_disconnect = self.on_disconnect
|
|
@@ -66,12 +69,19 @@ class MqttClient:
|
|
|
66
69
|
self.client.disconnect()
|
|
67
70
|
self.client = None
|
|
68
71
|
|
|
72
|
+
def is_available(self) -> bool:
|
|
73
|
+
return not self.fatal_failure.is_set()
|
|
74
|
+
|
|
69
75
|
def on_connect(
|
|
70
76
|
self, _client: mqtt.Client, _userdata: Any, _flags: mqtt.ConnectFlags, rc: ReasonCode, _props: Properties | None
|
|
71
77
|
) -> None:
|
|
72
|
-
if not self.client:
|
|
73
|
-
self.log.warn("No client, check if started")
|
|
78
|
+
if not self.client or self.fatal_failure.is_set():
|
|
79
|
+
self.log.warn("No client, check if started and authorized")
|
|
74
80
|
return
|
|
81
|
+
if rc.getName() == "Not authorized":
|
|
82
|
+
self.fatal_failure.set()
|
|
83
|
+
log.error("Invalid MQTT credentials", result_code=rc)
|
|
84
|
+
|
|
75
85
|
self.log.info("Connected to broker", result_code=rc)
|
|
76
86
|
for topic in self.providers_by_topic:
|
|
77
87
|
self.log.info("(Re)subscribing", topic=topic)
|
|
@@ -91,6 +101,8 @@ class MqttClient:
|
|
|
91
101
|
self, provider: ReleaseProvider, last_scan_session: str | None, wait_time: int = 5, force: bool = False
|
|
92
102
|
) -> None:
|
|
93
103
|
logger = self.log.bind(action="clean")
|
|
104
|
+
if self.fatal_failure.is_set():
|
|
105
|
+
return
|
|
94
106
|
logger.info("Starting clean cycle")
|
|
95
107
|
cleaner = mqtt.Client(
|
|
96
108
|
callback_api_version=CallbackAPIVersion.VERSION1,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: updates2mqtt
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.6
|
|
4
4
|
Summary: System update and docker image notification and execution over MQTT
|
|
5
5
|
Project-URL: Repository, https://github.com/rhizomatics/updates2mqtt
|
|
6
6
|
Project-URL: Documentation, https://updates2mqtt.rhizomatics.org.uk
|
|
@@ -52,147 +52,25 @@ Use Home Assistant to notify you of updates to Docker images for your containers
|
|
|
52
52
|
|
|
53
53
|
## Description
|
|
54
54
|
|
|
55
|
-
updates2mqtt perioidically checks for new versions of components being available, and publishes new version info to MQTT.
|
|
56
|
-
HomeAssistant auto discovery is supported, so all updates can be seen in the same place as Home Assistant's
|
|
57
|
-
own components and add-ins.
|
|
55
|
+
updates2mqtt perioidically checks for new versions of components being available, and publishes new version info to MQTT. HomeAssistant auto discovery is supported, so all updates can be seen in the same place as Home Assistant's own components and add-ins.
|
|
58
56
|
|
|
59
|
-
Currently only Docker containers are supported, either via an image registry check, or a git repo for source. The design is modular, so other update sources can be added, at least for notification. The next anticipated is **apt** for Debian based systems.
|
|
57
|
+
Currently only Docker containers are supported, either via an image registry check, or a git repo for source (see [Local Builds](local_builds.md)). The design is modular, so other update sources can be added, at least for notification. The next anticipated is **apt** for Debian based systems.
|
|
60
58
|
|
|
61
|
-
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install*
|
|
62
|
-
button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience.
|
|
59
|
+
Components can also be updated, either automatically or triggered via MQTT, for example by hitting the *Install* button in the HomeAssistant update dialog. Icons and release notes can be specified for a better HA experience.
|
|
63
60
|
|
|
64
|
-
|
|
61
|
+
To get started, read the [Installation](installation.md) and [Configuration](configuration.md) pages.
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
### Manual
|
|
69
|
-
```
|
|
70
|
-
uv sync
|
|
71
|
-
uv run updates2mqtt
|
|
72
|
-
```
|
|
73
|
-
### Docker
|
|
74
|
-
|
|
75
|
-
See `examples` directory for a working `docker-compose.yaml`.
|
|
76
|
-
|
|
77
|
-
If you want to update and restart containers, then the file system paths to the location of the
|
|
78
|
-
directory where the docker compose file lives must be available in the updates2mqtt container.
|
|
79
|
-
|
|
80
|
-
The example `docker-compose.yaml` mounts `/home/containers` for this purpose, so if your containers are in
|
|
81
|
-
`/home/containers/app1`, `/home/containers/app2` etc, then updates2mqtt will be able to find them. Map as
|
|
82
|
-
many root paths as needed.
|
|
83
|
-
|
|
84
|
-
## Configuration
|
|
85
|
-
|
|
86
|
-
Create file `config.yaml` in `conf` directory. If the file is not present, a default file will be generated.
|
|
87
|
-
|
|
88
|
-
### Example configuration file
|
|
89
|
-
|
|
90
|
-
This is a maximal config file, the minimum is no config file at all, which will generate a default config file. The only mandatory values are the MQTT user name and password, everything else can be omitted.
|
|
63
|
+
For a quick spin, try this:
|
|
91
64
|
|
|
92
65
|
```yaml
|
|
93
|
-
|
|
94
|
-
node:
|
|
95
|
-
name: docker-host-1 # Unique name for this instance, used to name MQTT entities. Defaults to O/S hostname
|
|
96
|
-
git_repo_path: /usr/bin/git # Path to git inside container, needed only if non-default and using local docker builds
|
|
97
|
-
healthcheck:
|
|
98
|
-
enabled: true
|
|
99
|
-
interval: 300 # publish a heartbeat every 5 minutes
|
|
100
|
-
topic_template: healthcheck/{node_name}/updates2mqtt
|
|
101
|
-
mqtt:
|
|
102
|
-
host: ${oc.env:MQTT_HOST}
|
|
103
|
-
user: ${oc.env:MQTT_USER}
|
|
104
|
-
password: ${oc.env:MQTT_PASS}$ # Use an environment variable for secrets
|
|
105
|
-
port: ${oc.env:MQTT_PORT}
|
|
106
|
-
topic_root: updates2mqtt
|
|
107
|
-
homeassistant:
|
|
108
|
-
discovery:
|
|
109
|
-
prefix: homeassistant # Matches the default MQTT discovery prefix in Home Assistant
|
|
110
|
-
enabled: true
|
|
111
|
-
state_topic_suffix: state
|
|
112
|
-
docker:
|
|
113
|
-
enabled: true
|
|
114
|
-
allow_pull: true # if true, will do a `docker pull` if an update is available
|
|
115
|
-
allow_restart: true # if true, will do a `docker-compose up` if an update is installed
|
|
116
|
-
allow_build: true # if true, will do a `docker-compose build` if a git repo is configured
|
|
117
|
-
compose_version: v2 # Controls whether to use `docker-compose` (v1) or `docker compose` (v2) command
|
|
118
|
-
default_entity_picture_url: https://www.docker.com/wp-content/uploads/2022/03/Moby-logo.png # Picture for update dialog
|
|
119
|
-
device_icon: mdi:docker # Material Design Icon to use when browsing entities in Home Assistant
|
|
120
|
-
# device_icon: mdi:train-car-container # Alternative icon if you don't like Docker branding
|
|
121
|
-
discover_metadata:
|
|
122
|
-
linuxserver.io:
|
|
123
|
-
enabled: true
|
|
124
|
-
cache_ttl: 604800 # cache metadata for 1 week
|
|
125
|
-
scan_interval: 10800 # sleep interval between scan runs, in seconds
|
|
126
|
-
log:
|
|
127
|
-
level: INFO
|
|
66
|
+
docker run -e MQTT_USER=user1 -e MQTT_PASS=pass1 -e MQTT_HOST=192.168.1.5 ghcr.io/rhizomatics/updates2mqtt:release
|
|
128
67
|
```
|
|
129
68
|
|
|
130
|
-
### Moving Secrets Out of Config
|
|
131
|
-
|
|
132
|
-
Example use of environment variables, e.g. for secrets:
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
mqtt:
|
|
136
|
-
password: ${oc.env:MQTT_PASS}
|
|
137
|
-
```
|
|
138
|
-
### Customizing images and release notes
|
|
139
|
-
|
|
140
|
-
Individual docker containers can have customized entity pictures or release notes, using env variables, for example in the `docker-compose.yaml` or in a separate `.env` file:
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
environment:
|
|
144
|
-
- UPD2MQTT_PICTURE=https://frigate.video/images/logo.svg
|
|
145
|
-
- UPD2MQTT_RELNOTES=https://github.com/blakeblackshear/frigate/releases
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
The images will show up in the *Update* section of *Settings* menu in HomeAssistant,
|
|
149
|
-
as will the release notes link. SVG icons should be used.
|
|
150
|
-
|
|
151
|
-
Some popular services have the icon and release note links pre-configured, in `common_packages.yaml`,
|
|
152
|
-
and packages from `linuxserver.io` can have metadata automatically discovered.
|
|
153
|
-
|
|
154
|
-
#### Icon Sources
|
|
155
|
-
|
|
156
|
-
- [Homarr Dashboard Icons](https://github.com/homarr-labs/dashboard-icons)
|
|
157
|
-
- [Self Hosted Icons](https://github.com/selfhst/icons)
|
|
158
|
-
- [Simple Icons](https://github.com/simple-icons/simple-icons)
|
|
159
|
-
- [Tabler Icons](https://tabler.io/icons)
|
|
160
|
-
- [Papirus Icons](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme)
|
|
161
|
-
- [Homelab SVG Assets](https://github.com/loganmarchione/homelab-svg-assets)
|
|
162
|
-
|
|
163
|
-
### Automated updates
|
|
164
|
-
|
|
165
|
-
If Docker containers should be immediately updated, without any confirmation
|
|
166
|
-
or trigger, *e.g.* from the HomeAssistant update dialog, then set an environment variable `UPD2MQTT_UPDATE`
|
|
167
|
-
in the target container to `Auto` ( it defaults to `Passive`)
|
|
168
|
-
|
|
169
|
-
### Custom docker builds
|
|
170
|
-
|
|
171
|
-
If the image is locally built from a checked out git repo, package update can be driven
|
|
172
|
-
by the availability of git repo changes to pull rather than a new image on a Docker registry.
|
|
173
|
-
|
|
174
|
-
Declare the git path using the env var in ``UPD2MQTT_GIT_REPO_PATH`` in the docker container ( directly or via an ``.env`` file).
|
|
175
|
-
The git repo at this path will be used as the source of timestamps, and an update command will carry out a
|
|
176
|
-
``git pull`` and ``docker-compose build`` rather than pulling an image.
|
|
177
|
-
|
|
178
|
-
Note that the updates2mqtt docker container needs access to this path declared in its volumes, and that has to
|
|
179
|
-
be read/write if automated install required.
|
|
180
|
-
|
|
181
|
-
### Environment Variables
|
|
182
|
-
|
|
183
|
-
The following environment variables can be used to configure updates2mqtt:
|
|
184
|
-
|
|
185
|
-
| Env Var | Description | Default |
|
|
186
|
-
|---------| ------------|----------|
|
|
187
|
-
| `UPD2MQTT_UPDATE` | Update mode, either `Passive` or `Auto`. If `Auto`, updates will be installed automatically. | `Passive` |
|
|
188
|
-
| `UPD2MQTT_PICTURE` | URL to an icon to use in Home Assistant. | Docker logo URL |
|
|
189
|
-
| `UPD2MQTT_RELNOTES` | URL to release notes for the package. | |
|
|
190
|
-
| `UPD2MQTT_GIT_REPO_PATH` | Relative path to a local git repo if the image is built locally. | |
|
|
191
|
-
| `UPD2MQTT_IGNORE` | If set to `True`, the container will be ignored by updates2mqtt. | False |
|
|
192
|
-
|
|
193
|
-
|
|
194
69
|
## Release Support
|
|
195
70
|
|
|
71
|
+
Presently only Docker containers are supported, although others are planned,
|
|
72
|
+
probably with priority for `apt`.
|
|
73
|
+
|
|
196
74
|
| Ecosystem | Support | Comments |
|
|
197
75
|
|-----------|-------------|----------------------------------------------------------------------------------------------------|
|
|
198
76
|
| Docker | Scan. Fetch | Fetch is ``docker pull`` only. Restart support only for ``docker-compose`` image based containers. |
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
updates2mqtt/__init__.py,sha256=gnmHrLOSYc-N1-c5VG46OpNpoXEybKzYhEvFMm955P8,237
|
|
2
2
|
updates2mqtt/__main__.py,sha256=HBF00oH5fhS33sI_CdbxNlaUvbIzuuGxwnRYdhHqx0M,194
|
|
3
|
-
updates2mqtt/app.py,sha256=
|
|
4
|
-
updates2mqtt/config.py,sha256=
|
|
3
|
+
updates2mqtt/app.py,sha256=7jnmtIkXlX4e4lIt8WCzV19IYrICkA7cU4m9u9QXvRU,8229
|
|
4
|
+
updates2mqtt/config.py,sha256=5nBJyTkmDlgG32jHhi8mMrI4KjWCFl2NJunVYCAyIwQ,5156
|
|
5
5
|
updates2mqtt/hass_formatter.py,sha256=Ulfj8F0e_1QMmRuJzHsNM2WxHbz9sIkWOWjRq3kQZzs,2772
|
|
6
6
|
updates2mqtt/model.py,sha256=5tWlj3appGGZjkuBeYR2lb-kXoy5mzCn4P_EJQjnwok,3676
|
|
7
|
-
updates2mqtt/mqtt.py,sha256=
|
|
7
|
+
updates2mqtt/mqtt.py,sha256=i2l1BlEmnkp3Ie2qeAPVmdhIO1I_mH8Zxbm84cIYtGI,12741
|
|
8
8
|
updates2mqtt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
updates2mqtt/integrations/__init__.py,sha256=KmNTUxvVWvqI7rl4I0xZg7XaCmcMS2O4OSv-ClsWM4Q,109
|
|
10
10
|
updates2mqtt/integrations/docker.py,sha256=OX_sXtWVgUJfRSFi_tTBib4gvP_foQI4MoeTkTeLbZc,18868
|
|
11
11
|
updates2mqtt/integrations/git_utils.py,sha256=SkAp6XcvCHwaiy17t6F97kcWTjBd7RyEmfhz6M_EhP0,2196
|
|
12
|
-
updates2mqtt-1.3.
|
|
13
|
-
updates2mqtt-1.3.
|
|
14
|
-
updates2mqtt-1.3.
|
|
15
|
-
updates2mqtt-1.3.
|
|
16
|
-
updates2mqtt-1.3.
|
|
12
|
+
updates2mqtt-1.3.6.dist-info/METADATA,sha256=HAwitJE-bHBhD2mAOS_sQJOCPdjU4enU7J2b2OW2vA4,7675
|
|
13
|
+
updates2mqtt-1.3.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
+
updates2mqtt-1.3.6.dist-info/entry_points.txt,sha256=Hc6NZ2dBevYSUKTJU6NOs8Mw7Vt0S-9lq5FuKb76NCc,54
|
|
15
|
+
updates2mqtt-1.3.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
+
updates2mqtt-1.3.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|