diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc7ea06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,220 @@ +pyproger/uploads/* +!pyproger/uploads/.gitkeep + +config.ini +data/ + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.env_* +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/main.py b/main.py new file mode 100644 index 0000000..ae63989 --- /dev/null +++ b/main.py @@ -0,0 +1,6 @@ +from src.app import run_test_monitor +from src.config import test_config + + +if __name__ == "__main__": + run_test_monitor(config=test_config) diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..a69ccd2 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,232 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "certifi" +version = "2023.11.17" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "influxdb-client" +version = "1.39.0" +description = "InfluxDB 2.0 Python client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "influxdb_client-1.39.0-py3-none-any.whl", hash = "sha256:35c4d73713b6b7d30ca5ebaf74b7d53217fb6c58cdec63484e529b43d26f061e"}, + {file = "influxdb_client-1.39.0.tar.gz", hash = "sha256:6a534913523bd262f1928e4ff80046bf95e313c1694ce13e45fd17eea90fe691"}, +] + +[package.dependencies] +certifi = ">=14.05.14" +python-dateutil = ">=2.5.3" +reactivex = ">=4.0.4" +setuptools = ">=21.0.0" +urllib3 = ">=1.26.0" + +[package.extras] +async = ["aiocsv (>=1.2.2)", "aiohttp (>=3.8.1)"] +ciso = ["ciso8601 (>=2.1.1)"] +extra = ["numpy", "pandas (>=0.25.3)"] +test = ["aioresponses (>=0.7.3)", "coverage (>=4.0.3)", "flake8 (>=5.0.3)", "httpretty (==1.0.5)", "jinja2 (==3.1.2)", "nose (>=1.3.7)", "pluggy (>=0.3.1)", "psutil (>=5.6.3)", "py (>=1.4.31)", "pytest (>=5.0.0)", "pytest-cov (>=3.0.0)", "pytest-timeout (>=2.1.0)", "randomize (>=0.13)", "sphinx (==1.8.5)", "sphinx-rtd-theme"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pluggy" +version = "1.3.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "1.0.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "reactivex" +version = "4.0.4" +description = "ReactiveX (Rx) for Python" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "reactivex-4.0.4-py3-none-any.whl", hash = "sha256:0004796c420bd9e68aad8e65627d85a8e13f293de76656165dffbcb3a0e3fb6a"}, + {file = "reactivex-4.0.4.tar.gz", hash = "sha256:e912e6591022ab9176df8348a653fe8c8fa7a301f26f9931c9d8c78a650e04e8"}, +] + +[package.dependencies] +typing-extensions = ">=4.1.1,<5.0.0" + +[[package]] +name = "setuptools" +version = "69.0.3" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.9.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, +] + +[[package]] +name = "urllib3" +version = "2.1.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "63e9ec089b621ebbb62f087b0c893cee4608b33e867a94543da384ea6520e3f6" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c9df43f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "IoT_monitoring" +version = "0.0.1" +description = "Monitoring for Iot deveces and save data" +authors = ["pi3c "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" +python-dotenv = "^1.0.0" +influxdb-client = "^1.39.0" + + +[tool.poetry.group.dev.dependencies] +pytest = "^7.4.4" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/app.py b/src/app.py new file mode 100644 index 0000000..a8b27fd --- /dev/null +++ b/src/app.py @@ -0,0 +1,19 @@ +from src.device import FakeInverter +from src.monitor import Monitor + + +def run_test_monitor(config: dict): + monitor = Monitor(session_config=config) + device_conf = { + "name": "myinv", + "model": "12345", + "location": "my_home", + "port": "COM", + } + device = FakeInverter(**device_conf) + monitor.init_device(device) + monitor.demo_get_device_data_from_file() + + +if __name__ == "__main__": + pass diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..3b29816 --- /dev/null +++ b/src/config.py @@ -0,0 +1,5 @@ +from dotenv import dotenv_values + + +prod_config = dotenv_values("src/.env_prod") +test_config = dotenv_values("nts_ntu/.env_test") diff --git a/src/device.py b/src/device.py new file mode 100644 index 0000000..a18d807 --- /dev/null +++ b/src/device.py @@ -0,0 +1,110 @@ +from abc import ABC, abstractmethod +from collections import namedtuple +from datetime import datetime, timedelta +from typing import Any + + +class Device(ABC): + """Абстрактный базовый класс прибора + Описывает необходимые к реализации атрибуты/методы, для подключения прибора + к системе мониторинга и сбора данных + + Атрибуты обязятельные к определению в приборе + --------------------------------------------------------------------------- + ... + + Методы обязательные к определению в приборе + --------------------------------------------------------------------------- + def connect(self) -> None + реализация подключения к прибору + + def get_data(self) -> dict + Получение текущих показаний прибора. Функция должна вернуть + словарь определенной структуры(см. соответствующий пункт документации) + """ + + @abstractmethod + def connect(self): + """Реализуется физическое подключение к прибору, для сбора данных""" + raise NotImplementedError + + @abstractmethod + def get_data(self) -> dict: + """Реализует получение данных от прибора возвращает словарь. + Считанные данные привести к dict описанной ниже структуры: + dict_structure = { + "measurement": "", + "tags": {"": ""}, + "fields": {"": }, + "time": + } + Допустимые типы данных в описанном словаре: + : str + : str + : str + : str + : str | int | float | bool + : datetime + + Функция должна вернуть созданный словарь + """ + raise NotImplementedError + + +class Inverter(Device): + def __init__(self, **kwargs) -> None: + self.name: str = kwargs.get("name", "fakeinvertor") + self.model: str = kwargs.get("model", "fakemodel") + self.location: str = kwargs.get("name", "fakelocation") + self._raw_data: str + self.port: str = kwargs.get("name", "fakeCOMport") + self.__dict__.update(kwargs) + + def connect(self): + pass + + def get_data(self, current_time: datetime = datetime.now()) -> dict: + val_template = namedtuple( + "InvertorData", + [ + "VVV", # O/P Voltage + "QQQ", # O/P load percent (Digital) 0, - 0% + "SS_S", # Battery voltage 12,24,48 + "BBB", # Battery capacity (as O/P load percent) + "TT_T", # Heat Sink Temperature (0-99.9) + "MMM", # Utility Power Voltage (0-250VACоооо) + "RR_R", # Output Power Frequency (40.0-70.0) Hz + "DDD", # DC BUS Voltage (0V) + "PPP", # O/P load Percent (Analog) (0-100%)u + "command_bits", + ], + ) + raw = self._raw_data.strip().lstrip("(").rstrip(")").split() + print(raw) + + values = val_template(*map(float, raw[:-1]), raw[-1]) + answer: dict = { + "measurement": self.name, + "tags": {"model": self.model, "location": self.location}, + "fields": values._asdict(), + "time": current_time, + } + return answer + + +class FakeInverter(Inverter): + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.cur_datetime: datetime = datetime.now() - timedelta(hours=23) + self.delta: timedelta = timedelta(minutes=10) + + def __getattribute__(self, __name: str) -> Any: + if __name == "cur_datetime": + self.__dict__["cur_datetime"] += self.delta + return super().__getattribute__(__name) + + def set_fake_answer(self, line: str) -> None: + self._raw_data = line + + def get_data(self, current_time: datetime = datetime.now()) -> dict: + return super().get_data(self.cur_datetime) diff --git a/src/monitor.py b/src/monitor.py new file mode 100644 index 0000000..be3eaab --- /dev/null +++ b/src/monitor.py @@ -0,0 +1,46 @@ +import time +from typing import List + +from src.device import Device +from src.session import InfDBSession + + +class Monitor: + def __init__( + self, + session_config: dict, + pooling_delay: int | float = 0.1, + ) -> None: + """ + description + """ + self.device_list: List[Device] = [] + self.session_config: dict = session_config + self.pooling_delay: int | float = pooling_delay + + def init_device(self, device: Device) -> None: + self.device_list.append(device) + + def _get_device_data(self, device: Device) -> dict: + answer = device.get_data() + return answer + + def __send_devices_data_to_db(self) -> None: + session = InfDBSession(config=self.session_config) + for device in self.device_list: + data: dict = self._get_device_data(device) + session.add(data) + session.commit() + + def mainloop(self) -> None: + while True: + self.__send_devices_data_to_db() + time.sleep(self.pooling_delay) + + def demo_get_device_data_from_file(self): + with open("telemetry.txt", mode="r") as f: + for line in f.readlines(): + line = line.strip() + if line: + self.device_list[0].set_fake_answer(line) + self.__send_devices_data_to_db() diff --git a/src/session.py b/src/session.py new file mode 100644 index 0000000..06d373b --- /dev/null +++ b/src/session.py @@ -0,0 +1,33 @@ +import influxdb_client as infdb +from influxdb_client import Point +from influxdb_client.client.write_api import SYNCHRONOUS + + +class InfDBSession: + def __init__(self, config: dict) -> None: + self.token: str + self.url: str + self.org: str + self.bucket: str + self.__dict__.update(config) + self.__points_queue: list = [] + + self.__client = infdb.InfluxDBClient( + url=self.url, + token=self.token, + org=self.org, + ) + self.__write_api = self.__client.write_api(write_options=SYNCHRONOUS) + + def add(self, point: dict) -> None: + print(point) + self.__points_queue.append(Point.from_dict(point)) + print(len(self.__points_queue)) + + def commit(self) -> None: + while self.__points_queue: + self.__write_api.write( + org=self.org, + bucket=self.bucket, + record=self.__points_queue.pop(0), + ) diff --git a/telemetry.txt b/telemetry.txt new file mode 100644 index 0000000..5825e3f --- /dev/null +++ b/telemetry.txt @@ -0,0 +1,135 @@ +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.3 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.8 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(230 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 20.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 30.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 40.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 50.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 60.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 70.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 80.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 99.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 70.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 40.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(250 050 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 050 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 075 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 100 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 100 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 100 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.2 100 00.0 000 50.0 000 007 1000000000000000000) +(229 025 27.1 100 00.0 000 50.0 000 007 1000000000000000000) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_interface.py b/tests/test_interface.py new file mode 100644 index 0000000..a221b7f --- /dev/null +++ b/tests/test_interface.py @@ -0,0 +1,7 @@ +from nts_ntu.app import InfDBInterface +from nts_ntu.config import test_config + + +def test_intarface_creation(): + interface = InfDBInterface(config=test_config) + assert interface.org == "MyOrg"