From 19da29b9b74459ba765a82645f69d2e2243956e5 Mon Sep 17 00:00:00 2001 From: pi3c Date: Sun, 14 Jan 2024 15:59:35 +0300 Subject: [PATCH] sprint1 refactor --- main.py | 6 ------ manage.py | 10 ++++++++++ poetry.lock | 34 ++++++++++++++++++++++++++++++- pyproject.toml | 1 + src/app.py | 11 ++++------ src/config.py | 2 +- src/device.py | 54 +++++++++++++++++++++++++++++++------------------- src/monitor.py | 30 +++++++++++++++------------- src/session.py | 2 -- 9 files changed, 99 insertions(+), 51 deletions(-) delete mode 100644 main.py create mode 100644 manage.py diff --git a/main.py b/main.py deleted file mode 100644 index ae63989..0000000 --- a/main.py +++ /dev/null @@ -1,6 +0,0 @@ -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/manage.py b/manage.py new file mode 100644 index 0000000..9b3db15 --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +import sys +from src.app import demo_test + + +if __name__ == "__main__": + if "--demo" in sys.argv: + demo_test() + + if "--run-server" in sys.argv: + pass diff --git a/poetry.lock b/poetry.lock index a69ccd2..9209fde 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,6 +71,20 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + [[package]] name = "packaging" version = "23.2" @@ -97,6 +111,24 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pyright" +version = "1.1.345" +description = "Command line wrapper for pyright" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyright-1.1.345-py3-none-any.whl", hash = "sha256:00891361baf58698aa660d9374823d65782823ceb4a65515ff5dd159b0d4d2b1"}, + {file = "pyright-1.1.345.tar.gz", hash = "sha256:bb8c80671cdaeb913142b49642a741959f3fcd728c99814631c2bde3a7864938"}, +] + +[package.dependencies] +nodeenv = ">=1.6.0" + +[package.extras] +all = ["twine (>=3.4.1)"] +dev = ["twine (>=3.4.1)"] + [[package]] name = "pytest" version = "7.4.4" @@ -229,4 +261,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "63e9ec089b621ebbb62f087b0c893cee4608b33e867a94543da384ea6520e3f6" +content-hash = "ea7047b815051aa3693aff5c70b1708617c98239d792c2361a90a86548e4184b" diff --git a/pyproject.toml b/pyproject.toml index c9df43f..e67db51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ influxdb-client = "^1.39.0" [tool.poetry.group.dev.dependencies] pytest = "^7.4.4" +pyright = "^1.1.345" [build-system] requires = ["poetry-core"] diff --git a/src/app.py b/src/app.py index a8b27fd..6021f02 100644 --- a/src/app.py +++ b/src/app.py @@ -1,9 +1,10 @@ +from src.config import test_config from src.device import FakeInverter from src.monitor import Monitor -def run_test_monitor(config: dict): - monitor = Monitor(session_config=config) +def demo_test(): + monitor = Monitor(session_config=test_config) device_conf = { "name": "myinv", "model": "12345", @@ -12,8 +13,4 @@ def run_test_monitor(config: dict): } device = FakeInverter(**device_conf) monitor.init_device(device) - monitor.demo_get_device_data_from_file() - - -if __name__ == "__main__": - pass + monitor.mainloop() diff --git a/src/config.py b/src/config.py index 3b29816..e572463 100644 --- a/src/config.py +++ b/src/config.py @@ -2,4 +2,4 @@ from dotenv import dotenv_values prod_config = dotenv_values("src/.env_prod") -test_config = dotenv_values("nts_ntu/.env_test") +test_config = dotenv_values("src/.env_test") diff --git a/src/device.py b/src/device.py index a18d807..f8ef97e 100644 --- a/src/device.py +++ b/src/device.py @@ -24,13 +24,14 @@ class Device(ABC): """ @abstractmethod - def connect(self): - """Реализуется физическое подключение к прибору, для сбора данных""" + def _connect_and_read(self) -> Any: + """Реализуется физическое подключение к прибору, и считывание данных""" raise NotImplementedError @abstractmethod def get_data(self) -> dict: - """Реализует получение данных от прибора возвращает словарь. + """Реализует получение данных "Монитором" от прибора. + Возвращает словарь. Считанные данные привести к dict описанной ниже структуры: dict_structure = { "measurement": "", @@ -45,25 +46,30 @@ class Device(ABC): : 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.name: str = "Invertor" + self.model: str = "model" + self.location: str = "location" self._raw_data: str - self.port: str = kwargs.get("name", "fakeCOMport") + self.port: str = "COM_port" self.__dict__.update(kwargs) - def connect(self): - pass + def _connect_and_read(self) -> str: + """Подключение к прибору + Реализует подключение к прибору и считывает поток данных + в виде строки. + Считанную строку сохранить в self._raw_data и вернуть + """ + return self._raw_data - def get_data(self, current_time: datetime = datetime.now()) -> dict: + def get_data(self, **kwargs) -> dict: + """""" + current_time = kwargs.get('current_time', datetime.now()) val_template = namedtuple( "InvertorData", [ @@ -71,7 +77,7 @@ class Inverter(Device): "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) + "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) @@ -80,8 +86,8 @@ class Inverter(Device): ], ) raw = self._raw_data.strip().lstrip("(").rstrip(")").split() - print(raw) - + if len(raw) != 10: + raise TypeError("неверный формат ответа") values = val_template(*map(float, raw[:-1]), raw[-1]) answer: dict = { "measurement": self.name, @@ -89,6 +95,7 @@ class Inverter(Device): "fields": values._asdict(), "time": current_time, } + print(answer) return answer @@ -97,14 +104,21 @@ class FakeInverter(Inverter): super().__init__(**kwargs) self.cur_datetime: datetime = datetime.now() - timedelta(hours=23) self.delta: timedelta = timedelta(minutes=10) + self.line_counter = 0 def __getattribute__(self, __name: str) -> Any: if __name == "cur_datetime": self.__dict__["cur_datetime"] += self.delta + + if __name == "_raw_data": + with open("telemetry.txt", mode="r") as f: + for _ in range(self.line_counter): + f.readline() + line = f.readline().strip() + self.__dict__["_raw_data"] = line + self.line_counter += 2 + 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) + def get_data(self, **kwargs) -> dict: + return super().get_data(current_time=self.cur_datetime) diff --git a/src/monitor.py b/src/monitor.py index be3eaab..6f0930b 100644 --- a/src/monitor.py +++ b/src/monitor.py @@ -11,36 +11,38 @@ class Monitor: 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) + """Инициализация конечного устройства для наблюдения""" + if isinstance(device, Device): + self.device_list.append(device) + else: + raise TypeError( + 'Не могу инициализировать конечное устройство,\n' \ + 'init_device притимает только объекты-наследники класса Device' + ) - def _get_device_data(self, device: Device) -> dict: + 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) + 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 index 06d373b..1125f0e 100644 --- a/src/session.py +++ b/src/session.py @@ -20,9 +20,7 @@ class InfDBSession: 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: