refactor: extract mqtt_demo/ — move bridge, config, logger, appliance descriptors
This commit is contained in:
@@ -3,12 +3,15 @@ FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
|
||||
# Python deps first so layer cache survives code changes
|
||||
COPY requirements.txt .
|
||||
COPY mqtt_demo/requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Application code
|
||||
COPY main.py .
|
||||
COPY samsung_appliance/ ./samsung_appliance/
|
||||
# Application code — build context is the repo root (see
|
||||
# docker-compose.yml's `context: ..`) since mqtt_demo/ depends on the
|
||||
# protocol/ and ocf/ library packages that live alongside it.
|
||||
COPY protocol/ ./protocol/
|
||||
COPY ocf/ ./ocf/
|
||||
COPY mqtt_demo/ ./mqtt_demo/
|
||||
|
||||
# /config holds the ab0b0ac4 client cert + key. Mount from the host so
|
||||
# secrets aren't baked into the image.
|
||||
@@ -28,4 +31,4 @@ ENV CERT_PATH=/config/ab0b0ac4_fullchain.pem \
|
||||
|
||||
# No port — bridge is outbound-only (DTLS UDP to appliance, MQTT to broker).
|
||||
|
||||
CMD ["python", "main.py"]
|
||||
CMD ["python", "-m", "mqtt_demo"]
|
||||
@@ -23,10 +23,10 @@ import threading
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
|
||||
from samsung_appliance.appliances import get_descriptor
|
||||
from samsung_appliance.bridge import PushBridge
|
||||
from samsung_appliance.config import SharedConfig, load_appliances
|
||||
from samsung_appliance.logger import logger
|
||||
from mqtt_demo.samples import get_descriptor
|
||||
from mqtt_demo.bridge import PushBridge
|
||||
from mqtt_demo.config import SharedConfig, load_appliances
|
||||
from mqtt_demo.logger import logger
|
||||
|
||||
|
||||
def main():
|
||||
@@ -23,15 +23,17 @@ import time
|
||||
|
||||
import cbor2
|
||||
|
||||
from .appliances.base import ApplianceDescriptor, bridge_diagnostic_discovery
|
||||
from .config import ApplianceConfig, SharedConfig
|
||||
from .logger import bridge_logger
|
||||
from protocol.dtls_session import DtlsCoapSession, fmt_code
|
||||
|
||||
from ocf.keepalive import KeepaliveTask
|
||||
from ocf.observe_refresh import ObserveRefreshTask
|
||||
from ocf.poll_scheduler import PollScheduler
|
||||
from ocf.state_cache import StateCache
|
||||
|
||||
from .descriptor import ApplianceDescriptor, bridge_diagnostic_discovery
|
||||
from .config import ApplianceConfig, SharedConfig
|
||||
from .logger import bridge_logger
|
||||
|
||||
|
||||
DEBUG_BRIDGE = os.environ.get('DEBUG_BRIDGE') == '1'
|
||||
|
||||
@@ -20,8 +20,15 @@
|
||||
# certs in $APPDATA_DIR are preserved.
|
||||
set -e
|
||||
|
||||
if [ ! -f .env ]; then
|
||||
echo "Error: .env file not found. Copy .env.example to .env and configure it."
|
||||
# This script lives in mqtt_demo/ but the build context is the repo
|
||||
# root (mqtt_demo/docker-compose.yml uses `context: ..`, since the
|
||||
# image needs the protocol/ and ocf/ library packages alongside
|
||||
# mqtt_demo/). Run everything from the repo root so the tar allowlist
|
||||
# and remote layout line up with that context.
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
if [ ! -f mqtt_demo/.env ]; then
|
||||
echo "Error: mqtt_demo/.env file not found. Copy mqtt_demo/.env.example to mqtt_demo/.env and configure it."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -29,7 +36,7 @@ fi
|
||||
# Sourcing would tokenize unquoted spaces in values (e.g.
|
||||
# `APPLIANCE_1_NAME=Samsung Dryer`) as shell commands.
|
||||
get_env() {
|
||||
grep -E "^${1}=" .env | head -1 | cut -d= -f2-
|
||||
grep -E "^${1}=" mqtt_demo/.env | head -1 | cut -d= -f2-
|
||||
}
|
||||
SSH_HOST=$(get_env SSH_HOST)
|
||||
REMOTE_DIR=$(get_env REMOTE_DIR)
|
||||
@@ -44,22 +51,20 @@ ssh "${SSH_HOST}" mkdir -p "${REMOTE_DIR}" "${APPDATA_DIR}"
|
||||
|
||||
# Source code — explicit allowlist instead of an excludelist. Anything
|
||||
# else in the repo (research files, certs, logs, the .git dir) stays
|
||||
# local.
|
||||
# local. protocol/ and ocf/ are the library packages mqtt_demo/ imports
|
||||
# from; they need to land as REMOTE_DIR's siblings of mqtt_demo/ so the
|
||||
# compose file's `context: ..` resolves the same way it does locally.
|
||||
COPYFILE_DISABLE=1 tar cz \
|
||||
main.py \
|
||||
samsung_appliance/ \
|
||||
Dockerfile \
|
||||
docker-compose.yml \
|
||||
requirements.txt \
|
||||
deploy.sh \
|
||||
protocol/ \
|
||||
ocf/ \
|
||||
mqtt_demo/ \
|
||||
README.md \
|
||||
.env.example \
|
||||
.gitignore \
|
||||
| ssh "${SSH_HOST}" "cd ${REMOTE_DIR} && tar xz && find . -name '._*' -delete"
|
||||
|
||||
# Ship .env separately and lock it down on the remote.
|
||||
scp .env "${SSH_HOST}:${REMOTE_DIR}/.env"
|
||||
ssh "${SSH_HOST}" "chmod 600 ${REMOTE_DIR}/.env"
|
||||
scp mqtt_demo/.env "${SSH_HOST}:${REMOTE_DIR}/mqtt_demo/.env"
|
||||
ssh "${SSH_HOST}" "chmod 600 ${REMOTE_DIR}/mqtt_demo/.env"
|
||||
|
||||
# Verify certs are present on the remote — they have to be uploaded
|
||||
# once before the first build.
|
||||
@@ -74,7 +79,7 @@ if ! ssh "${SSH_HOST}" "test -s ${APPDATA_DIR}/client_fullchain.pem && test -s $
|
||||
fi
|
||||
|
||||
echo "Rebuilding container…"
|
||||
ssh "${SSH_HOST}" "cd ${REMOTE_DIR} && docker compose up -d --build"
|
||||
ssh "${SSH_HOST}" "cd ${REMOTE_DIR}/mqtt_demo && docker compose up -d --build"
|
||||
|
||||
echo "Done."
|
||||
echo "Logs: ssh ${SSH_HOST} 'cd ${REMOTE_DIR} && docker compose logs -f'"
|
||||
echo "Logs: ssh ${SSH_HOST} 'cd ${REMOTE_DIR}/mqtt_demo && docker compose logs -f'"
|
||||
@@ -27,7 +27,7 @@ from dataclasses import dataclass, field
|
||||
from typing import Callable, Optional, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..poll_scheduler import PollTier
|
||||
from ocf.poll_scheduler import PollTier
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -1,6 +1,8 @@
|
||||
services:
|
||||
smartthings-local:
|
||||
build: .
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: mqtt_demo/Dockerfile
|
||||
container_name: smartthings-local
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -9,7 +9,7 @@ Adding a new appliance class:
|
||||
main.py imports get_descriptor(name) to look up the descriptor at
|
||||
startup; the bridge itself stays class-agnostic.
|
||||
"""
|
||||
from .base import ApplianceDescriptor
|
||||
from ..descriptor import ApplianceDescriptor
|
||||
from .dryer import DRYER
|
||||
from .oven import OVEN
|
||||
from .fridge import FRIDGE
|
||||
@@ -6,14 +6,14 @@ samsung_dryer/{bridge,sensors,discovery}.py modules into one place.
|
||||
"""
|
||||
import time
|
||||
|
||||
from .base import (
|
||||
from ..descriptor import (
|
||||
ApplianceDescriptor,
|
||||
avail_base,
|
||||
avail_with_remote,
|
||||
device_block,
|
||||
encode,
|
||||
)
|
||||
from ..poll_scheduler import PollTier
|
||||
from ocf.poll_scheduler import PollTier
|
||||
|
||||
|
||||
# --- OBSERVE paths -----------------------------------------------------
|
||||
@@ -24,13 +24,13 @@ Key differences from newer Tizen RT firmware:
|
||||
"""
|
||||
import time
|
||||
|
||||
from .base import (
|
||||
from ..descriptor import (
|
||||
ApplianceDescriptor,
|
||||
avail_base,
|
||||
device_block,
|
||||
encode,
|
||||
)
|
||||
from ..poll_scheduler import PollTier
|
||||
from ocf.poll_scheduler import PollTier
|
||||
|
||||
|
||||
MODEL = 'ARTIK051_REF_17K'
|
||||
@@ -23,7 +23,7 @@ Untested writes are gated behind <prefix>/remote_available so HA
|
||||
disables them in the UI when the oven's Remote Control switch is off."""
|
||||
import time
|
||||
|
||||
from .base import (
|
||||
from ..descriptor import (
|
||||
ApplianceDescriptor,
|
||||
avail_base,
|
||||
avail_with_cycle,
|
||||
@@ -31,7 +31,7 @@ from .base import (
|
||||
device_block,
|
||||
encode,
|
||||
)
|
||||
from ..poll_scheduler import PollTier
|
||||
from ocf.poll_scheduler import PollTier
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
@@ -33,7 +33,9 @@ from .coap import (
|
||||
encode_options, parse_coap, build_coap, block_value, fmt_code,
|
||||
split_dtls as _split_dtls,
|
||||
)
|
||||
from samsung_appliance.logger import logger
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Diagnostic logging — when DEBUG_BRIDGE=1 in env, the bridge dumps
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
"""Samsung appliance local-API → MQTT bridge with HA discovery.
|
||||
|
||||
Multi-device: dryer, oven, etc. The device class is selected at startup
|
||||
via the DEVICE_CLASS env var (see samsung_appliance.appliances)."""
|
||||
__version__ = "2.0.0"
|
||||
Reference in New Issue
Block a user