From 7661ebc5027eacd603c596acd872e57a8323f599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sat, 14 Sep 2024 20:28:03 +0200 Subject: [PATCH 01/15] Update build.yml --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 563d52c..4387bb8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,10 +38,13 @@ jobs: include: - os: windows-2019 arch: x86 + zipname: tdmgr_x86 - os: windows-2019 arch: x64 - - os: macos-latest + zipname: tdmgr_x64 + - os: macos-13 arch: x64 + zipname: tdmgr_x64 steps: - uses: actions/checkout@v3 with: @@ -60,5 +63,5 @@ jobs: - name: Upload binaries artifact to workflow uses: actions/upload-artifact@v4 with: - name: tdmgr + name: ${{ matrix.zipname }} path: dist/* From ba7e4ad48dfde8533bdc1b773c54ee18c5363f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sat, 14 Sep 2024 23:54:17 +0200 Subject: [PATCH 02/15] Split releases (#270) --- .github/workflows/develop.yml | 32 --------- .github/workflows/master.yml | 43 ------------ .github/workflows/pytest.yml | 42 ++++++------ .github/workflows/{build.yml => release.yml} | 70 ++++++++++++-------- .github/workflows/release_pypi.yml | 36 ++++++++++ 5 files changed, 99 insertions(+), 124 deletions(-) delete mode 100644 .github/workflows/develop.yml delete mode 100644 .github/workflows/master.yml rename .github/workflows/{build.yml => release.yml} (53%) create mode 100644 .github/workflows/release_pypi.yml diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml deleted file mode 100644 index b6ee4ce..0000000 --- a/.github/workflows/develop.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Develop Branch Workflow - -on: - workflow_dispatch: - -jobs: - Build: - uses: ./.github/workflows/build.yml - secrets: inherit - - Upload: - needs: Build - runs-on: ubuntu-latest - steps: - - name: Install SSH key - uses: webfactory/ssh-agent@v0.5.3 - with: - ssh-private-key: ${{ secrets.ASSETS_PRIVATE_KEY }} - - - name: Download artifacts from build - uses: actions/download-artifact@v2 - with: - path: dist - - - name: Upload assets via SCP - env: - HOST: ${{ secrets.ASSETS_HOST }} - PORT: ${{ secrets.ASSETS_PORT }} - USER: ${{ secrets.ASSETS_USER }} - run: | - scp -P $PORT -o StrictHostKeyChecking=no -r dist/* $USER@$HOST:/files/ - shell: bash diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml deleted file mode 100644 index 134ef89..0000000 --- a/.github/workflows/master.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Master Branch Release Workflow - -on: - push: - tags: - - 'v*' - -jobs: - Build: - uses: ./.github/workflows/build.yml - secrets: inherit - - Draft-Release: - needs: Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - # Create a draft release - - name: Create Draft Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref_name }} - release_name: TDM ${{ github.ref_name }} - draft: true - - - name: Download artifacts from build - uses: actions/download-artifact@v2 - with: - path: dist - - # Upload release assets: each file in `dist/` to the GitHub Release - - name: Upload Release Assets - run: | - for asset in dist/tdmgr/*; do - echo "Uploading asset: $asset" - gh release upload "${{ github.ref_name }}" "$asset" --clobber - done - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 73a0be1..bb7e60d 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -1,28 +1,28 @@ name: PyTest on: - workflow_dispatch: - pull_request: + workflow_dispatch: + pull_request: jobs: - PyTest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 + PyTest: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.8' - - - name: Install dependencies - run: pip install -r requirements_dev.txt && pip install pytest-md + - uses: actions/setup-python@v4 + with: + python-version: '3.8' - - name: Run pytest - uses: pavelzw/pytest-action@v2 - with: - verbose: true - emoji: false - job-summary: true - custom-arguments: '-q' - click-to-expand: true - report-title: 'Test Report' + - name: Install dependencies + run: pip install -r requirements_dev.txt && pip install pytest-md + + - name: Run pytest + uses: pavelzw/pytest-action@v2 + with: + verbose: true + emoji: false + job-summary: true + custom-arguments: '-q' + click-to-expand: true + report-title: 'Test Report' diff --git a/.github/workflows/build.yml b/.github/workflows/release.yml similarity index 53% rename from .github/workflows/build.yml rename to .github/workflows/release.yml index 4387bb8..e141405 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/release.yml @@ -1,36 +1,16 @@ -name: Shared Build Workflow +name: Master Branch GitHub release on: - workflow_call: + push: + branches: + - master + - develop + paths-ignore: + - '.github/**' + - '**.md' jobs: - Wheel: - permissions: - id-token: write - - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - uses: actions/setup-python@v4 - with: - python-version: '3.8' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel setuptools_scm[toml] build - - - name: Build package - run: python -m build --wheel --outdir dist/ - - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - Binaries: - needs: Wheel runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -45,6 +25,7 @@ jobs: - os: macos-13 arch: x64 zipname: tdmgr_x64 + steps: - uses: actions/checkout@v3 with: @@ -54,6 +35,7 @@ jobs: with: python-version: '3.8' architecture: ${{ matrix.arch }} + - name: Install PyInstaller run: pip install -r requirements_build.txt @@ -65,3 +47,35 @@ jobs: with: name: ${{ matrix.zipname }} path: dist/* + + Draft-Release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + # Create a draft release + - name: Create Draft Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref_name }} + release_name: TDM ${{ github.ref_name }} + draft: true + prerelease: ${{ github.ref_name == 'refs/heads/develop'}} + + - name: Download artifacts from build + uses: actions/download-artifact@v2 + with: + path: dist + + # Upload release assets: each file in `dist/` to the GitHub Release + - name: Upload Release Assets + run: | + for asset in dist/tdmgr/*; do + echo "Uploading asset: $asset" + gh release upload "${{ github.ref_name }}" "$asset" --clobber + done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release_pypi.yml b/.github/workflows/release_pypi.yml new file mode 100644 index 0000000..b6456cc --- /dev/null +++ b/.github/workflows/release_pypi.yml @@ -0,0 +1,36 @@ +name: Master Branch PyPI release + +on: + push: + branches: + - master + paths-ignore: + - '.github/**' + - '**.md' + +jobs: + build_wheel_and_release: + permissions: + id-token: write + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v4 + with: + python-version: '3.8' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel build + + - name: Build package + run: python -m build --wheel --outdir dist/ + + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + From 40a142ec7eff3eda8fbb0d00463ec7c6ac8cd61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sat, 14 Sep 2024 23:57:45 +0200 Subject: [PATCH 03/15] Update release.yml --- .github/workflows/release.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e141405..d272f79 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,7 @@ -name: Master Branch GitHub release +name: GitHub release on: + workflow_dispatch: push: branches: - master @@ -17,15 +18,12 @@ jobs: matrix: include: - os: windows-2019 - arch: x86 - zipname: tdmgr_x86 + arch: x86 - os: windows-2019 - arch: x64 - zipname: tdmgr_x64 + arch: x64 - os: macos-13 arch: x64 - zipname: tdmgr_x64 - + steps: - uses: actions/checkout@v3 with: @@ -43,13 +41,14 @@ jobs: run: pyinstaller --noconfirm --clean tdmgr.spec - name: Upload binaries artifact to workflow - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: - name: ${{ matrix.zipname }} + name: tdmgr path: dist/* Draft-Release: runs-on: ubuntu-latest + needs: Binaries steps: - uses: actions/checkout@v3 @@ -66,7 +65,7 @@ jobs: prerelease: ${{ github.ref_name == 'refs/heads/develop'}} - name: Download artifacts from build - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: dist From f945d5e17af543ab8b04ba22f1727771c12542bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 01:35:17 +0200 Subject: [PATCH 04/15] refactor logging, misc refactors (#271) --- tdmgr/GUI/dialogs/main.py | 32 ++++++----------- tdmgr/run.py | 46 +++++++++++++----------- tdmgr/schemas/common.py | 13 ------- tdmgr/schemas/status.py | 73 ++++++++++++++++++++++----------------- tdmgr/util/__init__.py | 1 - tdmgr/util/mqtt.py | 10 +++--- 6 files changed, 83 insertions(+), 92 deletions(-) diff --git a/tdmgr/GUI/dialogs/main.py b/tdmgr/GUI/dialogs/main.py index f4b9309..312d524 100644 --- a/tdmgr/GUI/dialogs/main.py +++ b/tdmgr/GUI/dialogs/main.py @@ -1,7 +1,6 @@ import csv import logging import re -from logging.handlers import TimedRotatingFileHandler from PyQt5.QtCore import QDir, QFileInfo, QSettings, QSize, Qt, QTimer, QUrl, pyqtSlot from PyQt5.QtGui import QDesktopServices, QFont, QIcon @@ -34,6 +33,8 @@ from tdmgr.util.discovery import lwt_discovery_stage2 from tdmgr.util.mqtt import DEFAULT_PATTERNS, Message, MqttClient, expand_fulltopic +log = logging.getLogger(__name__) + class MainWindow(QMainWindow): def __init__( @@ -41,7 +42,6 @@ def __init__( version: str, settings: QSettings, devices: QSettings, - log_path: str, debug: bool, *args, **kwargs, @@ -69,17 +69,6 @@ def __init__( self.devices = devices self.setMinimumSize(QSize(1000, 600)) - # configure logging - logging.basicConfig( - level="DEBUG" if debug else "INFO", - datefmt="%Y-%m-%d %H:%M:%S", - format="%(asctime)s [%(levelname)s] %(message)s", - ) - logging.getLogger().addHandler( - TimedRotatingFileHandler(filename=log_path, when="d", interval=1) - ) - logging.info("### TDM START ###") - # load devices from the devices file, create TasmotaDevices and add the to the environment for mac in self.devices.childGroups(): self.devices.beginGroup(mac) @@ -129,6 +118,7 @@ def __init__( self.tele_docks = [] self.consoles = [] + log.info(f"### TDM {self._version} START ###") def setup_main_layout(self): self.mdi = QMdiArea() @@ -352,7 +342,7 @@ def mqtt_message(self, msg: Message): # try: # obj = DiscoverySchema.model_validate_json(msg.payload) # except ValueError: - # logging.error("Unable to parse Tasmota discovery message: %s", msg.payload) + # log.error("Unable to parse Tasmota discovery message: %s", msg.payload) # # if obj and not self.env.find_device(obj.t): # device = TasmotaDevice.from_discovery(obj) @@ -363,7 +353,7 @@ def mqtt_message(self, msg: Message): # # self.env.devices.append(device) # self.device_model.addDevice(device) - # logging.info( + # log.info( # "DISCOVERY(NATIVE): Discovered topic=%s with fulltopic=%s", # obj.t, # device.p["FullTopic"], @@ -375,7 +365,7 @@ def mqtt_message(self, msg: Message): if device := self.env.find_device(msg.topic): if msg.is_lwt: - logging.debug("MQTT: LWT message for %s: %s", device.p["Topic"], msg.payload) + log.debug("MQTT: LWT message for %s: %s", device.p["Topic"], msg.payload) device.update_property("LWT", msg.payload) if msg.payload == device.p["Online"]: @@ -396,7 +386,7 @@ def mqtt_message(self, msg: Message): # unknown device, start autodiscovery process if msg.is_lwt: self.env.lwts[msg.topic] = msg.payload - logging.info("DISCOVERY(LEGACY): LWT from an unknown device %s", msg.topic) + log.info("DISCOVERY(LEGACY): LWT from an unknown device %s", msg.topic) # STAGE 1 # load default and user-provided FullTopic patterns and for all the patterns, @@ -418,7 +408,7 @@ def mqtt_message(self, msg: Message): "/LWT", "/FullTopic" ) ) - logging.debug( + log.debug( "DISCOVERY(LEGACY): Asking an unknown device for FullTopic at %s", possible_topic_cmnd, ) @@ -429,7 +419,7 @@ def mqtt_message(self, msg: Message): if d := lwt_discovery_stage2(self.env, msg): self.env.devices.append(d) self.device_model.addDevice(d) - logging.debug("DISCOVERY: Sending initial query to topic %s", d.p["Topic"]) + log.debug("DISCOVERY: Sending initial query to topic %s", d.p["Topic"]) self.initial_query(d, True) tele_topic = d.tele_topic("LWT") self.env.lwts.pop(tele_topic, None) @@ -496,7 +486,7 @@ def clear_retained_topics(self): topic = itm.text() self.mqtt.publish(topic, retain=True) self.env.retained.remove(topic) - logging.info("MQTT: Cleared %s", topic) + log.info("MQTT: Cleared %s", topic) def prefs(self): dlg = PrefsDialog(self.settings) @@ -535,7 +525,7 @@ def open_config_file(self): @staticmethod def open_log_location(): - fi = QFileInfo(logging.getLogger().handlers[1].baseFilename) + fi = QFileInfo(log.getLogger().handlers[1].baseFilename) QDesktopServices.openUrl(QUrl.fromLocalFile(fi.absolutePath())) def auto_telemetry_period(self): diff --git a/tdmgr/run.py b/tdmgr/run.py index 22b0156..43e2194 100644 --- a/tdmgr/run.py +++ b/tdmgr/run.py @@ -4,6 +4,7 @@ import os import pathlib import sys +from logging.handlers import TimedRotatingFileHandler from PyQt5.QtCore import QDir, QSettings from PyQt5.QtWidgets import QApplication @@ -17,31 +18,33 @@ version = "" -def get_settings(args): - if args.local: - return QSettings("tdm.cfg", QSettings.IniFormat) - if args.config_location: - return QSettings(os.path.join(args.config_location, "tdm.cfg"), QSettings.IniFormat) - return QSettings(QSettings.IniFormat, QSettings.UserScope, "tdm", "tdm") +def configure_logging(args) -> None: + log_path = os.path.join(QDir.tempPath(), "tdm.log") - -def get_devices(args): if args.local: - return QSettings("devices.cfg", QSettings.IniFormat) - if args.config_location: - return QSettings(os.path.join(args.config_location, "devices.cfg"), QSettings.IniFormat) - return QSettings(QSettings.IniFormat, QSettings.UserScope, "tdm", "devices") + log_path = "tdm.log" + elif args.log_location: + log_path = os.path.join(args.log_location, "tdm.log") + + logging.basicConfig( + level="DEBUG" if args.debug else "INFO", + datefmt="%Y-%m-%d %H:%M:%S", + format="%(asctime)s [%(levelname)s] [%(filename)s] %(message)s", + ) + logging.getLogger(__name__).addHandler( + TimedRotatingFileHandler(filename=log_path, when="d", interval=1) + ) -def get_log_path(args): +def get_settings(args: argparse.Namespace, filename: str) -> QSettings: if args.local: - return "tdm.log" - if args.log_location: - return os.path.join(args.log_location, "tdm.log") - return os.path.join(QDir.tempPath(), "tdm.log") + return QSettings(f"{filename}.ini", QSettings.IniFormat) + if args.config_location: + return QSettings(os.path.join(args.config_location, f"{filename}.ini"), QSettings.IniFormat) + return QSettings(QSettings.IniFormat, QSettings.UserScope, "tdm", f"{filename}.ini") -def setup_parser(): +def setup_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(prog='Tasmota Device Manager') parser.add_argument('--debug', action='store_true', help='Enable debugging') parser.add_argument( @@ -54,17 +57,18 @@ def setup_parser(): return parser -def start(): +def start() -> None: parser = setup_parser() args = parser.parse_args() + configure_logging(args) try: app = QApplication(sys.argv) app.lastWindowClosed.connect(app.quit) app.setStyle("Fusion") - settings, devices, log_path = get_settings(args), get_devices(args), get_log_path(args) - MW = MainWindow(version, settings, devices, log_path, args.debug) + settings, devices = get_settings(args, "tdm"), get_settings(args, "devices") + MW = MainWindow(version, settings, devices, args.debug) MW.show() sys.exit(app.exec_()) diff --git a/tdmgr/schemas/common.py b/tdmgr/schemas/common.py index 83c0427..6c0d3a1 100644 --- a/tdmgr/schemas/common.py +++ b/tdmgr/schemas/common.py @@ -1,19 +1,6 @@ -import logging from enum import Enum -from pydantic import BaseModel, ConfigDict, model_validator - class OnOffEnum(str, Enum): ON = "ON" OFF = "OFF" - - -class TDMBaseModel(BaseModel): - model_config = ConfigDict(extra="allow") - - @model_validator(mode="after") - def log_extra_fields(cls, values): - if cls.__name__ != "StatusSNSSchema" and values.model_extra: - logging.warning("%s has extra fields: %s", cls.__name__, values.model_extra) - return values diff --git a/tdmgr/schemas/status.py b/tdmgr/schemas/status.py index 6bbffa4..741dbe6 100644 --- a/tdmgr/schemas/status.py +++ b/tdmgr/schemas/status.py @@ -1,11 +1,22 @@ +import logging from typing import List, Optional, Union -from pydantic import create_model +from pydantic import BaseModel, ConfigDict, create_model, model_validator -from tdmgr.schemas.common import TDMBaseModel +log = logging.getLogger(__name__) -class StatusSchema(TDMBaseModel): +class StatusBaseModel(BaseModel): + model_config = ConfigDict(extra="allow") + + @model_validator(mode="after") + def log_extra_fields(cls, values): + if cls.__name__ != "StatusSNSSchema" and values.model_extra: + log.warning("%s has extra fields: %s", cls.__name__, values.model_extra) + return values + + +class StatusSchema(StatusBaseModel): ButtonRetain: int ButtonTopic: str DeviceName: Optional[str] = None @@ -29,7 +40,7 @@ class StatusSchema(TDMBaseModel): Topic: str -class StatusPRMSchema(TDMBaseModel): +class StatusPRMSchema(StatusBaseModel): BCResetTime: Optional[str] = None Baudrate: int BootCount: int @@ -45,7 +56,7 @@ class StatusPRMSchema(TDMBaseModel): Uptime: str -class StatusFWRSchema(TDMBaseModel): +class StatusFWRSchema(StatusBaseModel): Boot: Optional[int] = None BuildDateTime: str CR: Optional[str] = None @@ -56,7 +67,7 @@ class StatusFWRSchema(TDMBaseModel): Version: str -class StatusLOGSchema(TDMBaseModel): +class StatusLOGSchema(StatusBaseModel): LogHost: str LogPort: int MqttLog: Optional[int] = None @@ -69,7 +80,7 @@ class StatusLOGSchema(TDMBaseModel): WebLog: int -class StatusMEMSchema(TDMBaseModel): +class StatusMEMSchema(StatusBaseModel): Drivers: Optional[str] = None Features: List[str] FlashChipId: str @@ -87,7 +98,7 @@ class StatusMEMSchema(TDMBaseModel): StackLowMark: Optional[int] = None -class BaseNETSchema(TDMBaseModel): +class StatusNETBaseSchema(StatusBaseModel): DNSServer1: Optional[str] = None DNSServer2: Optional[str] = None DNSServer: Optional[str] = None @@ -101,14 +112,14 @@ class BaseNETSchema(TDMBaseModel): Subnetmask: str -class StatusNETSchema(BaseNETSchema): - Ethernet: Optional[BaseNETSchema] = None +class StatusNETSchema(StatusNETBaseSchema): + Ethernet: Optional[StatusNETBaseSchema] = None Webserver: int WifiConfig: int WifiPower: Optional[int] = None -class StatusMQTSchema(TDMBaseModel): +class StatusMQTSchema(StatusBaseModel): KEEPALIVE: int MAX_PACKET_SIZE: int MqttClient: str @@ -121,7 +132,7 @@ class StatusMQTSchema(TDMBaseModel): SOCKET_TIMEOUT: Optional[int] = None -class StatusPTHSchema(TDMBaseModel): +class StatusPTHSchema(StatusBaseModel): CurrentHigh: Union[int, List[int]] CurrentLow: Union[int, List[int]] MaxEnergy: Optional[int] = None @@ -136,7 +147,7 @@ class StatusPTHSchema(TDMBaseModel): VoltageLow: Union[int, List[int]] -class StatusSTKSchema(TDMBaseModel): +class StatusSTKSchema(StatusBaseModel): CallChain: List[str] DEPC: str EPC: List[str] @@ -145,12 +156,12 @@ class StatusSTKSchema(TDMBaseModel): Reason: str -class StatusSNSSchema(TDMBaseModel): +class StatusSNSSchema(StatusBaseModel): TempUnit: Optional[str] = None Time: str -class StatusTIMSchema(TDMBaseModel): +class StatusTIMSchema(StatusBaseModel): EndDST: str Local: str StartDST: str @@ -160,7 +171,7 @@ class StatusTIMSchema(TDMBaseModel): UTC: str -class WifiSchema(TDMBaseModel): +class WifiSchema(StatusBaseModel): AP: int BSSId: str Channel: Union[int, List[int]] @@ -172,12 +183,12 @@ class WifiSchema(TDMBaseModel): Signal: Optional[int] = None -class BerrySchema(TDMBaseModel): +class BerrySchema(StatusBaseModel): HeapUsed: int Objects: int -class StateSTSBaseSchema(TDMBaseModel): +class StateSTSBaseSchema(StatusBaseModel): Berry: Optional[BerrySchema] = None Channel: Optional[List[int]] = None Color: Optional[str] = None @@ -220,51 +231,51 @@ class StateBaseSchema(StateSTSBaseSchema): ) -class StatusResponseSchema(TDMBaseModel): +class StatusResponseSchema(StatusBaseModel): Status: StatusSchema -class Status1ResponseSchema(TDMBaseModel): +class Status1ResponseSchema(StatusBaseModel): StatusPRM: StatusPRMSchema -class Status2ResponseSchema(TDMBaseModel): +class Status2ResponseSchema(StatusBaseModel): StatusFWR: StatusFWRSchema -class Status3ResponseSchema(TDMBaseModel): +class Status3ResponseSchema(StatusBaseModel): StatusLOG: StatusLOGSchema -class Status4ResponseSchema(TDMBaseModel): +class Status4ResponseSchema(StatusBaseModel): StatusMEM: StatusMEMSchema -class Status5ResponseSchema(TDMBaseModel): +class Status5ResponseSchema(StatusBaseModel): StatusNET: StatusNETSchema -class Status6ResponseSchema(TDMBaseModel): +class Status6ResponseSchema(StatusBaseModel): StatusMQT: StatusMQTSchema -class Status7ResponseSchema(TDMBaseModel): +class Status7ResponseSchema(StatusBaseModel): StatusTIM: StatusTIMSchema -class Status9ResponseSchema(TDMBaseModel): +class Status9ResponseSchema(StatusBaseModel): StatusPTH: StatusPTHSchema -class Status10ResponseSchema(TDMBaseModel): +class Status10ResponseSchema(StatusBaseModel): StatusSNS: StatusSNSSchema -class Status11ResponseSchema(TDMBaseModel): +class Status11ResponseSchema(StatusBaseModel): StatusSTS: StatusSTSSchema -class Status12ResponseSchema(TDMBaseModel): +class Status12ResponseSchema(StatusBaseModel): StatusSTK: StatusSTKSchema @@ -279,7 +290,7 @@ class Status0ResponseSchema(StatusResponseSchema): StatusSNS: Optional[Status10ResponseSchema] -STATUS_SCHEMA_MAP: [str, TDMBaseModel] = { +STATUS_SCHEMA_MAP: [str, StatusBaseModel] = { 'STATE': StateSchema, 'STATUS': StatusResponseSchema, 'STATUS0': Status0ResponseSchema, diff --git a/tdmgr/util/__init__.py b/tdmgr/util/__init__.py index d0a7119..5f69f0e 100644 --- a/tdmgr/util/__init__.py +++ b/tdmgr/util/__init__.py @@ -144,7 +144,6 @@ def __init__(self, topic: str, fulltopic: str = "%prefix%/%topic%/", devicename: @classmethod def from_discovery(cls, obj: DiscoverySchema): - logging.debug(obj) _ft = obj.ft.replace(obj.t, "%topic%").replace(obj.tp.tele, "%prefix%") device = TasmotaDevice(obj.t, _ft, obj.dn) device.topic_prefixes = obj.tp diff --git a/tdmgr/util/mqtt.py b/tdmgr/util/mqtt.py index 94541fe..115a594 100644 --- a/tdmgr/util/mqtt.py +++ b/tdmgr/util/mqtt.py @@ -11,6 +11,8 @@ import paho.mqtt.client as mqtt from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot +log = logging.getLogger(__name__) + MQTT_PATH_REGEX = "[^+#*>$/]+" # all symbols accepted except forbidden by MQTT topic spec DEFAULT_PREFIXES = ["tele", "stat"] @@ -66,7 +68,7 @@ def dict(self) -> dict: try: return json.loads(self.payload) except JSONDecodeError as e: - logging.critical("MQTT: Cannot parse %s: %s (%s)", self.endpoint, self.payload, e) + log.critical("Cannot parse %s: %s (%s)", self.endpoint, self.payload, e) return {} def match_fulltopic(self, pattern: str) -> Union[Match, None]: @@ -242,7 +244,7 @@ def disconnectFromHost(self): def subscribe(self, path): if self.state == MqttClient.Connected: self.m_client.subscribe(path) - logging.info("MQTT: Subscribed to %s", ", ".join([p[0] for p in path])) + log.info("Subscribed to %s", ", ".join([p[0] for p in path])) @pyqtSlot(str, str) def publish(self, topic, payload=None, qos=0, retain=False): @@ -256,9 +258,7 @@ def on_message(self, mqttc, obj, msg): message = Message(msg.topic, msg.payload, msg.retain) self.messageSignal.emit(message) except UnicodeDecodeError as e: - logging.error( - "MQTT MESSAGE DECODE ERROR: %s (%s=%s)", e, msg.topic, msg.payload.__repr__() - ) + log.error("MESSAGE DECODE ERROR: %s (%s=%s)", e, msg.topic, msg.payload.__repr__()) def on_connect(self, *args): rc = args[3] From 31fe4396707154c254ba013d74dd60115c726646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 01:41:46 +0200 Subject: [PATCH 05/15] fix crash on menu buttons without device selected, fixes #235 (#272) --- tdmgr/GUI/devices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tdmgr/GUI/devices.py b/tdmgr/GUI/devices.py index 3c2dba5..60d0038 100644 --- a/tdmgr/GUI/devices.py +++ b/tdmgr/GUI/devices.py @@ -1,5 +1,6 @@ import os from json import dumps +from typing import Optional from PyQt5.QtCore import QDir, QSortFilterProxyModel, Qt, QUrl, pyqtSignal from PyQt5.QtGui import QColor, QIcon @@ -62,7 +63,7 @@ def __init__(self, parent, *args, **kwargs): self.mqtt = parent.mqtt self.env = parent.env - self.device: TasmotaDevice + self.device: Optional[TasmotaDevice] = None self.idx = None self.nam = QNetworkAccessManager() From f64ee1035d029684f3d99bfa04b47de2d4be937e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 02:49:44 +0200 Subject: [PATCH 06/15] show ethernet address when wifi is disabled (fixes #266) (#273) --- tdmgr/GUI/console.py | 6 +++--- tdmgr/GUI/dialogs/main.py | 5 +---- tdmgr/GUI/dialogs/timers.py | 6 +++--- tdmgr/GUI/rules.py | 2 +- tdmgr/util/__init__.py | 31 +++++++++++++++++++++++++------ tests/conftest.py | 11 ++++++++++- tests/test_device.py | 20 +++++++++++++++++++- tests/test_environment.py | 5 +++-- 8 files changed, 65 insertions(+), 21 deletions(-) diff --git a/tdmgr/GUI/console.py b/tdmgr/GUI/console.py index e05f42f..9e0a818 100644 --- a/tdmgr/GUI/console.py +++ b/tdmgr/GUI/console.py @@ -18,7 +18,7 @@ ) from tdmgr.GUI.widgets import GroupBoxV, HLayout, VLayout, console_font -from tdmgr.util import Message +from tdmgr.util import Message, TasmotaDevice from tdmgr.util.commands import commands @@ -29,7 +29,7 @@ def __init__(self, settings, device, *args, **kwargs): super().__init__() self.setAllowedAreas(Qt.BottomDockWidgetArea) self.setWindowTitle(f"Console [{device.name}]") - self.device = device + self.device: TasmotaDevice = device self.settings = settings @@ -113,7 +113,7 @@ def command_changed(self, text): @pyqtSlot(Message) def consoleAppend(self, msg: Message): - if self.device.matches(msg.topic): + if self.device.message_topic_matches_fulltopic(msg): self.console.appendPlainText( f"[{msg.timestamp.strftime('%X')}] {msg.topic} {msg.payload}" ) diff --git a/tdmgr/GUI/dialogs/main.py b/tdmgr/GUI/dialogs/main.py index 312d524..5f56ec8 100644 --- a/tdmgr/GUI/dialogs/main.py +++ b/tdmgr/GUI/dialogs/main.py @@ -363,7 +363,7 @@ def mqtt_message(self, msg: Message): # lwt = self.env.lwts.pop(f"{obj.ft}/LWT", obj.ofln) # device.update_property("LWT", lwt) - if device := self.env.find_device(msg.topic): + if device := self.env.find_device(msg): if msg.is_lwt: log.debug("MQTT: LWT message for %s: %s", device.p["Topic"], msg.payload) device.update_property("LWT", msg.payload) @@ -373,9 +373,6 @@ def mqtt_message(self, msg: Message): self.initial_query(device, True) else: - _prefix = re.match(device.fulltopic_regex, msg.topic) - if _prefix: - msg.prefix = _prefix.groupdict()["prefix"] # forward the message for processing device.update_property("LWT", device.p["Online"]) device.process_message(msg) diff --git a/tdmgr/GUI/dialogs/timers.py b/tdmgr/GUI/dialogs/timers.py index 3ddb376..64f1404 100644 --- a/tdmgr/GUI/dialogs/timers.py +++ b/tdmgr/GUI/dialogs/timers.py @@ -14,7 +14,7 @@ ) from tdmgr.GUI.widgets import GroupBoxH, GroupBoxV, HLayout, VLayout -from tdmgr.util import Message +from tdmgr.util import Message, TasmotaDevice class TimersDialog(QDialog): @@ -22,7 +22,7 @@ class TimersDialog(QDialog): def __init__(self, device, *args, **kwargs): super(TimersDialog, self).__init__(*args, **kwargs) - self.device = device + self.device: TasmotaDevice = device self.timers = {} self.armKey = "Arm" self.setWindowTitle(f"Timers [{self.device.name}]") @@ -257,7 +257,7 @@ def parseMessage(self, msg: Message): "Days":"0000000","Repeat":0, "Action":0}, .... """ - if self.device.matches(msg.topic): + if self.device.message_topic_matches_fulltopic(msg): if msg.is_result or msg.endpoint == "TIMERS": payload = msg.dict() all = list(payload) diff --git a/tdmgr/GUI/rules.py b/tdmgr/GUI/rules.py index 5355fa1..a34c8a5 100644 --- a/tdmgr/GUI/rules.py +++ b/tdmgr/GUI/rules.py @@ -270,7 +270,7 @@ def unfold_rule(self, rules: str): @pyqtSlot(Message) def parseMessage(self, msg: Message): - if self.device.matches(msg.topic): + if self.device.message_topic_matches_fulltopic(msg): payload = msg.dict() if payload: if msg.is_result and msg.first_key == "T1" or msg.endpoint == "RULETIMER": diff --git a/tdmgr/util/__init__.py b/tdmgr/util/__init__.py index 5f69f0e..f7612c5 100644 --- a/tdmgr/util/__init__.py +++ b/tdmgr/util/__init__.py @@ -84,13 +84,13 @@ class DiscoveryMode(int, Enum): class TasmotaEnvironment: def __init__(self): - self.devices = [] + self.devices: list[TasmotaDevice] = [] self.lwts = dict() self.retained = set() - def find_device(self, topic) -> 'TasmotaDevice': + def find_device(self, msg: Message) -> 'TasmotaDevice': for d in self.devices: - if d.matches(topic): + if d.message_topic_matches_fulltopic(msg): return d @@ -142,6 +142,14 @@ def __init__(self, topic: str, fulltopic: str = "%prefix%/%topic%/", devicename: r"GPIOs\d?": self._process_gpios, } + @property + def topic(self) -> str: + return self.p["Topic"] + + @property + def fulltopic(self) -> str: + return self.p["FullTopic"] + @classmethod def from_discovery(cls, obj: DiscoverySchema): _ft = obj.ft.replace(obj.t, "%topic%").replace(obj.tp.tele, "%prefix%") @@ -184,6 +192,13 @@ def tele_topic(self, endpoint=""): def is_default(self): return self.p["FullTopic"] in DEFAULT_PATTERNS + def message_topic_matches_fulltopic(self, msg: Message) -> bool: + if _prefix := re.match(self.fulltopic_regex, msg.topic): + if not msg.prefix: + msg.prefix = _prefix.groupdict()["prefix"] + return True + return False + @property def subscribable_topics(self): topics = [] @@ -218,9 +233,6 @@ def fulltopic_regex(self) -> str: ) return f'^{_ft_pattern}' - def matches(self, topic: str) -> bool: - return re.match(self.fulltopic_regex, topic) is not None - def _process_module(self, msg: Message): print(msg.payload) @@ -352,6 +364,13 @@ def color(self): color.update({15: self.setoption(15), 17: self.setoption(17), 68: self.setoption(68)}) return color + @property + def ip_address(self) -> str: + for ip in [self.p.get("IPAddress"), self.p.get("Ethernet", {}).get("IPAddress")]: + if ip != "0.0.0.0": + return ip + return "0.0.0.0" + def setoption(self, o): if 0 <= o < 32: reg = 0 diff --git a/tests/conftest.py b/tests/conftest.py index 9e42777..3ba0720 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,12 +1,21 @@ +import os + import pytest from tdmgr.util import Message, TasmotaDevice +def get_payload(version: str, filename: str) -> bytes: + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'status_parsing', 'jsonfiles') + fname = os.path.join(path, version, filename) + with open(fname, 'rb') as f: + return f.read() + + @pytest.fixture def device(request): topic = "device" - if request.param: + if hasattr(request, "param"): topic = request.param yield TasmotaDevice(topic) diff --git a/tests/test_device.py b/tests/test_device.py index 18cedce..0f4bd1f 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -1,6 +1,7 @@ import pytest from tdmgr.util import Message, TasmotaDevice +from tests.conftest import get_payload @pytest.mark.parametrize( @@ -14,7 +15,8 @@ ) def test_matches(fulltopic, topic, expected): device = TasmotaDevice("some_topic", fulltopic) - assert device.matches(topic) is expected + msg = Message(topic) + assert device.message_topic_matches_fulltopic(msg) is expected @pytest.mark.parametrize("topic", ["stat/device/RESULT", "stat/device/TEMPLATE"]) @@ -27,3 +29,19 @@ def test_process_template(topic): assert message.first_key == "NAME" assert device.p.get("Template") == "NodeMCU" + + +@pytest.mark.parametrize("version", ("14.2.0.4",)) +@pytest.mark.parametrize( + "filename, expected", + [ + ("STATUS5.json", "192.168.0.1"), + ("STATUS5.1.json", "192.168.7.187"), + ], +) +def test_ip_address(device, version, filename, expected): + payload = get_payload(version, filename) + msg = Message("stat/topic/STATUS5", payload, prefix="stat") + device.process_message(msg) + + assert device.ip_address == expected diff --git a/tests/test_environment.py b/tests/test_environment.py index 30906c8..a50416a 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -1,6 +1,6 @@ import pytest -from tdmgr.util import TasmotaDevice, TasmotaEnvironment +from tdmgr.util import Message, TasmotaDevice, TasmotaEnvironment @pytest.mark.parametrize( @@ -19,6 +19,7 @@ def test_find_device(full_topic, test_topic, expected): dev = TasmotaDevice(topic='device', fulltopic=full_topic) env.devices.append(dev) - device = env.find_device(test_topic) + msg = Message(test_topic) + device = env.find_device(msg) assert (device == dev) is expected From a9bffe9c626768a7e7b763d89202286427d7f65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 02:55:32 +0200 Subject: [PATCH 07/15] use wifi or ethernet ip address for webui (#274) --- tdmgr/util/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tdmgr/util/__init__.py b/tdmgr/util/__init__.py index f7612c5..b0c6eb6 100644 --- a/tdmgr/util/__init__.py +++ b/tdmgr/util/__init__.py @@ -412,9 +412,9 @@ def is_online(self): return self.p.get("LWT", self.p["Offline"]) == self.p["Online"] @property - def url(self): - if url := self.p.get("IPAddress", None): - return f"http://{url}" + def url(self) -> Optional[str]: + if self.ip_address != "0.0.0.0": + return f"http://{self.ip_address}" def version(self, short=True): if version := self.p.get("Version"): From bb8c47c3d9b21459aa5046cdead8f17368044b8f Mon Sep 17 00:00:00 2001 From: jziolkowski Date: Sun, 15 Sep 2024 03:01:03 +0200 Subject: [PATCH 08/15] update readme and changelog --- CHANGELOG.md | 10 ++++++++-- README.md | 7 +++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 838c3c6..3e2024f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [development] +## Changed +- ethernet-enabled devices now show eth ip address when wifi is disabled (#266) + +## Fixed +- clicking main menu buttons doesn't crash anymore (#235) + ## [2024.9.2] - 2024-09-14 ## Fixed - missing pydantic in pyproject.toml @@ -8,13 +15,12 @@ - TDM now stores tdm.cfg in locations suggested by the OS ## Added -- support for MQTT wildcards in autodiscovery patterns +- support for MQTT wildcards in autodiscovery patterns (#254) - misc UI changes ## Fixed - many bugs, crashes, small annoyances - ## [0.2.6] - 2019-12-24 ## Changed - support for 16 var/mem in rules editor diff --git a/README.md b/README.md index 061bbfe..0595799 100644 --- a/README.md +++ b/README.md @@ -21,20 +21,19 @@ While I'm not in any way abandoning this project, I don't have as much time as I - [autodiscovery](https://github.com/jziolkowski/tdm/wiki/Autodiscovery) of Tasmota devices (even if they use custom FullTopics) - module, GPIO and template configuration - rules editor with Var/Mem/Ruletimer monitor - - easy to read detachable telemetry viewers (working in active and passive mode) + - easy to read detachable telemetry viewers (working in active and passive mode) - relay, color and PWM control - user-friendly configuration of buttons, switches and relays, including their related SetOptions - timers editor - clear retained relay and LWT topics - - detachable device consoles with command completion and intuitive history + - detachable device consoles with command completion and intuitive history - selectable views to see the most vital device parameters at a glance - BSSID aliasing for larger deployments - support for current and legacy Timers payloads (thanks @GrahamM) # Planned functions - + - PWM/NTP/Topics configuration dialogs and a few others - - config export for OpenHAB and HomeAssistant - dynamic and manual grouping of devices: by group topic, module, firmware revision, and more - group actions: reset/restart/control power/upgrade - quick settings for common use cases From 4bee940e40279c539ee0c01ecbbff46732a83854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 17:00:13 +0200 Subject: [PATCH 09/15] add status json files (#275) --- tdmgr/schemas/status.py | 1 + tests/status_parsing/__init__.py | 0 .../jsonfiles/12.1.1.5/STATUS.json | 37 +++++++++++++ .../jsonfiles/12.1.1.5/STATUS1.json | 17 ++++++ .../jsonfiles/12.1.1.5/STATUS10.json | 5 ++ .../jsonfiles/12.1.1.5/STATUS11.json | 26 +++++++++ .../jsonfiles/12.1.1.5/STATUS2.json | 12 ++++ .../jsonfiles/12.1.1.5/STATUS3.json | 24 ++++++++ .../jsonfiles/12.1.1.5/STATUS4.json | 26 +++++++++ .../jsonfiles/12.1.1.5/STATUS5.json | 15 +++++ .../jsonfiles/12.1.1.5/STATUS6.json | 13 +++++ .../jsonfiles/12.1.1.5/STATUS7.json | 11 ++++ .../jsonfiles/12.2.0.2/STATUS.json | 24 ++++---- .../jsonfiles/12.2.0.2/STATUS1.json | 18 +++--- .../jsonfiles/12.2.0.2/STATUS2.json | 10 ++-- .../jsonfiles/12.4.0/STATUS.json | 55 +++++++++++++++++++ .../jsonfiles/12.4.0/STATUS1.json | 17 ++++++ .../jsonfiles/12.4.0/STATUS10.json | 21 +++++++ .../jsonfiles/12.4.0/STATUS11.json | 24 ++++++++ .../jsonfiles/12.4.0/STATUS2.json | 12 ++++ .../jsonfiles/12.4.0/STATUS3.json | 24 ++++++++ .../jsonfiles/12.4.0/STATUS4.json | 26 +++++++++ .../jsonfiles/12.4.0/STATUS5.json | 15 +++++ .../jsonfiles/12.4.0/STATUS6.json | 13 +++++ .../jsonfiles/12.4.0/STATUS7.json | 11 ++++ .../jsonfiles/12.4.0/STATUS9.json | 15 +++++ .../jsonfiles/13.2.0.2/STATUS.json | 55 +++++++++++++++++++ .../jsonfiles/13.2.0.2/STATUS1.json | 17 ++++++ .../jsonfiles/13.2.0.2/STATUS10.json | 6 ++ .../jsonfiles/13.2.0.2/STATUS11.json | 24 ++++++++ .../jsonfiles/13.2.0.2/STATUS2.json | 12 ++++ .../jsonfiles/13.2.0.2/STATUS3.json | 24 ++++++++ .../jsonfiles/13.2.0.2/STATUS4.json | 28 ++++++++++ .../jsonfiles/13.2.0.2/STATUS5.json | 15 +++++ .../jsonfiles/13.2.0.2/STATUS6.json | 13 +++++ .../jsonfiles/13.2.0.2/STATUS7.json | 11 ++++ .../jsonfiles/14.2.0.4/STATUS5.1.json | 28 +++++----- .../jsonfiles/14.2.0.4/STATUS5.json | 28 +++++----- .../jsonfiles/6.3.0.12/STATE.json | 8 +-- .../jsonfiles/6.3.0.12/STATUS.json | 16 +++--- .../jsonfiles/6.3.0.12/STATUS1.json | 12 ++-- .../jsonfiles/6.3.0.12/STATUS10.json | 10 ++-- .../jsonfiles/6.3.0.12/STATUS11.json | 8 +-- .../jsonfiles/6.3.0.12/STATUS2.json | 8 +-- .../jsonfiles/6.3.0.12/STATUS3.json | 12 ++-- .../jsonfiles/6.3.0.12/STATUS4.json | 18 +++--- .../jsonfiles/6.3.0.12/STATUS5.json | 8 +-- .../jsonfiles/6.3.0.12/STATUS6.json | 12 ++-- .../jsonfiles/6.3.0.12/STATUS7.json | 10 ++-- .../jsonfiles/7.0.0.4/STATE.json | 16 +++--- .../jsonfiles/8.1.0.3/STATUS.json | 33 +++++++++++ .../jsonfiles/8.1.0.3/STATUS1.json | 16 ++++++ .../jsonfiles/8.1.0.3/STATUS10.json | 8 +++ .../jsonfiles/8.1.0.3/STATUS11.json | 25 +++++++++ .../jsonfiles/8.1.0.3/STATUS2.json | 11 ++++ .../jsonfiles/8.1.0.3/STATUS3.json | 22 ++++++++ .../jsonfiles/8.1.0.3/STATUS4.json | 21 +++++++ .../jsonfiles/8.1.0.3/STATUS5.json | 13 +++++ .../jsonfiles/8.1.0.3/STATUS6.json | 12 ++++ .../jsonfiles/8.1.0.3/STATUS7.json | 11 ++++ .../jsonfiles/8.5.1/STATUS.1.json | 33 +++++++++++ .../jsonfiles/8.5.1/STATUS.2.json | 32 +++++++++++ .../jsonfiles/8.5.1/STATUS.json | 32 +++++++++++ .../jsonfiles/8.5.1/STATUS1.1.json | 17 ++++++ .../jsonfiles/8.5.1/STATUS1.2.json | 17 ++++++ .../jsonfiles/8.5.1/STATUS1.json | 17 ++++++ .../jsonfiles/8.5.1/STATUS10.1.json | 7 +++ .../jsonfiles/8.5.1/STATUS10.2.json | 5 ++ .../jsonfiles/8.5.1/STATUS10.json | 5 ++ .../jsonfiles/8.5.1/STATUS11.1.json | 25 +++++++++ .../jsonfiles/8.5.1/STATUS11.2.json | 36 ++++++++++++ .../jsonfiles/8.5.1/STATUS11.json | 24 ++++++++ .../jsonfiles/8.5.1/STATUS2.1.json | 12 ++++ .../jsonfiles/8.5.1/STATUS2.2.json | 12 ++++ .../jsonfiles/8.5.1/STATUS2.json | 12 ++++ .../jsonfiles/8.5.1/STATUS3.1.json | 23 ++++++++ .../jsonfiles/8.5.1/STATUS3.2.json | 23 ++++++++ .../jsonfiles/8.5.1/STATUS3.json | 23 ++++++++ .../jsonfiles/8.5.1/STATUS4.1.json | 24 ++++++++ .../jsonfiles/8.5.1/STATUS4.2.json | 24 ++++++++ .../jsonfiles/8.5.1/STATUS4.json | 24 ++++++++ .../jsonfiles/8.5.1/STATUS5.1.json | 13 +++++ .../jsonfiles/8.5.1/STATUS5.2.json | 13 +++++ .../jsonfiles/8.5.1/STATUS5.json | 13 +++++ .../jsonfiles/8.5.1/STATUS6.1.json | 12 ++++ .../jsonfiles/8.5.1/STATUS6.2.json | 12 ++++ .../jsonfiles/8.5.1/STATUS6.json | 12 ++++ .../jsonfiles/8.5.1/STATUS7.1.json | 11 ++++ .../jsonfiles/8.5.1/STATUS7.2.json | 11 ++++ .../jsonfiles/8.5.1/STATUS7.json | 11 ++++ .../jsonfiles/9.1.0/STATUS.json | 32 +++++++++++ .../jsonfiles/9.1.0/STATUS1.json | 17 ++++++ .../jsonfiles/9.1.0/STATUS10.json | 5 ++ .../jsonfiles/9.1.0/STATUS11.json | 39 +++++++++++++ .../jsonfiles/9.1.0/STATUS2.json | 12 ++++ .../jsonfiles/9.1.0/STATUS3.json | 23 ++++++++ .../jsonfiles/9.1.0/STATUS4.json | 24 ++++++++ .../jsonfiles/9.1.0/STATUS5.json | 13 +++++ .../jsonfiles/9.1.0/STATUS6.json | 12 ++++ .../jsonfiles/9.1.0/STATUS7.json | 11 ++++ .../jsonfiles/9.5.0.4/STATUS.json | 34 ++++++++++++ .../jsonfiles/9.5.0.4/STATUS1.json | 17 ++++++ .../jsonfiles/9.5.0.4/STATUS11.json | 23 ++++++++ .../jsonfiles/9.5.0.4/STATUS2.json | 12 ++++ .../jsonfiles/9.5.0.4/STATUS3.json | 23 ++++++++ .../jsonfiles/9.5.0.4/STATUS4.json | 25 +++++++++ .../jsonfiles/9.5.0.4/STATUS5.json | 14 +++++ .../jsonfiles/9.5.0.4/STATUS6.json | 13 +++++ .../jsonfiles/9.5.0.4/STATUS7.json | 11 ++++ 109 files changed, 1815 insertions(+), 123 deletions(-) delete mode 100644 tests/status_parsing/__init__.py create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS10.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/12.1.1.5/STATUS7.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS10.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS7.json create mode 100644 tests/status_parsing/jsonfiles/12.4.0/STATUS9.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS10.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/13.2.0.2/STATUS7.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS10.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/8.1.0.3/STATUS7.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS1.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS1.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS10.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS10.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS10.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS11.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS11.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS2.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS2.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS3.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS3.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS4.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS4.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS5.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS5.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS6.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS6.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS7.1.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS7.2.json create mode 100644 tests/status_parsing/jsonfiles/8.5.1/STATUS7.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS10.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/9.1.0/STATUS7.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS1.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS11.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS2.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS3.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS4.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS5.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS6.json create mode 100644 tests/status_parsing/jsonfiles/9.5.0.4/STATUS7.json diff --git a/tdmgr/schemas/status.py b/tdmgr/schemas/status.py index 741dbe6..1f4d565 100644 --- a/tdmgr/schemas/status.py +++ b/tdmgr/schemas/status.py @@ -192,6 +192,7 @@ class StateSTSBaseSchema(StatusBaseModel): Berry: Optional[BerrySchema] = None Channel: Optional[List[int]] = None Color: Optional[str] = None + CT: Optional[int] = None Fade: Optional[str] = None HSBColor: Optional[str] = None Heap: Optional[int] = None diff --git a/tests/status_parsing/__init__.py b/tests/status_parsing/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS.json new file mode 100644 index 0000000..b87b3a6 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS.json @@ -0,0 +1,37 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "PorchTasmota", + "FriendlyName": [ + "PorchTasmota", + "Tasmota2", + "Tasmota3" + ], + "InfoRetain": 0, + "LedMask": "FFFF", + "LedState": 1, + "Module": 0, + "Power": 2, + "PowerOnState": 3, + "PowerRetain": 1, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "StateRetain": 0, + "StatusRetain": 0, + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "porch" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS1.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS1.json new file mode 100644 index 0000000..180a305 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2021-10-02T20:04:51", + "Baudrate": 115200, + "BootCount": 728, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/tasmota.bin", + "RestartReason": "Software/System restart", + "SaveAddress": "F9000", + "SaveCount": 12664, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-07-24T15:06:41", + "Uptime": "51T01:54:34" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS10.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS10.json new file mode 100644 index 0000000..6af2d59 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS10.json @@ -0,0 +1,5 @@ +{ + "StatusSNS": { + "Time": "2024-09-13T19:01:15" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS11.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS11.json new file mode 100644 index 0000000..07b3349 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS11.json @@ -0,0 +1,26 @@ +{ + "StatusSTS": { + "Heap": 23, + "LoadAvg": 19, + "MqttCount": 3, + "POWER1": "OFF", + "POWER2": "ON", + "POWER3": "OFF", + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-13T19:01:15", + "Uptime": "51T01:54:34", + "UptimeSec": 4413274, + "Wifi": { + "AP": 1, + "BSSId": "28:D1:27:DB:35:26", + "Channel": 1, + "Downtime": "0T00:00:08", + "LinkCount": 2, + "Mode": "11n", + "RSSI": 52, + "SSId": "WifiNet1", + "Signal": -74 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS2.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS2.json new file mode 100644 index 0000000..9b4a7dd --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2022-10-12T15:20:06", + "CR": "442/699", + "Core": "2_7_4_9", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "12.1.1.5(tasmota)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS3.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS3.json new file mode 100644 index 0000000..ec6632f --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS3.json @@ -0,0 +1,24 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "WifiNet1", + "WifiNet1" + ], + "SerialLog": 2, + "SetOption": [ + "00008029", + "2805C80001000600003C5A0A002800000000", + "000000A1", + "00006000", + "00004000", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS4.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS4.json new file mode 100644 index 0000000..6562c9b --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS4.json @@ -0,0 +1,26 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45,62", + "Features": [ + "00000809", + "8F9AC787", + "04368001", + "000000CF", + "010013C0", + "C000F981", + "00004004", + "00001000", + "54000020", + "00000000" + ], + "FlashChipId": "1540C8", + "FlashFrequency": 40, + "FlashMode": "DOUT", + "FlashSize": 2048, + "Free": 376, + "Heap": 21, + "ProgramFlashSize": 1024, + "ProgramSize": 626, + "Sensors": "1,2,3,4,5,6" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS5.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS5.json new file mode 100644 index 0000000..61a4310 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS5.json @@ -0,0 +1,15 @@ +{ + "StatusNET": { + "DNSServer1": "192.168.1.142", + "DNSServer2": "0.0.0.0", + "Gateway": "192.168.1.142", + "HTTP_API": 1, + "Hostname": "porch-1076", + "IPAddress": "192.168.1.187", + "Mac": "2C:F4:32:3F:44:34", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 2, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS6.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS6.json new file mode 100644 index 0000000..7407145 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS6.json @@ -0,0 +1,13 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_3F4434", + "MqttClientMask": "DVES_%06X", + "MqttCount": 3, + "MqttHost": "192.168.1.230", + "MqttPort": 1883, + "MqttUser": "DVES_USER", + "SOCKET_TIMEOUT": 4 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.1.1.5/STATUS7.json b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS7.json new file mode 100644 index 0000000..8646f41 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.1.1.5/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T02:00:00", + "Local": "2024-09-13T19:01:15", + "StartDST": "2024-03-24T02:00:00", + "Sunrise": "05:33", + "Sunset": "19:18", + "Timezone": 99, + "UTC": "2024-09-13T17:01:15" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json index 4280368..f42e462 100644 --- a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json +++ b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json @@ -1,19 +1,23 @@ { "Status": { - "Module": 6, + "ButtonRetain": 0, + "ButtonTopic": "0", "DeviceName": "Tasmota", "FriendlyName": [ "Tasmota" ], - "Topic": "tasmota_1A704F", - "ButtonTopic": "0", + "InfoRetain": 0, + "LedMask": "FFFF", + "LedState": 1, + "Module": 6, "Power": 1, "PowerOnState": 3, - "LedState": 1, - "LedMask": "FFFF", + "PowerRetain": 0, "SaveData": 1, "SaveState": 1, - "SwitchTopic": "0", + "SensorRetain": 0, + "StateRetain": 0, + "StatusRetain": 0, "SwitchMode": [ 0, 0, @@ -24,12 +28,8 @@ 0, 0 ], - "ButtonRetain": 0, "SwitchRetain": 0, - "SensorRetain": 0, - "PowerRetain": 0, - "InfoRetain": 0, - "StateRetain": 0, - "StatusRetain": 0 + "SwitchTopic": "0", + "Topic": "tasmota_1A704F" } } \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json index 062e9ee..c55f514 100644 --- a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json +++ b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json @@ -1,17 +1,17 @@ { "StatusPRM": { + "BCResetTime": "2022-11-05T18:47:52", "Baudrate": 115200, - "SerialConfig": "8N1", + "BootCount": 12, + "CfgHolder": 4617, "GroupTopic": "tasmotas", "OtaUrl": "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz", "RestartReason": "Power On", - "Uptime": "94T04:19:39", - "StartupUTC": "2023-10-09T15:15:19", - "Sleep": 50, - "CfgHolder": 4617, - "BootCount": 12, - "BCResetTime": "2022-11-05T18:47:52", + "SaveAddress": "FB000", "SaveCount": 896, - "SaveAddress": "FB000" + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2023-10-09T15:15:19", + "Uptime": "94T04:19:39" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json index 20c20d8..6da3069 100644 --- a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json +++ b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json @@ -1,12 +1,12 @@ { "StatusFWR": { - "Version": "12.2.0.2(tasmota)", - "BuildDateTime": "2022-11-03T16:54:39", "Boot": 31, + "BuildDateTime": "2022-11-03T16:54:39", + "CR": "369/699", "Core": "2_7_4_9", - "SDK": "2.2.2-dev(38a443e)", "CpuFrequency": 80, "Hardware": "ESP8266EX", - "CR": "369/699" + "SDK": "2.2.2-dev(38a443e)", + "Version": "12.2.0.2(tasmota)" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS.json new file mode 100644 index 0000000..675fd28 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS.json @@ -0,0 +1,55 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "TasmotaOutlet5", + "FriendlyName": [ + "TasmotaOutlet5" + ], + "InfoRetain": 0, + "LedMask": "FFFF", + "LedState": 1, + "Module": 0, + "Power": 0, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "StateRetain": 0, + "StatusRetain": 0, + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "tasmota_outlet5" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS1.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS1.json new file mode 100644 index 0000000..5d4ea10 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2023-12-28T19:08:44", + "Baudrate": 4800, + "BootCount": 13, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release/tasmota-4M.bin.gz", + "RestartReason": "Power On", + "SaveAddress": "FB000", + "SaveCount": 559, + "SerialConfig": "8E1", + "Sleep": 50, + "StartupUTC": "2024-05-20T08:44:34", + "Uptime": "116T07:42:22" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS10.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS10.json new file mode 100644 index 0000000..3214fcf --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS10.json @@ -0,0 +1,21 @@ +{ + "StatusSNS": { + "ANALOG": { + "Temperature": 25.3 + }, + "ENERGY": { + "ApparentPower": 0, + "Current": 0.0, + "Factor": 0.0, + "Power": 0, + "ReactivePower": 0, + "Today": 0.0, + "Total": 141.051, + "TotalStartTime": "2023-12-28T19:08:44", + "Voltage": 0, + "Yesterday": 0.0 + }, + "TempUnit": "C", + "Time": "2024-09-13T17:26:56" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS11.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS11.json new file mode 100644 index 0000000..8d20da9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS11.json @@ -0,0 +1,24 @@ +{ + "StatusSTS": { + "Heap": 18, + "LoadAvg": 19, + "MqttCount": 8, + "POWER": "OFF", + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-13T17:26:56", + "Uptime": "116T07:42:22", + "UptimeSec": 10050142, + "Wifi": { + "AP": 1, + "BSSId": "5C:E9:31:18:49:D4", + "Channel": 7, + "Downtime": "73T07:13:32", + "LinkCount": 5, + "Mode": "11n", + "RSSI": 52, + "SSId": "WifiNet", + "Signal": -74 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS2.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS2.json new file mode 100644 index 0000000..80dc52b --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2023-05-12T14:52:14", + "CR": "414/699", + "Core": "2_7_4_9", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "12.4.0(tasmota)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS3.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS3.json new file mode 100644 index 0000000..0bc49e0 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS3.json @@ -0,0 +1,24 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "WifiNet", + "" + ], + "SerialLog": 0, + "SetOption": [ + "00008009", + "2805C80001000680003C5A0A192800000000", + "00000080", + "00006000", + "00004000", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS4.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS4.json new file mode 100644 index 0000000..9991a30 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS4.json @@ -0,0 +1,26 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,38,45,50,62,126", + "Features": [ + "00000809", + "8F9AC78F", + "04368001", + "000000CF", + "010013C0", + "C000F981", + "00004084", + "00201000", + "54000020", + "00000080" + ], + "FlashChipId": "164068", + "FlashFrequency": 40, + "FlashMode": "DOUT", + "FlashSize": 4096, + "Free": 1340, + "Heap": 18, + "ProgramFlashSize": 4096, + "ProgramSize": 705, + "Sensors": "1,2,3,4,5,6" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS5.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS5.json new file mode 100644 index 0000000..7bd62ff --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS5.json @@ -0,0 +1,15 @@ +{ + "StatusNET": { + "DNSServer1": "192.168.1.142", + "DNSServer2": "0.0.0.0", + "Gateway": "192.168.1.142", + "HTTP_API": 1, + "Hostname": "tasmota-outlet5-4287", + "IPAddress": "192.168.1.213", + "Mac": "C8:C9:A3:14:D0:BF", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS6.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS6.json new file mode 100644 index 0000000..c214403 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS6.json @@ -0,0 +1,13 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_14D0BF", + "MqttClientMask": "DVES_%06X", + "MqttCount": 8, + "MqttHost": "192.168.1.230", + "MqttPort": 1883, + "MqttUser": "DVES_USER", + "SOCKET_TIMEOUT": 4 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS7.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS7.json new file mode 100644 index 0000000..64ef954 --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-13T17:26:56", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "06:24", + "Sunset": "19:06", + "Timezone": "+01:00", + "UTC": "2024-09-13T16:26:56" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.4.0/STATUS9.json b/tests/status_parsing/jsonfiles/12.4.0/STATUS9.json new file mode 100644 index 0000000..8f6b5dd --- /dev/null +++ b/tests/status_parsing/jsonfiles/12.4.0/STATUS9.json @@ -0,0 +1,15 @@ +{ + "StatusPTH": { + "CurrentHigh": 0, + "CurrentLow": 0, + "PowerDelta": [ + 0, + 0, + 0 + ], + "PowerHigh": 0, + "PowerLow": 0, + "VoltageHigh": 0, + "VoltageLow": 0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS.json new file mode 100644 index 0000000..fc5619f --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS.json @@ -0,0 +1,55 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "Wyj\u015bcie \u015bwiat\u0142o", + "FriendlyName": [ + "Tasmota" + ], + "InfoRetain": 0, + "LedMask": "FFFF", + "LedState": 1, + "Module": 0, + "Power": 0, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "StateRetain": 0, + "StatusRetain": 0, + "SwitchMode": [ + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "wyjscie_swiatlo" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS1.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS1.json new file mode 100644 index 0000000..11320ca --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2023-11-16T20:53:46", + "Baudrate": 115200, + "BootCount": 13, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz", + "RestartReason": "External System", + "SaveAddress": "F5000", + "SaveCount": 3191, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-03-15T11:40:13", + "Uptime": "184T01:12:45" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS10.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS10.json new file mode 100644 index 0000000..6be1b61 --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS10.json @@ -0,0 +1,6 @@ +{ + "StatusSNS": { + "Switch1": "ON", + "Time": "2024-09-15T13:52:58" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS11.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS11.json new file mode 100644 index 0000000..9f802b6 --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS11.json @@ -0,0 +1,24 @@ +{ + "StatusSTS": { + "Heap": 22, + "LoadAvg": 19, + "MqttCount": 23, + "POWER": "OFF", + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-15T13:52:58", + "Uptime": "184T01:12:45", + "UptimeSec": 15901965, + "Wifi": { + "AP": 1, + "BSSId": "E6:8D:8C:AE:84:A4", + "Channel": 6, + "Downtime": "0T00:22:16", + "LinkCount": 7, + "Mode": "11n", + "RSSI": 92, + "SSId": "NznCoDk3McKgMzgy", + "Signal": -54 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS2.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS2.json new file mode 100644 index 0000000..e9ea2fc --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2023-11-16T09:28:14", + "CR": "382/699", + "Core": "2_7_4_9", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "13.2.0.2(tasmota)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS3.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS3.json new file mode 100644 index 0000000..1e5f5b7 --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS3.json @@ -0,0 +1,24 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "NznCoDk3McKgMzgy", + "" + ], + "SerialLog": 2, + "SetOption": [ + "00008009", + "0F05C80001000600003C5A0A192800000000", + "02000080", + "00006000", + "00004000", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS4.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS4.json new file mode 100644 index 0000000..7adc785 --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS4.json @@ -0,0 +1,28 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45,62,68", + "Features": [ + "0809", + "8F9AC787", + "04368001", + "000000CF", + "010013C0", + "C000F981", + "00004004", + "00001000", + "54000020", + "00000080", + "00000000" + ], + "FlashChipId": "1540C8", + "FlashFrequency": 40, + "FlashMode": "DOUT", + "FlashSize": 2048, + "Free": 368, + "Heap": 22, + "I2CDriver": "7", + "ProgramFlashSize": 1024, + "ProgramSize": 635, + "Sensors": "1,2,3,4,5,6" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS5.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS5.json new file mode 100644 index 0000000..4ce0fd9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS5.json @@ -0,0 +1,15 @@ +{ + "StatusNET": { + "DNSServer1": "10.2.30.254", + "DNSServer2": "0.0.0.0", + "Gateway": "10.2.30.254", + "HTTP_API": 1, + "Hostname": "wyjscie-swiatlo-2927", + "IPAddress": "10.2.30.60", + "Mac": "EC:FA:BC:4B:8B:6F", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS6.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS6.json new file mode 100644 index 0000000..c3a987c --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS6.json @@ -0,0 +1,13 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_4B8B6F", + "MqttClientMask": "DVES_%06X", + "MqttCount": 23, + "MqttHost": "mqtt.iot", + "MqttPort": 1883, + "MqttUser": "DVES_USER", + "SOCKET_TIMEOUT": 4 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/13.2.0.2/STATUS7.json b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS7.json new file mode 100644 index 0000000..c83841e --- /dev/null +++ b/tests/status_parsing/jsonfiles/13.2.0.2/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-15T13:52:58", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "06:27", + "Sunset": "19:02", + "Timezone": "+01:00", + "UTC": "2024-09-15T12:52:58" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json index 3a82b2a..bb765d1 100644 --- a/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json +++ b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json @@ -1,27 +1,27 @@ { "StatusNET": { - "Hostname": "tasmota-68FF94-8084", - "IPAddress": "0.0.0.0", - "Gateway": "192.168.7.1", - "Subnetmask": "255.255.255.0", "DNSServer1": "192.168.7.1", "DNSServer2": "0.0.0.0", - "Mac": "34:98:7A:68:FF:94", - "IP6Global": "", - "IP6Local": "", "Ethernet": { - "Hostname": "tasmota-68FF94-8084eth", - "IPAddress": "192.168.7.187", - "Gateway": "192.168.7.1", - "Subnetmask": "255.255.255.0", "DNSServer1": "192.168.7.1", "DNSServer2": "0.0.0.0", - "Mac": "34:98:7A:68:FF:97", + "Gateway": "192.168.7.1", + "Hostname": "tasmota-68FF94-8084eth", "IP6Global": "", - "IP6Local": "fe80::3698:7aff:fe68:ff97%en1" + "IP6Local": "fe80::3698:7aff:fe68:ff97%en1", + "IPAddress": "192.168.7.187", + "Mac": "34:98:7A:68:FF:97", + "Subnetmask": "255.255.255.0" }, - "Webserver": 2, + "Gateway": "192.168.7.1", "HTTP_API": 1, + "Hostname": "tasmota-68FF94-8084", + "IP6Global": "", + "IP6Local": "", + "IPAddress": "0.0.0.0", + "Mac": "34:98:7A:68:FF:94", + "Subnetmask": "255.255.255.0", + "Webserver": 2, "WifiConfig": 0, "WifiPower": 17.0 } diff --git a/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json index 73c6a4e..fd6b062 100644 --- a/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json +++ b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json @@ -1,27 +1,27 @@ { "StatusNET": { - "Hostname": "xxxxxxxx", - "IPAddress": "192.168.0.1", - "Gateway": "192.168.0.99", - "Subnetmask": "255.255.254.0", "DNSServer1": "192.168.0.99", "DNSServer2": "0.0.0.0", - "Mac": "xx:xx:xx:xx:xx:xx", - "IP6Global": "xxxx:::::::xxxx", - "IP6Local": "fe80::xxxx:xxxx:xxxx:xxxx%st3", "Ethernet": { - "Hostname": "xxxxxxxx-eth", - "IPAddress": "192.168.0.2", - "Gateway": "192.168.0.99", - "Subnetmask": "255.255.254.0", "DNSServer1": "192.168.0.99", "DNSServer2": "0.0.0.0", - "Mac": "xx:xx:xx:xx:xx:xx", + "Gateway": "192.168.0.99", + "Hostname": "xxxxxxxx-eth", "IP6Global": "xxxx:::::::xxxx", - "IP6Local": "fe80::xxxx:xxxx:xxxx:xxxx%en1" + "IP6Local": "fe80::xxxx:xxxx:xxxx:xxxx%en1", + "IPAddress": "192.168.0.2", + "Mac": "xx:xx:xx:xx:xx:xx", + "Subnetmask": "255.255.254.0" }, - "Webserver": 2, + "Gateway": "192.168.0.99", "HTTP_API": 1, + "Hostname": "xxxxxxxx", + "IP6Global": "xxxx:::::::xxxx", + "IP6Local": "fe80::xxxx:xxxx:xxxx:xxxx%st3", + "IPAddress": "192.168.0.1", + "Mac": "xx:xx:xx:xx:xx:xx", + "Subnetmask": "255.255.254.0", + "Webserver": 2, "WifiConfig": 4, "WifiPower": 0.0 } diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json index 5daa964..407b977 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json @@ -1,13 +1,13 @@ { + "POWER1": "OFF", "Time": "2024-01-12T06:29:01", "Uptime": "2T05:25:48", "Vcc": 3.258, - "POWER1": "OFF", "Wifi": { "AP": 1, - "SSId": "xxx", "BSSId": "F0:9F:C2:03:CD:73", "Channel": 6, - "RSSI": 100 + "RSSI": 100, + "SSId": "xxx" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json index 826b85a..00fcd6a 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json @@ -1,17 +1,18 @@ { "Status": { - "Module": 1, + "ButtonRetain": 0, + "ButtonTopic": "0", "FriendlyName": [ "Sonoff_1" ], - "Topic": "sonoff_1", - "ButtonTopic": "0", + "LedState": 1, + "Module": 1, "Power": 1, "PowerOnState": 3, - "LedState": 1, + "PowerRetain": 0, "SaveData": 1, "SaveState": 1, - "SwitchTopic": "0", + "SensorRetain": 0, "SwitchMode": [ 0, 0, @@ -22,9 +23,8 @@ 0, 0 ], - "ButtonRetain": 0, "SwitchRetain": 0, - "SensorRetain": 0, - "PowerRetain": 0 + "SwitchTopic": "0", + "Topic": "sonoff_1" } } \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json index 4d865f2..8c9e798 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json @@ -1,14 +1,14 @@ { "StatusPRM": { "Baudrate": 115200, + "BootCount": 420, "GroupTopic": "sonoffs", "OtaUrl": "http://sonoff.maddox.co.uk/tasmota/sonoff.ino.bin", "RestartReason": "Hardware Watchdog", - "Uptime": "1T19:36:45", - "StartupUTC": "2024-01-10T00:03:13", - "Sleep": 0, - "BootCount": 420, + "SaveAddress": "F6000", "SaveCount": 10693, - "SaveAddress": "F6000" + "Sleep": 0, + "StartupUTC": "2024-01-10T00:03:13", + "Uptime": "1T19:36:45" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json index 3731aee..63246d0 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json @@ -1,10 +1,10 @@ { "StatusSNS": { - "Time": "2024-01-11T20:39:58", "AM2301": { - "Temperature": 23.9, - "Humidity": 24.4 + "Humidity": 24.4, + "Temperature": 23.9 }, - "TempUnit": "C" + "TempUnit": "C", + "Time": "2024-01-11T20:39:58" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json index a530494..a873dd6 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json @@ -1,15 +1,15 @@ { "StatusSTS": { + "POWER1": "ON", "Time": "2024-01-11T20:39:58", "Uptime": "1T19:36:45", "Vcc": 3.231, - "POWER1": "ON", "Wifi": { "AP": 1, - "SSId": "xxx", "BSSId": "F0:9F:C2:03:CD:73", "Channel": 6, - "RSSI": 100 + "RSSI": 100, + "SSId": "xxx" } } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json index 96a18cc..9c51b7e 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json @@ -1,9 +1,9 @@ { "StatusFWR": { - "Version": "6.3.0.12(sonoff)", - "BuildDateTime": "2018-11-23T14:07:50", "Boot": 4, + "BuildDateTime": "2018-11-23T14:07:50", "Core": "2_3_0", - "SDK": "1.5.3(aec24ac9)" + "SDK": "1.5.3(aec24ac9)", + "Version": "6.3.0.12(sonoff)" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json index d14ac9d..4c52cf3 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json @@ -1,19 +1,19 @@ { "StatusLOG": { - "SerialLog": 2, - "WebLog": 2, - "SysLog": 0, "LogHost": "192.168.0.130", "LogPort": 514, "SSId": [ "xxx", "xxx-2" ], - "TelePeriod": 300, + "SerialLog": 2, "SetOption": [ "54000009", "55818000", "00000001" - ] + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json index 62b4b48..009d6e3 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json @@ -1,18 +1,18 @@ { "StatusMEM": { - "ProgramSize": 498, - "Free": 504, - "Heap": 18, - "ProgramFlashSize": 1024, - "FlashSize": 1024, - "FlashChipId": "1440E0", - "FlashMode": 3, "Features": [ "00000809", "0FDAE794", "240383A0", "23B617CE", "00003BC0" - ] + ], + "FlashChipId": "1440E0", + "FlashMode": 3, + "FlashSize": 1024, + "Free": 504, + "Heap": 18, + "ProgramFlashSize": 1024, + "ProgramSize": 498 } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json index 46b6ff7..f38013d 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json @@ -1,12 +1,12 @@ { "StatusNET": { + "DNSServer": "192.168.1.130", + "Gateway": "192.168.1.1", "Hostname": "sonoff_1-3937", "IPAddress": "192.168.1.200", - "Gateway": "192.168.1.1", - "Subnetmask": "255.255.255.0", - "DNSServer": "192.168.1.130", "Mac": "5C:CF:7F:E7:4F:61", + "Subnetmask": "255.255.255.0", "Webserver": 2, "WifiConfig": 3 } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json index 57f4930..9433d71 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json @@ -1,12 +1,12 @@ { "StatusMQT": { + "KEEPALIVE": 15, + "MAX_PACKET_SIZE": 1000, + "MqttClient": "DVES_E74F61", + "MqttClientMask": "DVES_%06X", "MqttHost": "192.168.1.130", "MqttPort": 1883, - "MqttClientMask": "DVES_%06X", - "MqttClient": "DVES_E74F61", - "MqttUser": "DVES_USER", "MqttType": 1, - "MAX_PACKET_SIZE": 1000, - "KEEPALIVE": 15 + "MqttUser": "DVES_USER" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json index c4d0be8..5b514df 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json @@ -1,11 +1,11 @@ { "StatusTIM": { - "UTC": "Thu Jan 11 19:39:58 2024", + "EndDST": "Sun Oct 27 03:00:00 2024", "Local": "Thu Jan 11 20:39:58 2024", "StartDST": "Sun Mar 31 02:00:00 2024", - "EndDST": "Sun Oct 27 03:00:00 2024", - "Timezone": "+01:00", "Sunrise": "08:41", - "Sunset": "17:14" + "Sunset": "17:14", + "Timezone": "+01:00", + "UTC": "Thu Jan 11 19:39:58 2024" } -} +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json b/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json index b2fecef..437919c 100644 --- a/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json +++ b/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json @@ -1,19 +1,19 @@ { - "Time": "2024-01-11T11:42:21", - "Uptime": "44T15:13:31", - "UptimeSec": 3856411, "Heap": 26, - "SleepMode": "Dynamic", - "Sleep": 50, "LoadAvg": 19, "MqttCount": 12, + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-01-11T11:42:21", + "Uptime": "44T15:13:31", + "UptimeSec": 3856411, "Wifi": { "AP": 1, - "SSId": "asdqwe", "BSSId": "AA:BB:CC:DD:EE:FF", "Channel": 6, - "RSSI": 66, + "Downtime": "0T02:15:08", "LinkCount": 19, - "Downtime": "0T02:15:08" + "RSSI": 66, + "SSId": "asdqwe" } } \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS.json new file mode 100644 index 0000000..52cc2ec --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS.json @@ -0,0 +1,33 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "", + "FriendlyName": [ + "Ch\u0139\u201aopcy \u0139\u0161wiat\u0139\u201ao", + "Sonoff2", + "Sonoff3" + ], + "LedMask": "0000", + "LedState": 1, + "Module": 0, + "Power": 1, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "SwitchMode": [ + 5, + 5, + 5, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "ds102_chlopcy" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS1.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS1.json new file mode 100644 index 0000000..b1e5fed --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS1.json @@ -0,0 +1,16 @@ +{ + "StatusPRM": { + "Baudrate": 115200, + "BootCount": 1793, + "CfgHolder": 4617, + "GroupTopic": "swiatlo", + "OtaUrl": "http://ota.tasmota.com/tasmota/release-8.5.1/tasmota-lite.bin", + "RestartReason": "Software/System restart", + "SaveAddress": "FB000", + "SaveCount": 16456, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-08-28T23:18:44", + "Uptime": "17T12:56:51" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS10.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS10.json new file mode 100644 index 0000000..cf9bfbf --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS10.json @@ -0,0 +1,8 @@ +{ + "StatusSNS": { + "Switch1": "ON", + "Switch2": "ON", + "Switch3": "ON", + "Time": "2024-09-15T13:15:35" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS11.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS11.json new file mode 100644 index 0000000..ac24549 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS11.json @@ -0,0 +1,25 @@ +{ + "StatusSTS": { + "Heap": 25, + "LoadAvg": 19, + "MqttCount": 2, + "POWER1": "ON", + "POWER2": "OFF", + "POWER3": "OFF", + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-15T13:15:35", + "Uptime": "17T12:56:51", + "UptimeSec": 1515411, + "Wifi": { + "AP": 1, + "BSSId": "0A:55:31:5F:EB:B5", + "Channel": 6, + "Downtime": "0T00:00:09", + "LinkCount": 2, + "RSSI": 72, + "SSId": "NznCoDk3McKgMzgy", + "Signal": -64 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS2.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS2.json new file mode 100644 index 0000000..322c89d --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS2.json @@ -0,0 +1,11 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2020-01-11T17:00:11", + "CR": "351/699", + "Core": "2_6_1", + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "8.1.0.3(e7b061c-tasmota)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS3.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS3.json new file mode 100644 index 0000000..f13fdfc --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS3.json @@ -0,0 +1,22 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "NznCoDk3McKgMzgy", + "" + ], + "SerialLog": 2, + "SetOption": [ + "0000A009", + "0505C8000100060000005AFF000000000000", + "02808001", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 60, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS4.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS4.json new file mode 100644 index 0000000..6f718c8 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS4.json @@ -0,0 +1,21 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,29", + "Features": [ + "00000809", + "8FDAE397", + "043683A0", + "22B617CD", + "01001BC0", + "00007881" + ], + "FlashChipId": "1440C8", + "FlashMode": 3, + "FlashSize": 1024, + "Free": 432, + "Heap": 25, + "ProgramFlashSize": 1024, + "ProgramSize": 568, + "Sensors": "1,2,3,4,5,6,7,8,9,10,14,15,17,18,20,22,26,34" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS5.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS5.json new file mode 100644 index 0000000..a5c4ba8 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS5.json @@ -0,0 +1,13 @@ +{ + "StatusNET": { + "DNSServer": "10.2.30.254", + "Gateway": "10.2.30.254", + "Hostname": "ds102_chlopcy-4858", + "IPAddress": "10.2.30.40", + "Mac": "80:7D:3A:60:92:FA", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 2, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS6.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS6.json new file mode 100644 index 0000000..217a975 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS6.json @@ -0,0 +1,12 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1000, + "MqttClient": "DVES_6092FA", + "MqttClientMask": "DVES_%06X", + "MqttCount": 2, + "MqttHost": "mqtt.iot", + "MqttPort": 1883, + "MqttUser": "DVES_USER" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.1.0.3/STATUS7.json b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS7.json new file mode 100644 index 0000000..7eebe63 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.1.0.3/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "Sun Oct 27 03:00:00 2024", + "Local": "Sun Sep 15 13:15:35 2024", + "StartDST": "Sun Mar 31 02:00:00 2024", + "Sunrise": "06:27", + "Sunset": "19:02", + "Timezone": "+01:00", + "UTC": "Sun Sep 15 12:15:35 2024" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS.1.json new file mode 100644 index 0000000..e4c7e44 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS.1.json @@ -0,0 +1,33 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "Kuchnia \u015awiat\u0142o", + "FriendlyName": [ + "Kuchnia \u015awiat\u0142o", + "Sonoff2" + ], + "LedMask": "FFFF", + "LedState": 0, + "Module": 0, + "Power": 0, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "SwitchMode": [ + 5, + 5, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "", + "Topic": "ds102_kuchnia" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS.2.json new file mode 100644 index 0000000..0aaf5f5 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS.2.json @@ -0,0 +1,32 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "\u0141azienka H801", + "FriendlyName": [ + "\u0141azienka H801" + ], + "LedMask": "FFFF", + "LedState": 1, + "Module": 0, + "Power": 0, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "h801_lazienka" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS.json new file mode 100644 index 0000000..5172e0d --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS.json @@ -0,0 +1,32 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "Kuchnia Okap", + "FriendlyName": [ + "Kuchnia Okap" + ], + "LedMask": "FFFF", + "LedState": 1, + "Module": 49, + "Power": 0, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "neo_okap" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS1.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS1.1.json new file mode 100644 index 0000000..fe2e9f9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS1.1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2022-12-06T17:06:47", + "Baudrate": 115200, + "BootCount": 40, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release-8.5.1/tasmota-lite.bin", + "RestartReason": "External System", + "SaveAddress": "FA000", + "SaveCount": 31879, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-03-15T11:40:13", + "Uptime": "184T01:08:28" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS1.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS1.2.json new file mode 100644 index 0000000..40e859b --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS1.2.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2020-06-05T21:45:02", + "Baudrate": 115200, + "BootCount": 38, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release-8.5.1/tasmota-lite.bin", + "RestartReason": "Hardware Watchdog", + "SaveAddress": "F4000", + "SaveCount": 2998, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-06-25T22:33:36", + "Uptime": "81T14:18:09" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS1.json new file mode 100644 index 0000000..966193e --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2020-06-18T22:07:13", + "Baudrate": 115200, + "BootCount": 47, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release-8.5.1/tasmota-lite.bin", + "RestartReason": "Software/System restart", + "SaveAddress": "F9000", + "SaveCount": 8010, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-01-03T23:47:29", + "Uptime": "255T12:38:28" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS10.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS10.1.json new file mode 100644 index 0000000..be07df9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS10.1.json @@ -0,0 +1,7 @@ +{ + "StatusSNS": { + "Switch1": "ON", + "Switch2": "ON", + "Time": "2024-09-15T13:48:41" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS10.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS10.2.json new file mode 100644 index 0000000..1b9279a --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS10.2.json @@ -0,0 +1,5 @@ +{ + "StatusSNS": { + "Time": "2024-09-15T13:51:45" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS10.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS10.json new file mode 100644 index 0000000..3b74169 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS10.json @@ -0,0 +1,5 @@ +{ + "StatusSNS": { + "Time": "2024-09-15T13:25:57" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS11.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS11.1.json new file mode 100644 index 0000000..27dfa88 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS11.1.json @@ -0,0 +1,25 @@ +{ + "StatusSTS": { + "Heap": 27, + "LoadAvg": 19, + "MqttCount": 21, + "POWER1": "OFF", + "POWER2": "OFF", + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-15T13:48:41", + "Uptime": "184T01:08:28", + "UptimeSec": 15901708, + "Vcc": 3.438, + "Wifi": { + "AP": 1, + "BSSId": "E6:8D:8C:AE:84:A4", + "Channel": 6, + "Downtime": "0T00:22:20", + "LinkCount": 5, + "RSSI": 92, + "SSId": "NznCoDk3McKgMzgy", + "Signal": -54 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS11.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS11.2.json new file mode 100644 index 0000000..4e60df8 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS11.2.json @@ -0,0 +1,36 @@ +{ + "StatusSTS": { + "Channel": [ + 40, + 100, + 0 + ], + "Color": "66FF00", + "Dimmer": 100, + "Fade": "ON", + "HSBColor": "96,100,100", + "Heap": 27, + "LedTable": "ON", + "LoadAvg": 19, + "MqttCount": 77, + "POWER": "OFF", + "Scheme": 4, + "Sleep": 50, + "SleepMode": "Dynamic", + "Speed": 3, + "Time": "2024-09-15T13:51:45", + "Uptime": "81T14:18:09", + "UptimeSec": 7049889, + "Vcc": 3.538, + "Wifi": { + "AP": 1, + "BSSId": "0A:55:31:5F:EB:B5", + "Channel": 6, + "Downtime": "0T00:12:08", + "LinkCount": 68, + "RSSI": 54, + "SSId": "NznCoDk3McKgMzgy", + "Signal": -73 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS11.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS11.json new file mode 100644 index 0000000..eb39ba9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS11.json @@ -0,0 +1,24 @@ +{ + "StatusSTS": { + "Heap": 25, + "LoadAvg": 19, + "MqttCount": 920, + "POWER": "OFF", + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-15T13:25:57", + "Uptime": "255T12:38:28", + "UptimeSec": 22077508, + "Vcc": 3.526, + "Wifi": { + "AP": 1, + "BSSId": "E6:8D:8C:AE:84:A4", + "Channel": 6, + "Downtime": "0T10:33:49", + "LinkCount": 911, + "RSSI": 80, + "SSId": "NznCoDk3McKgMzgy", + "Signal": -60 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS2.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS2.1.json new file mode 100644 index 0000000..d1fa8e4 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS2.1.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2020-10-02T10:10:35", + "CR": "396/699", + "Core": "2_7_4_1", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "8.5.1(lite)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS2.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS2.2.json new file mode 100644 index 0000000..529956f --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS2.2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2020-10-02T10:10:35", + "CR": "425/699", + "Core": "2_7_4_1", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "8.5.1(lite)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS2.json new file mode 100644 index 0000000..3c2f7fa --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2020-10-02T10:10:35", + "CR": "382/699", + "Core": "2_7_4_1", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "8.5.1(lite)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS3.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS3.1.json new file mode 100644 index 0000000..a2ce1e7 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS3.1.json @@ -0,0 +1,23 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "NznCoDk3McKgMzgy", + "" + ], + "SerialLog": 2, + "SetOption": [ + "00008009", + "0505C8000100060000005AFF000000000000", + "02000001", + "00006000", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 60, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS3.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS3.2.json new file mode 100644 index 0000000..cfa7158 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS3.2.json @@ -0,0 +1,23 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "NznCoDk3McKgMzgy", + "" + ], + "SerialLog": 2, + "SetOption": [ + "00008009", + "2805C8000100060000005A00000000000000", + "02000001", + "00006200", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS3.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS3.json new file mode 100644 index 0000000..bfd6a42 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS3.json @@ -0,0 +1,23 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "NznCoDk3McKgMzgy", + "" + ], + "SerialLog": 2, + "SetOption": [ + "00008009", + "2805C8000100060000005A00000000000000", + "02008001", + "00006000", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS4.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS4.1.json new file mode 100644 index 0000000..0d561f9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS4.1.json @@ -0,0 +1,24 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,9,10,16,20,21,37", + "Features": [ + "00000809", + "8F000783", + "04108001", + "00000006", + "010001C0", + "00000000", + "00004004", + "00000000" + ], + "FlashChipId": "1440C8", + "FlashFrequency": 40, + "FlashMode": 3, + "FlashSize": 1024, + "Free": 528, + "Heap": 27, + "ProgramFlashSize": 1024, + "ProgramSize": 473, + "Sensors": "3" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS4.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS4.2.json new file mode 100644 index 0000000..0d561f9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS4.2.json @@ -0,0 +1,24 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,9,10,16,20,21,37", + "Features": [ + "00000809", + "8F000783", + "04108001", + "00000006", + "010001C0", + "00000000", + "00004004", + "00000000" + ], + "FlashChipId": "1440C8", + "FlashFrequency": 40, + "FlashMode": 3, + "FlashSize": 1024, + "Free": 528, + "Heap": 27, + "ProgramFlashSize": 1024, + "ProgramSize": 473, + "Sensors": "3" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS4.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS4.json new file mode 100644 index 0000000..04d8a92 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS4.json @@ -0,0 +1,24 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,9,10,16,20,21,37", + "Features": [ + "00000809", + "8F000783", + "04108001", + "00000006", + "010001C0", + "00000000", + "00004004", + "00000000" + ], + "FlashChipId": "146085", + "FlashFrequency": 40, + "FlashMode": 3, + "FlashSize": 1024, + "Free": 528, + "Heap": 25, + "ProgramFlashSize": 1024, + "ProgramSize": 473, + "Sensors": "3" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS5.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS5.1.json new file mode 100644 index 0000000..95e4b95 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS5.1.json @@ -0,0 +1,13 @@ +{ + "StatusNET": { + "DNSServer": "10.2.30.254", + "Gateway": "10.2.30.254", + "Hostname": "ds102_kuchnia-8070", + "IPAddress": "10.2.30.20", + "Mac": "A4:CF:12:A3:5F:86", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS5.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS5.2.json new file mode 100644 index 0000000..5dc898e --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS5.2.json @@ -0,0 +1,13 @@ +{ + "StatusNET": { + "DNSServer": "10.2.30.254", + "Gateway": "10.2.30.254", + "Hostname": "h801_lazienka-7004", + "IPAddress": "10.2.30.31", + "Mac": "80:7D:3A:33:BB:5C", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS5.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS5.json new file mode 100644 index 0000000..0c22100 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS5.json @@ -0,0 +1,13 @@ +{ + "StatusNET": { + "DNSServer": "10.2.30.254", + "Gateway": "10.2.30.254", + "Hostname": "neo_okap-6502", + "IPAddress": "10.2.30.21", + "Mac": "CC:50:E3:C8:F9:66", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS6.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS6.1.json new file mode 100644 index 0000000..6301bd6 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS6.1.json @@ -0,0 +1,12 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_A35F86", + "MqttClientMask": "DVES_%06X", + "MqttCount": 21, + "MqttHost": "mqtt.iot", + "MqttPort": 1883, + "MqttUser": "DVES_USER" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS6.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS6.2.json new file mode 100644 index 0000000..eedf6d9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS6.2.json @@ -0,0 +1,12 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_33BB5C", + "MqttClientMask": "DVES_%06X", + "MqttCount": 77, + "MqttHost": "mqtt.iot", + "MqttPort": 1883, + "MqttUser": "DVES_USER" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS6.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS6.json new file mode 100644 index 0000000..a2069f6 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS6.json @@ -0,0 +1,12 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_C8F966", + "MqttClientMask": "DVES_%06X", + "MqttCount": 920, + "MqttHost": "mqtt.iot", + "MqttPort": 1883, + "MqttUser": "DVES_USER" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS7.1.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS7.1.json new file mode 100644 index 0000000..e22bbe9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS7.1.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-15T13:48:41", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "06:27", + "Sunset": "19:02", + "Timezone": "+01:00", + "UTC": "2024-09-15T12:48:41" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS7.2.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS7.2.json new file mode 100644 index 0000000..d8e66b5 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS7.2.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-15T13:51:45", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "06:27", + "Sunset": "19:02", + "Timezone": "+01:00", + "UTC": "2024-09-15T12:51:45" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/8.5.1/STATUS7.json b/tests/status_parsing/jsonfiles/8.5.1/STATUS7.json new file mode 100644 index 0000000..b6ad759 --- /dev/null +++ b/tests/status_parsing/jsonfiles/8.5.1/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-15T13:25:57", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "06:27", + "Sunset": "19:02", + "Timezone": "+01:00", + "UTC": "2024-09-15T12:25:57" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS.json new file mode 100644 index 0000000..55cdf61 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS.json @@ -0,0 +1,32 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "RedRoomBulb1", + "FriendlyName": [ + "RedRoomBulb1" + ], + "LedMask": "FFFF", + "LedState": 1, + "Module": 0, + "Power": 1, + "PowerOnState": 3, + "PowerRetain": 1, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "redroombulb1" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS1.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS1.json new file mode 100644 index 0000000..3fb7a95 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2022-02-14T17:24:23", + "Baudrate": 115200, + "BootCount": 1121, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz", + "RestartReason": "External System", + "SaveAddress": "F9000", + "SaveCount": 3179, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2024-09-13T17:02:23", + "Uptime": "0T00:00:36" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS10.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS10.json new file mode 100644 index 0000000..11d3e0b --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS10.json @@ -0,0 +1,5 @@ +{ + "StatusSNS": { + "Time": "2024-09-13T18:02:59" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS11.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS11.json new file mode 100644 index 0000000..e0d331e --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS11.json @@ -0,0 +1,39 @@ +{ + "StatusSTS": { + "CT": 500, + "Channel": [ + 0, + 0, + 0, + 0, + 100 + ], + "Color": "00000000FF", + "Dimmer": 100, + "Fade": "ON", + "HSBColor": "0,0,0", + "Heap": 23, + "LedTable": "ON", + "LoadAvg": 94, + "MqttCount": 1, + "POWER": "ON", + "Scheme": 0, + "Sleep": 10, + "SleepMode": "Dynamic", + "Speed": 5, + "Time": "2024-09-13T18:02:59", + "Uptime": "0T00:00:36", + "UptimeSec": 36, + "White": 100, + "Wifi": { + "AP": 1, + "BSSId": "5C:E9:31:18:49:D4", + "Channel": 7, + "Downtime": "0T00:00:03", + "LinkCount": 1, + "RSSI": 66, + "SSId": "WifiNet", + "Signal": -67 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS2.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS2.json new file mode 100644 index 0000000..fbe9648 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2021-03-04T17:56:42", + "CR": "429/699", + "Core": "2_7_4_5", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "9.1.0(tasmota)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS3.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS3.json new file mode 100644 index 0000000..b8c655f --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS3.json @@ -0,0 +1,23 @@ +{ + "StatusLOG": { + "LogHost": "", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "WifiNet", + "" + ], + "SerialLog": 2, + "SetOption": [ + "00208029", + "0405C8000100060000005A00000000000000", + "08000000", + "00006000", + "00000000" + ], + "SysLog": 0, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS4.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS4.json new file mode 100644 index 0000000..9a6cd63 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS4.json @@ -0,0 +1,24 @@ +{ + "StatusMEM": { + "Drivers": "1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37", + "Features": [ + "00000809", + "8FDAE797", + "04368001", + "000000CF", + "010013C0", + "C000F981", + "00004004", + "00000000" + ], + "FlashChipId": "1540A1", + "FlashFrequency": 40, + "FlashMode": 3, + "FlashSize": 2048, + "Free": 400, + "Heap": 23, + "ProgramFlashSize": 1024, + "ProgramSize": 601, + "Sensors": "1,2,3,4,5,6" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS5.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS5.json new file mode 100644 index 0000000..58b69db --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS5.json @@ -0,0 +1,13 @@ +{ + "StatusNET": { + "DNSServer": "192.168.1.142", + "Gateway": "192.168.1.142", + "Hostname": "RedRoomBulb1", + "IPAddress": "192.168.1.154", + "Mac": "4C:EB:D6:02:41:E0", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS6.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS6.json new file mode 100644 index 0000000..1d07624 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS6.json @@ -0,0 +1,12 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "RedRoomBulb1", + "MqttClientMask": "RedRoomBulb1", + "MqttCount": 1, + "MqttHost": "192.168.1.230", + "MqttPort": 1883, + "MqttUser": "DVES_USER" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.1.0/STATUS7.json b/tests/status_parsing/jsonfiles/9.1.0/STATUS7.json new file mode 100644 index 0000000..b72c3ef --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.1.0/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-13T18:02:59", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "06:24", + "Sunset": "19:06", + "Timezone": "+01:00", + "UTC": "2024-09-13T17:02:59" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS.json new file mode 100644 index 0000000..d56176f --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS.json @@ -0,0 +1,34 @@ +{ + "Status": { + "ButtonRetain": 0, + "ButtonTopic": "0", + "DeviceName": "Woonkamer zigbee", + "FriendlyName": [ + "Woonkamer zigbee" + ], + "InfoRetain": 0, + "LedMask": "FFFF", + "LedState": 1, + "Module": 18, + "Power": 0, + "PowerOnState": 3, + "PowerRetain": 0, + "SaveData": 1, + "SaveState": 1, + "SensorRetain": 0, + "StateRetain": 0, + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "SwitchRetain": 0, + "SwitchTopic": "0", + "Topic": "zigbee" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS1.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS1.json new file mode 100644 index 0000000..1fcd704 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS1.json @@ -0,0 +1,17 @@ +{ + "StatusPRM": { + "BCResetTime": "2021-07-30T15:31:28", + "Baudrate": 115200, + "BootCount": 17, + "CfgHolder": 4617, + "GroupTopic": "tasmotas", + "OtaUrl": "http://otaserver/ota/tasmota/tasmota.bin.gz", + "RestartReason": "Power On", + "SaveAddress": "F5000", + "SaveCount": 4439, + "SerialConfig": "8N1", + "Sleep": 50, + "StartupUTC": "2023-10-30T08:26:27", + "Uptime": "321T06:15:00" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS11.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS11.json new file mode 100644 index 0000000..8c9c467 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS11.json @@ -0,0 +1,23 @@ +{ + "StatusSTS": { + "Heap": 24, + "LoadAvg": 22, + "MqttCount": 117, + "Sleep": 50, + "SleepMode": "Dynamic", + "Time": "2024-09-15T16:41:27", + "Uptime": "321T06:15:00", + "UptimeSec": 27756900, + "Wifi": { + "AP": 1, + "BSSId": "74:83:C2:2A:F1:AC", + "Channel": 1, + "Downtime": "0T00:14:26", + "LinkCount": 106, + "Mode": "11n", + "RSSI": 76, + "SSId": "indebuurt_IoT", + "Signal": -62 + } + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS2.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS2.json new file mode 100644 index 0000000..8e47e2f --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS2.json @@ -0,0 +1,12 @@ +{ + "StatusFWR": { + "Boot": 31, + "BuildDateTime": "2021-07-30T16:05:47", + "CR": "358/699", + "Core": "2_7_4_9", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "SDK": "2.2.2-dev(38a443e)", + "Version": "9.5.0.4(tzigbee)" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS3.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS3.json new file mode 100644 index 0000000..42be1f1 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS3.json @@ -0,0 +1,23 @@ +{ + "StatusLOG": { + "LogHost": "loghost", + "LogPort": 514, + "MqttLog": 0, + "Resolution": "558180C0", + "SSId": [ + "indebuurt_IoT", + "indebuurt" + ], + "SerialLog": 3, + "SetOption": [ + "00008009", + "2805C8000100060000005A0A000000000000", + "00000080", + "00046002", + "00000000" + ], + "SysLog": 2, + "TelePeriod": 300, + "WebLog": 2 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS4.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS4.json new file mode 100644 index 0000000..41d6ab9 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS4.json @@ -0,0 +1,25 @@ +{ + "StatusMEM": { + "Drivers": "1,2,7,9,10,12,23,24,38", + "Features": [ + "00000809", + "0F100580", + "04400001", + "00000002", + "00000000", + "00000001", + "00000080", + "00000000", + "00000000" + ], + "FlashChipId": "1640E0", + "FlashFrequency": 40, + "FlashMode": 3, + "FlashSize": 4096, + "Free": 476, + "Heap": 25, + "ProgramFlashSize": 1024, + "ProgramSize": 527, + "Sensors": "2" + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS5.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS5.json new file mode 100644 index 0000000..2512700 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS5.json @@ -0,0 +1,14 @@ +{ + "StatusNET": { + "DNSServer1": "192.168.2.27", + "DNSServer2": "192.168.2.24", + "Gateway": "192.168.2.254", + "Hostname": "zigbee", + "IPAddress": "192.168.2.175", + "Mac": "5C:CF:7F:13:9F:D8", + "Subnetmask": "255.255.255.0", + "Webserver": 2, + "WifiConfig": 4, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS6.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS6.json new file mode 100644 index 0000000..77abd89 --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS6.json @@ -0,0 +1,13 @@ +{ + "StatusMQT": { + "KEEPALIVE": 30, + "MAX_PACKET_SIZE": 1200, + "MqttClient": "DVES_139FD8", + "MqttClientMask": "DVES_%06X", + "MqttCount": 117, + "MqttHost": "mqttbroker", + "MqttPort": 1883, + "MqttUser": "DVES_USER", + "SOCKET_TIMEOUT": 4 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/9.5.0.4/STATUS7.json b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS7.json new file mode 100644 index 0000000..91cdfde --- /dev/null +++ b/tests/status_parsing/jsonfiles/9.5.0.4/STATUS7.json @@ -0,0 +1,11 @@ +{ + "StatusTIM": { + "EndDST": "2024-10-27T03:00:00", + "Local": "2024-09-15T16:41:27", + "StartDST": "2024-03-31T02:00:00", + "Sunrise": "07:06", + "Sunset": "19:46", + "Timezone": 99, + "UTC": "2024-09-15T14:41:27" + } +} \ No newline at end of file From 7482601ea2c82b99e5e776a5abcd38d323c718b0 Mon Sep 17 00:00:00 2001 From: jziolkowski Date: Sun, 15 Sep 2024 17:28:00 +0200 Subject: [PATCH 10/15] fix discovery parameter --- tdmgr/util/discovery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdmgr/util/discovery.py b/tdmgr/util/discovery.py index e5a192e..d6a9cba 100644 --- a/tdmgr/util/discovery.py +++ b/tdmgr/util/discovery.py @@ -18,7 +18,7 @@ def lwt_discovery_stage2(env: TasmotaEnvironment, message: Message): if match := message.match_fulltopic(full_topic): _match_topic = match.groupdict()["topic"] - if d := env.find_device(topic=_match_topic): + if d := env.find_device(message): d.update_property("FullTopic", full_topic) else: From 5ac28ec9b61df75a983610ad1edbc2612b76c4ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 18:36:12 +0200 Subject: [PATCH 11/15] make rows slimmer, enable shutter stopping, bump max shutters to 8 (#277) --- tdmgr/GUI/delegates/devices.py | 34 +++++++++++----------------------- tdmgr/GUI/devices.py | 7 +++++-- tdmgr/GUI/widgets.py | 2 +- tdmgr/models/devices.py | 4 ---- tdmgr/util/__init__.py | 6 +++--- 5 files changed, 20 insertions(+), 33 deletions(-) diff --git a/tdmgr/GUI/delegates/devices.py b/tdmgr/GUI/delegates/devices.py index 8412ef8..f7ecfad 100644 --- a/tdmgr/GUI/delegates/devices.py +++ b/tdmgr/GUI/delegates/devices.py @@ -25,9 +25,7 @@ class RectSpacing: RECT_ADJUSTMENT = (2, 2, -1, -1) -SHUTTER_RECT_SIZE = QSize( - RECT_SIZE.width() * 3 + RectSpacing.h * 2, RECT_SIZE.height() * 2 + RectSpacing.v -) +SHUTTER_RECT_SIZE = QSize(RECT_SIZE.width() * 2 + RectSpacing.h * 2, RECT_SIZE.height()) def get_pixmap_for_rssi(rssi: int) -> QPixmap: @@ -73,7 +71,7 @@ def get_relays_height(): return 6 + self.get_relays_rect_size(relay_data).height() return 0 - hint_height = max(42, get_relays_height(), 6 + SHUTTER_RECT_SIZE.height()) + hint_height = max(28, get_relays_height()) return QSize(QStyledItemDelegate().sizeHint(option, index).width(), hint_height) return QStyledItemDelegate().sizeHint(option, index) @@ -218,17 +216,13 @@ def paint(self, p: QPainter, option, index): def draw_rssi_pixmap(self, index, option, p): p.save() px = self.rssi_offline - rssi = 'offln' if index.data(DeviceRoles.LWTRole): rssi = index.data(DeviceRoles.RSSIRole) px = get_pixmap_for_rssi(rssi) - px_y = option.rect.y() + (option.rect.height() - 38) // 2 + px_y = option.rect.y() + (option.rect.height() - 24) // 2 px_rect = QRect(option.rect.x() + 2, px_y, 24, 24) p.drawPixmap(px_rect, px.scaled(24, 24)) - rssi_rect = QRect(option.rect.x() + 2, px_rect.y() + px_rect.height() + 2, 24, 12) - p.setFont(self.font_8pt) - p.drawText(rssi_rect, Qt.AlignCenter, str(rssi)) p.restore() def draw_relay_state(self, p: QPainter, target_rect: QRect, relay_data: dict): @@ -259,32 +253,26 @@ def draw_shutters_state(self, p: QPainter, target_rect: QRect, shutter_pos_data: title_rect = QRect(rect) title_rect.setHeight(RECT_SIZE.height()) - state_rect = QRect(rect) - state_rect.moveTop(title_rect.bottom() + 1) - state_rect.setBottom(rect.bottom()) - state_rect.adjust(*RECT_ADJUSTMENT) - - p.drawText(title_rect, Qt.AlignCenter, f'Shutter {shutter}') - direction = shutter_state['Direction'] + arrow_direction = {-1: ARROW_DN, 1: ARROW_UP} + position = ( - 'CLOSED' + 'CLS' if shutter_state['Position'] == 0 - else 'OPEN' if shutter_state['Position'] == 100 else shutter_state['Position'] + else 'OPN' if shutter_state['Position'] == 100 else shutter_state['Position'] ) - arrow_direction = {-1: ARROW_DN, 1: ARROW_UP} - if direction != 0: p.save() p.setPen(self.hltext_pen) - p.fillRect(state_rect, GREEN) - p.drawText(state_rect, Qt.AlignCenter, f"{arrow_direction[direction]} {position}") + p.fillRect(title_rect, GREEN) + p.drawText(title_rect, Qt.AlignCenter, f"{arrow_direction[direction]} {position}") p.restore() else: - p.drawText(state_rect, Qt.AlignCenter, f"{position}") + p.drawText(title_rect, Qt.AlignCenter, f'SHT{shutter} {position}') for r in [title_rect, rect]: p.drawRect(r) + shutter_col += 1 def draw_rssi_rect(self, p: QPainter, rect, index): diff --git a/tdmgr/GUI/devices.py b/tdmgr/GUI/devices.py index 60d0038..0939547 100644 --- a/tdmgr/GUI/devices.py +++ b/tdmgr/GUI/devices.py @@ -198,7 +198,7 @@ def create_actions(self): self.agShutters = QActionGroup(self) self.agShutters.setVisible(False) self.agShutters.setExclusive(False) - for shutter_idx in range(1, 5): + for shutter_idx in range(1, 9): for idx, arrow in enumerate([ARROW_UP, ARROW_DN]): px = make_relay_pixmap(arrow) self.agShutters.addAction( @@ -410,7 +410,10 @@ def toggle_power_all(self, action): def move_shutter(self, action): idx = 1 + self.agShutters.actions().index(action) shutter = (idx + 1) // 2 - action = "ShutterClose" if idx % 2 == 0 else "ShutterOpen" + direction = self.device.p[f"Shutter{shutter}"]["Direction"] + action = ( + "ShutterStop" if direction != 0 else "ShutterClose" if idx % 2 == 0 else "ShutterOpen" + ) self.mqtt.publish(self.device.cmnd_topic(f"{action}{shutter}")) def set_color(self): diff --git a/tdmgr/GUI/widgets.py b/tdmgr/GUI/widgets.py index 9c7f506..46a1c5d 100644 --- a/tdmgr/GUI/widgets.py +++ b/tdmgr/GUI/widgets.py @@ -209,7 +209,7 @@ def setupColumns(self, columns, hidden=None): def setupView(self, view): for i, c in enumerate(view): - if c in ("Device", "Module", "Topic", "FullTopic"): + if c in ("Device",): self.horizontalHeader().setSectionResizeMode(i, QHeaderView.Stretch) else: self.horizontalHeader().setSectionResizeMode(i, QHeaderView.ResizeToContents) diff --git a/tdmgr/models/devices.py b/tdmgr/models/devices.py index 0a4399e..7bf5c5f 100644 --- a/tdmgr/models/devices.py +++ b/tdmgr/models/devices.py @@ -33,10 +33,6 @@ def deviceAtRow(self, row): def notify_change(self, d, key): row = self.tasmota_env.devices.index(d) - # if key.startswith("POWER") and "Power" in self.columns: - # power_idx = self.columns.index("Power") - # idx = self.index(row, power_idx) - # self.dataChanged.emit(idx, idx) if any( [ diff --git a/tdmgr/util/__init__.py b/tdmgr/util/__init__.py index b0c6eb6..1a207f4 100644 --- a/tdmgr/util/__init__.py +++ b/tdmgr/util/__init__.py @@ -62,7 +62,7 @@ def initial_commands(): commands = [(command, "") for command in commands] commands += [("status", "0"), ("gpios", "255")] - for sht in range(4): + for sht in range(8): commands.append([f"shutterrelay{sht + 1}", ""]) commands.append([f"shutterposition{sht + 1}", ""]) @@ -343,12 +343,12 @@ def power(self): def shutters(self) -> dict: return { k: self.p[f"ShutterRelay{k}"] - for k in range(1, 5) + for k in range(1, 9) if f"ShutterRelay{k}" in self.p and self.p[f"ShutterRelay{k}"] != 0 } def shutter_positions(self) -> dict: - x = {k: self.p[f"Shutter{k}"] for k in range(1, 5) if f"Shutter{k}" in self.p} + x = {k: self.p[f"Shutter{k}"] for k in range(1, 9) if f"Shutter{k}" in self.p} return x def pwm(self): From 179adb70cce15b46349182e0ca7750c11363a4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Sun, 15 Sep 2024 20:32:15 +0200 Subject: [PATCH 12/15] Refactor (#278) --- tdmgr/GUI/console.py | 5 +- tdmgr/GUI/devices.py | 4 +- tdmgr/GUI/dialogs/buttons.py | 4 +- tdmgr/GUI/dialogs/main.py | 20 ++-- tdmgr/GUI/dialogs/patterns.py | 2 +- tdmgr/GUI/dialogs/power.py | 4 +- tdmgr/GUI/dialogs/setoptions.py | 2 +- tdmgr/GUI/dialogs/switches.py | 4 +- tdmgr/GUI/dialogs/templates.py | 11 ++- tdmgr/GUI/dialogs/timers.py | 3 +- tdmgr/GUI/rules.py | 3 +- tdmgr/GUI/widgets.py | 2 +- tdmgr/models/devices.py | 4 +- tdmgr/{util => }/mqtt.py | 23 +++++ tdmgr/tasmota/__init__.py | 0 tdmgr/{util => tasmota}/commands.py | 10 ++ tdmgr/tasmota/common.py | 1 + tdmgr/{util/__init__.py => tasmota/device.py} | 92 +++---------------- tdmgr/{util => tasmota}/discovery.py | 4 +- tdmgr/tasmota/environment.py | 22 +++++ tdmgr/{util => tasmota}/setoptions.py | 0 tests/conftest.py | 3 +- tests/test_device.py | 3 +- tests/test_environment.py | 4 +- tests/test_message.py | 2 +- tests/test_mqtt.py | 2 +- 26 files changed, 126 insertions(+), 108 deletions(-) rename tdmgr/{util => }/mqtt.py (94%) create mode 100644 tdmgr/tasmota/__init__.py rename tdmgr/{util => tasmota}/commands.py (89%) create mode 100644 tdmgr/tasmota/common.py rename tdmgr/{util/__init__.py => tasmota/device.py} (85%) rename tdmgr/{util => tasmota}/discovery.py (86%) create mode 100644 tdmgr/tasmota/environment.py rename tdmgr/{util => tasmota}/setoptions.py (100%) diff --git a/tdmgr/GUI/console.py b/tdmgr/GUI/console.py index 9e0a818..48db278 100644 --- a/tdmgr/GUI/console.py +++ b/tdmgr/GUI/console.py @@ -18,8 +18,9 @@ ) from tdmgr.GUI.widgets import GroupBoxV, HLayout, VLayout, console_font -from tdmgr.util import Message, TasmotaDevice -from tdmgr.util.commands import commands +from tdmgr.mqtt import Message +from tdmgr.tasmota.commands import commands +from tdmgr.tasmota.device import TasmotaDevice class ConsoleWidget(QDockWidget): diff --git a/tdmgr/GUI/devices.py b/tdmgr/GUI/devices.py index 0939547..676d5b0 100644 --- a/tdmgr/GUI/devices.py +++ b/tdmgr/GUI/devices.py @@ -44,7 +44,9 @@ base_view, default_views, ) -from tdmgr.util import TasmotaDevice, initial_commands, resets +from tdmgr.mqtt import initial_commands +from tdmgr.tasmota.commands import resets +from tdmgr.tasmota.device import TasmotaDevice class DevicesListWidget(QWidget): diff --git a/tdmgr/GUI/dialogs/buttons.py b/tdmgr/GUI/dialogs/buttons.py index 671d179..8201e58 100644 --- a/tdmgr/GUI/dialogs/buttons.py +++ b/tdmgr/GUI/dialogs/buttons.py @@ -2,8 +2,8 @@ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTabWidget, QWidget from tdmgr.GUI.widgets import Command, HTMLLabel, VLayout, docs_url -from tdmgr.util.commands import commands -from tdmgr.util.setoptions import setoptions +from tdmgr.tasmota.commands import commands +from tdmgr.tasmota.setoptions import setoptions class ButtonsDialog(QDialog): diff --git a/tdmgr/GUI/dialogs/main.py b/tdmgr/GUI/dialogs/main.py index 5f56ec8..0f450a3 100644 --- a/tdmgr/GUI/dialogs/main.py +++ b/tdmgr/GUI/dialogs/main.py @@ -29,9 +29,17 @@ from tdmgr.GUI.telemetry import TelemetryWidget from tdmgr.GUI.widgets import Toolbar from tdmgr.models.devices import TasmotaDevicesModel -from tdmgr.util import MQTT_PATH_REGEX, TasmotaDevice, TasmotaEnvironment, initial_commands -from tdmgr.util.discovery import lwt_discovery_stage2 -from tdmgr.util.mqtt import DEFAULT_PATTERNS, Message, MqttClient, expand_fulltopic +from tdmgr.mqtt import ( + DEFAULT_PATTERNS, + MQTT_PATH_REGEX, + Message, + MqttClient, + expand_fulltopic, + initial_commands, +) +from tdmgr.tasmota.device import TasmotaDevice +from tdmgr.tasmota.discovery import lwt_discovery_stage2 +from tdmgr.tasmota.environment import TasmotaEnvironment log = logging.getLogger(__name__) @@ -366,15 +374,15 @@ def mqtt_message(self, msg: Message): if device := self.env.find_device(msg): if msg.is_lwt: log.debug("MQTT: LWT message for %s: %s", device.p["Topic"], msg.payload) - device.update_property("LWT", msg.payload) + device.online = msg.payload - if msg.payload == device.p["Online"]: + if device.online: # known device came online, query initial state self.initial_query(device, True) else: # forward the message for processing - device.update_property("LWT", device.p["Online"]) + device.online = True device.process_message(msg) # TODO: ditto diff --git a/tdmgr/GUI/dialogs/patterns.py b/tdmgr/GUI/dialogs/patterns.py index 2e994a8..248259b 100644 --- a/tdmgr/GUI/dialogs/patterns.py +++ b/tdmgr/GUI/dialogs/patterns.py @@ -1,7 +1,7 @@ from PyQt5.QtWidgets import QDialog, QInputDialog, QLabel, QListWidget, QMessageBox, QPushButton from tdmgr.GUI.widgets import HLayout, VLayout -from tdmgr.util import DEFAULT_PATTERNS +from tdmgr.mqtt import DEFAULT_PATTERNS class PatternsDialog(QDialog): diff --git a/tdmgr/GUI/dialogs/power.py b/tdmgr/GUI/dialogs/power.py index 401a391..e18ff51 100644 --- a/tdmgr/GUI/dialogs/power.py +++ b/tdmgr/GUI/dialogs/power.py @@ -2,8 +2,8 @@ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTabWidget, QWidget from tdmgr.GUI.widgets import Command, HTMLLabel, Interlock, PulseTime, VLayout, docs_url -from tdmgr.util.commands import commands -from tdmgr.util.setoptions import setoptions +from tdmgr.tasmota.commands import commands +from tdmgr.tasmota.setoptions import setoptions class PowerDialog(QDialog): diff --git a/tdmgr/GUI/dialogs/setoptions.py b/tdmgr/GUI/dialogs/setoptions.py index 46e3434..821d682 100644 --- a/tdmgr/GUI/dialogs/setoptions.py +++ b/tdmgr/GUI/dialogs/setoptions.py @@ -2,7 +2,7 @@ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QLabel from tdmgr.GUI.widgets import DictComboBox, GroupBoxV, VLayout -from tdmgr.util.setoptions import setoptions +from tdmgr.tasmota.setoptions import setoptions class SetOptionsDialog(QDialog): diff --git a/tdmgr/GUI/dialogs/switches.py b/tdmgr/GUI/dialogs/switches.py index 3bd1f00..ba7be55 100644 --- a/tdmgr/GUI/dialogs/switches.py +++ b/tdmgr/GUI/dialogs/switches.py @@ -2,8 +2,8 @@ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTabWidget, QWidget from tdmgr.GUI.widgets import Command, CommandMultiSelect, HTMLLabel, VLayout, docs_url -from tdmgr.util.commands import commands -from tdmgr.util.setoptions import setoptions +from tdmgr.tasmota.commands import commands +from tdmgr.tasmota.setoptions import setoptions class SwitchesDialog(QDialog): diff --git a/tdmgr/GUI/dialogs/templates.py b/tdmgr/GUI/dialogs/templates.py index 4a0eaad..76e47a7 100644 --- a/tdmgr/GUI/dialogs/templates.py +++ b/tdmgr/GUI/dialogs/templates.py @@ -12,7 +12,16 @@ ) from tdmgr.GUI.widgets import DictComboBox, VLayout -from tdmgr.util import template_adc + +template_adc = { + "0": "None", + "15": "User", + "1": "Analog", + "2": "Temperature", + "3": "Light", + "4": "Button", + "5": "Buttoni", +} class TemplateDialog(QDialog): diff --git a/tdmgr/GUI/dialogs/timers.py b/tdmgr/GUI/dialogs/timers.py index 64f1404..f937119 100644 --- a/tdmgr/GUI/dialogs/timers.py +++ b/tdmgr/GUI/dialogs/timers.py @@ -14,7 +14,8 @@ ) from tdmgr.GUI.widgets import GroupBoxH, GroupBoxV, HLayout, VLayout -from tdmgr.util import Message, TasmotaDevice +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice class TimersDialog(QDialog): diff --git a/tdmgr/GUI/rules.py b/tdmgr/GUI/rules.py index a34c8a5..760633e 100644 --- a/tdmgr/GUI/rules.py +++ b/tdmgr/GUI/rules.py @@ -15,7 +15,8 @@ ) from tdmgr.GUI.widgets import CheckableAction, GroupBoxH, GroupBoxV, HLayout, Toolbar, VLayout -from tdmgr.util import Message, TasmotaDevice +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice RE_RULE = re.compile(r"^RULE\d", re.IGNORECASE) diff --git a/tdmgr/GUI/widgets.py b/tdmgr/GUI/widgets.py index 46a1c5d..6dfbdd5 100644 --- a/tdmgr/GUI/widgets.py +++ b/tdmgr/GUI/widgets.py @@ -24,7 +24,7 @@ ) from tdmgr.schemas.result import PulseTimeLegacyResultSchema -from tdmgr.util import TasmotaDevice +from tdmgr.tasmota.device import TasmotaDevice base_view = ["Device"] default_views = { diff --git a/tdmgr/models/devices.py b/tdmgr/models/devices.py index 7bf5c5f..8c6deea 100644 --- a/tdmgr/models/devices.py +++ b/tdmgr/models/devices.py @@ -4,7 +4,7 @@ from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt from tdmgr.models.roles import DeviceRoles -from tdmgr.util import TasmotaDevice +from tdmgr.tasmota.device import TasmotaDevice class TasmotaDevicesModel(QAbstractTableModel): @@ -128,7 +128,7 @@ def data(self, idx, role=Qt.DisplayRole): return val if role == DeviceRoles.LWTRole: - return d.is_online + return d.online if role == DeviceRoles.RestartReasonRole: return d.p.get("RestartReason") diff --git a/tdmgr/util/mqtt.py b/tdmgr/mqtt.py similarity index 94% rename from tdmgr/util/mqtt.py rename to tdmgr/mqtt.py index 115a594..31cfbfa 100644 --- a/tdmgr/util/mqtt.py +++ b/tdmgr/mqtt.py @@ -24,6 +24,29 @@ ] +def initial_commands(): + commands = [ + "template", + "modules", + "gpio", + "buttondebounce", + "switchdebounce", + "interlock", + "blinktime", + "blinkcount", + "pulsetime", + ] + + commands = [(command, "") for command in commands] + commands += [("status", "0"), ("gpios", "255")] + + for sht in range(8): + commands.append([f"shutterrelay{sht + 1}", ""]) + commands.append([f"shutterposition{sht + 1}", ""]) + + return commands + + def expand_fulltopic(fulltopic): if fulltopic[-1] != '/': fulltopic = f"{fulltopic}/" diff --git a/tdmgr/tasmota/__init__.py b/tdmgr/tasmota/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tdmgr/util/commands.py b/tdmgr/tasmota/commands.py similarity index 89% rename from tdmgr/util/commands.py rename to tdmgr/tasmota/commands.py index 9e862bf..a83998c 100644 --- a/tdmgr/util/commands.py +++ b/tdmgr/tasmota/commands.py @@ -1,3 +1,13 @@ +resets = [ + "1: reset device settings to firmware defaults", + "2: erase flash, reset device settings to firmware defaults", + "3: erase flash SDK parameters", + "4: reset device settings to firmware defaults, keep Wi-Fi credentials", + "5: erase flash, reset parameters to firmware defaults, keep Wi-Fi settings", + "6: erase flash, reset parameters to firmware defaults, keep Wi-Fi and MQTT settings", + "99: reset device bootcount to zero", +] + commands = { "BlinkCount": { "description": "Number of relay toggles (blinks)", diff --git a/tdmgr/tasmota/common.py b/tdmgr/tasmota/common.py new file mode 100644 index 0000000..b9dbbce --- /dev/null +++ b/tdmgr/tasmota/common.py @@ -0,0 +1 @@ +COMMAND_UNKNOWN = {"Command": "Unknown"} diff --git a/tdmgr/util/__init__.py b/tdmgr/tasmota/device.py similarity index 85% rename from tdmgr/util/__init__.py rename to tdmgr/tasmota/device.py index 1a207f4..2990eac 100644 --- a/tdmgr/util/__init__.py +++ b/tdmgr/tasmota/device.py @@ -1,7 +1,6 @@ import json import logging import re -from enum import Enum from functools import lru_cache from typing import Callable, Optional, Union @@ -9,6 +8,7 @@ from pydantic import BaseModel, ValidationError from PyQt5.QtCore import QObject, pyqtSignal +from tdmgr.mqtt import DEFAULT_PATTERNS, MQTT_PATH_REGEX, Message from tdmgr.schemas.discovery import DiscoverySchema, TopicPrefixes from tdmgr.schemas.result import ( PulseTimeLegacyResultSchema, @@ -16,82 +16,9 @@ TemplateResultSchema, ) from tdmgr.schemas.status import STATUS_SCHEMA_MAP -from tdmgr.util.mqtt import DEFAULT_PATTERNS, MQTT_PATH_REGEX, Message +from tdmgr.tasmota.common import COMMAND_UNKNOWN -# TODO: extract from __init__ - -# TODO: extract to common -resets = [ - "1: reset device settings to firmware defaults", - "2: erase flash, reset device settings to firmware defaults", - "3: erase flash SDK parameters", - "4: reset device settings to firmware defaults, keep Wi-Fi credentials", - "5: erase flash, reset parameters to firmware defaults, keep Wi-Fi settings", - "6: erase flash, reset parameters to firmware defaults, keep Wi-Fi and MQTT settings", - "99: reset device bootcount to zero", -] - -template_adc = { - "0": "None", - "15": "User", - "1": "Analog", - "2": "Temperature", - "3": "Light", - "4": "Button", - "5": "Buttoni", -} - - -COMMAND_UNKNOWN = {"Command": "Unknown"} - - -# TODO: extract to mqtt -def initial_commands(): - commands = [ - "template", - "modules", - "gpio", - "buttondebounce", - "switchdebounce", - "interlock", - "blinktime", - "blinkcount", - "pulsetime", - ] - - commands = [(command, "") for command in commands] - commands += [("status", "0"), ("gpios", "255")] - - for sht in range(8): - commands.append([f"shutterrelay{sht + 1}", ""]) - commands.append([f"shutterposition{sht + 1}", ""]) - - return commands - - -def parse_payload(payload): - match = re.match(r"(\d+) \((.*)\)", payload) - if match: - return dict([match.groups()]) - return {} - - -class DiscoveryMode(int, Enum): - BOTH = 0 - NATIVE = 1 - LEGACY = 2 - - -class TasmotaEnvironment: - def __init__(self): - self.devices: list[TasmotaDevice] = [] - self.lwts = dict() - self.retained = set() - - def find_device(self, msg: Message) -> 'TasmotaDevice': - for d in self.devices: - if d.message_topic_matches_fulltopic(msg): - return d +log = logging.getLogger(__name__) class TasmotaDevice(QObject): @@ -294,7 +221,7 @@ def process_status(self, schema: BaseModel, payload: dict): self.update_property(k, v) except ValidationError as e: - logging.critical("MQTT: Cannot parse %s", e) + log.critical("MQTT: Cannot parse %s", e) def process_sensor(self, payload: str): sensor_data = json.loads(payload) @@ -305,7 +232,7 @@ def process_sensor(self, payload: str): def process_message(self, msg: Message): if self.debug: - logging.debug("MQTT: %s %s", msg.topic, msg.payload) + log.debug("MQTT: %s %s", msg.topic, msg.payload) if msg.prefix in (self.topic_prefixes.stat, self.topic_prefixes.tele): # /STATE or /STATUS response @@ -408,9 +335,16 @@ def name(self): return self.p["Topic"] @property - def is_online(self): + def online(self): return self.p.get("LWT", self.p["Offline"]) == self.p["Online"] + @online.setter + def online(self, val: Union[bool, dict]): + if isinstance(val, bool): + self.update_property("LWT", self.p["Online"]) + else: + self.update_property("LWT", val) + @property def url(self) -> Optional[str]: if self.ip_address != "0.0.0.0": diff --git a/tdmgr/util/discovery.py b/tdmgr/tasmota/discovery.py similarity index 86% rename from tdmgr/util/discovery.py rename to tdmgr/tasmota/discovery.py index d6a9cba..bc7fc14 100644 --- a/tdmgr/util/discovery.py +++ b/tdmgr/tasmota/discovery.py @@ -1,6 +1,8 @@ import logging -from tdmgr.util import Message, TasmotaDevice, TasmotaEnvironment +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice +from tdmgr.tasmota.environment import TasmotaEnvironment def native_discovery(): diff --git a/tdmgr/tasmota/environment.py b/tdmgr/tasmota/environment.py new file mode 100644 index 0000000..98e47a5 --- /dev/null +++ b/tdmgr/tasmota/environment.py @@ -0,0 +1,22 @@ +from enum import Enum + +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice + + +class DiscoveryMode(int, Enum): + BOTH = 0 + NATIVE = 1 + LEGACY = 2 + + +class TasmotaEnvironment: + def __init__(self): + self.devices: list[TasmotaDevice] = [] + self.lwts = dict() + self.retained = set() + + def find_device(self, msg: Message) -> TasmotaDevice: + for d in self.devices: + if d.message_topic_matches_fulltopic(msg): + return d diff --git a/tdmgr/util/setoptions.py b/tdmgr/tasmota/setoptions.py similarity index 100% rename from tdmgr/util/setoptions.py rename to tdmgr/tasmota/setoptions.py diff --git a/tests/conftest.py b/tests/conftest.py index 3ba0720..143668c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,7 +2,8 @@ import pytest -from tdmgr.util import Message, TasmotaDevice +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice def get_payload(version: str, filename: str) -> bytes: diff --git a/tests/test_device.py b/tests/test_device.py index 0f4bd1f..18d24a4 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -1,6 +1,7 @@ import pytest -from tdmgr.util import Message, TasmotaDevice +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice from tests.conftest import get_payload diff --git a/tests/test_environment.py b/tests/test_environment.py index a50416a..42b7127 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -1,6 +1,8 @@ import pytest -from tdmgr.util import Message, TasmotaDevice, TasmotaEnvironment +from tdmgr.mqtt import Message +from tdmgr.tasmota.device import TasmotaDevice +from tdmgr.tasmota.environment import TasmotaEnvironment @pytest.mark.parametrize( diff --git a/tests/test_message.py b/tests/test_message.py index 4e6876d..d947079 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -1,6 +1,6 @@ import pytest -from tdmgr.util import Message +from tdmgr.mqtt import Message def test_message(): diff --git a/tests/test_mqtt.py b/tests/test_mqtt.py index 8bbf5bc..9633f73 100644 --- a/tests/test_mqtt.py +++ b/tests/test_mqtt.py @@ -1,6 +1,6 @@ import pytest -from tdmgr.util.mqtt import expand_fulltopic +from tdmgr.mqtt import expand_fulltopic @pytest.mark.parametrize( From 71e001bab9def6ccf34a616a06bd2cb93a391992 Mon Sep 17 00:00:00 2001 From: jziolkowski Date: Sun, 15 Sep 2024 20:36:48 +0200 Subject: [PATCH 13/15] Fix logging --- tdmgr/GUI/dialogs/main.py | 2 +- tdmgr/run.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tdmgr/GUI/dialogs/main.py b/tdmgr/GUI/dialogs/main.py index 0f450a3..06450d4 100644 --- a/tdmgr/GUI/dialogs/main.py +++ b/tdmgr/GUI/dialogs/main.py @@ -530,7 +530,7 @@ def open_config_file(self): @staticmethod def open_log_location(): - fi = QFileInfo(log.getLogger().handlers[1].baseFilename) + fi = QFileInfo(logging.getLogger().handlers[1].baseFilename) QDesktopServices.openUrl(QUrl.fromLocalFile(fi.absolutePath())) def auto_telemetry_period(self): diff --git a/tdmgr/run.py b/tdmgr/run.py index 43e2194..8549455 100644 --- a/tdmgr/run.py +++ b/tdmgr/run.py @@ -26,22 +26,24 @@ def configure_logging(args) -> None: elif args.log_location: log_path = os.path.join(args.log_location, "tdm.log") + logging.basicConfig( level="DEBUG" if args.debug else "INFO", datefmt="%Y-%m-%d %H:%M:%S", format="%(asctime)s [%(levelname)s] [%(filename)s] %(message)s", ) - logging.getLogger(__name__).addHandler( + + logging.getLogger().addHandler( TimedRotatingFileHandler(filename=log_path, when="d", interval=1) ) def get_settings(args: argparse.Namespace, filename: str) -> QSettings: if args.local: - return QSettings(f"{filename}.ini", QSettings.IniFormat) + return QSettings(filename, QSettings.IniFormat) if args.config_location: - return QSettings(os.path.join(args.config_location, f"{filename}.ini"), QSettings.IniFormat) - return QSettings(QSettings.IniFormat, QSettings.UserScope, "tdm", f"{filename}.ini") + return QSettings(os.path.join(args.config_location, filename), QSettings.IniFormat) + return QSettings(QSettings.IniFormat, QSettings.UserScope, "tdm", filename) def setup_parser() -> argparse.ArgumentParser: From d3a0a007eda609c901317262787ff7b9d7a8a330 Mon Sep 17 00:00:00 2001 From: jziolkowski Date: Sun, 15 Sep 2024 20:39:30 +0200 Subject: [PATCH 14/15] Release 2024.9.3 --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e2024f..447860c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ -## [development] +## [2024.9.3] +## Added +- up to 8 shutters supported + ## Changed - ethernet-enabled devices now show eth ip address when wifi is disabled (#266) +- rows in device list are slimmer now +- made shutter icons in device list smaller ## Fixed - clicking main menu buttons doesn't crash anymore (#235) From 97afc2ae24cb040e4a6b1f5aba262930aa6c351e Mon Sep 17 00:00:00 2001 From: jziolkowski Date: Sun, 15 Sep 2024 20:54:17 +0200 Subject: [PATCH 15/15] use version tag in (pre)release --- .github/workflows/release.yml | 146 ++++++++++++++++++---------------- pyproject.toml | 2 +- requirements_build.txt | 3 +- tdmgr/run.py | 1 - 4 files changed, 81 insertions(+), 71 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d272f79..c46904a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,80 +1,90 @@ name: GitHub release on: - workflow_dispatch: - push: - branches: - - master - - develop - paths-ignore: - - '.github/**' - - '**.md' + workflow_dispatch: + push: + branches: + - master + - develop + paths-ignore: + - '.github/**' + - '**.md' jobs: - Binaries: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - os: windows-2019 - arch: x86 - - os: windows-2019 - arch: x64 - - os: macos-13 - arch: x64 - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Set up Python 3.8 - uses: actions/setup-python@v4 - with: - python-version: '3.8' - architecture: ${{ matrix.arch }} + Binaries: + runs-on: ${{ matrix.os }} + outputs: + version-tag: ${{ steps.version_tag.outputs.VERSION_TAG }} + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + arch: x86 + - os: windows-2019 + arch: x64 + - os: macos-13 + arch: x64 - - name: Install PyInstaller - run: pip install -r requirements_build.txt + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python 3.8 + uses: actions/setup-python@v4 + with: + python-version: '3.8' + architecture: ${{ matrix.arch }} - - name: Build with PyInstaller - run: pyinstaller --noconfirm --clean tdmgr.spec + - name: Install PyInstaller + run: pip install -r requirements_build.txt - - name: Upload binaries artifact to workflow - uses: actions/upload-artifact@v3 - with: - name: tdmgr - path: dist/* + - name: Retrieve version tag + id: version_tag + shell: bash + run: echo "VERSION_TAG=$(python -m setuptools_scm)" >> $GITHUB_OUTPUT - Draft-Release: - runs-on: ubuntu-latest - needs: Binaries - steps: - - uses: actions/checkout@v3 + - name: Build with PyInstaller + run: pyinstaller --noconfirm --clean tdmgr.spec - # Create a draft release - - name: Create Draft Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref_name }} - release_name: TDM ${{ github.ref_name }} - draft: true - prerelease: ${{ github.ref_name == 'refs/heads/develop'}} + - name: Upload binaries artifact to workflow + uses: actions/upload-artifact@v3 + with: + name: tdmgr + path: dist/* - - name: Download artifacts from build - uses: actions/download-artifact@v3 - with: - path: dist + Draft-Release: + runs-on: ubuntu-latest + needs: Binaries + env: + VERSION_TAG: ${{ needs.Binaries.outputs.version-tag }} + steps: + - uses: actions/checkout@v3 - # Upload release assets: each file in `dist/` to the GitHub Release - - name: Upload Release Assets - run: | - for asset in dist/tdmgr/*; do - echo "Uploading asset: $asset" - gh release upload "${{ github.ref_name }}" "$asset" --clobber - done - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Create a draft release + - name: Create Draft Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.VERSION_TAG }} + release_name: TDM ${{ env.VERSION_TAG }} + draft: ${{ github.ref_name != 'refs/heads/develop'}} + prerelease: ${{ github.ref_name == 'refs/heads/develop'}} + + + - name: Download artifacts from build + uses: actions/download-artifact@v3 + with: + path: dist + + # Upload release assets: each file in `dist/` to the GitHub Release + - name: Upload Release Assets + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + for asset in dist/tdmgr/*; do + echo "Uploading asset: $asset" + gh release upload ${{ env.VERSION_TAG }} "$asset" --clobber + done diff --git a/pyproject.toml b/pyproject.toml index cb5ded6..207f80b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=42", "setuptools_scm>=6.0"] +requires = ["setuptools>=64", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" [project] diff --git a/requirements_build.txt b/requirements_build.txt index 3a20c6a..c55e3b3 100644 --- a/requirements_build.txt +++ b/requirements_build.txt @@ -1,3 +1,4 @@ -r requirements.txt pyinstaller>=4 -setuptools_scm +setuptools>=64 +setuptools-scm>=8 diff --git a/tdmgr/run.py b/tdmgr/run.py index 8549455..26ca1b2 100644 --- a/tdmgr/run.py +++ b/tdmgr/run.py @@ -26,7 +26,6 @@ def configure_logging(args) -> None: elif args.log_location: log_path = os.path.join(args.log_location, "tdm.log") - logging.basicConfig( level="DEBUG" if args.debug else "INFO", datefmt="%Y-%m-%d %H:%M:%S",