miza-datahub 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. miza_datahub-1.0.0/LICENSE +21 -0
  2. miza_datahub-1.0.0/MANIFEST.in +2 -0
  3. miza_datahub-1.0.0/PKG-INFO +42 -0
  4. miza_datahub-1.0.0/README.md +25 -0
  5. miza_datahub-1.0.0/pyproject.toml +16 -0
  6. miza_datahub-1.0.0/setup.cfg +73 -0
  7. miza_datahub-1.0.0/src/logic.egg-info/PKG-INFO +12 -0
  8. miza_datahub-1.0.0/src/logic.egg-info/SOURCES.txt +17 -0
  9. miza_datahub-1.0.0/src/logic.egg-info/dependency_links.txt +1 -0
  10. miza_datahub-1.0.0/src/logic.egg-info/top_level.txt +1 -0
  11. miza_datahub-1.0.0/src/miza_datahub/__init__.py +0 -0
  12. miza_datahub-1.0.0/src/miza_datahub/__pycache__/__init__.cpython-311.pyc +0 -0
  13. miza_datahub-1.0.0/src/miza_datahub/common/__init__.py +0 -0
  14. miza_datahub-1.0.0/src/miza_datahub/common/__pycache__/__init__.cpython-311.pyc +0 -0
  15. miza_datahub-1.0.0/src/miza_datahub/common/__pycache__/config_const.cpython-311.pyc +0 -0
  16. miza_datahub-1.0.0/src/miza_datahub/common/__pycache__/config_util.cpython-311.pyc +0 -0
  17. miza_datahub-1.0.0/src/miza_datahub/common/__pycache__/singleton.cpython-311.pyc +0 -0
  18. miza_datahub-1.0.0/src/miza_datahub/common/config_const.py +14 -0
  19. miza_datahub-1.0.0/src/miza_datahub/common/config_util.py +74 -0
  20. miza_datahub-1.0.0/src/miza_datahub/common/singleton.py +11 -0
  21. miza_datahub-1.0.0/src/miza_datahub/influxdb/__init__.py +0 -0
  22. miza_datahub-1.0.0/src/miza_datahub/influxdb/__pycache__/__init__.cpython-311.pyc +0 -0
  23. miza_datahub-1.0.0/src/miza_datahub/influxdb/__pycache__/influx_repository.cpython-311.pyc +0 -0
  24. miza_datahub-1.0.0/src/miza_datahub/influxdb/__pycache__/influx_rest_client.cpython-311.pyc +0 -0
  25. miza_datahub-1.0.0/src/miza_datahub/influxdb/influx_repository.py +15 -0
  26. miza_datahub-1.0.0/src/miza_datahub/influxdb/influx_rest_client.py +26 -0
  27. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/__init__.py +0 -0
  28. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/__pycache__/__init__.cpython-311.pyc +0 -0
  29. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/__pycache__/paper_machine_query.cpython-311.pyc +0 -0
  30. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/__pycache__/paper_oee_query.cpython-311.pyc +0 -0
  31. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/paper_machine_query.py +110 -0
  32. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/paper_oee_query.py +97 -0
  33. miza_datahub-1.0.0/src/miza_datahub/influxdb/queries/production_time_query.py +51 -0
  34. miza_datahub-1.0.0/src/miza_datahub/influxdb/writers/__init__.py +0 -0
  35. miza_datahub-1.0.0/src/miza_datahub/influxdb/writers/__pycache__/__init__.cpython-311.pyc +0 -0
  36. miza_datahub-1.0.0/src/miza_datahub/influxdb/writers/__pycache__/paper_daily_oee_writer.cpython-311.pyc +0 -0
  37. miza_datahub-1.0.0/src/miza_datahub/influxdb/writers/paper_daily_oee_writer.py +80 -0
  38. miza_datahub-1.0.0/src/miza_datahub/readers/__init__.py +0 -0
  39. miza_datahub-1.0.0/src/miza_datahub/readers/__pycache__/__init__.cpython-311.pyc +0 -0
  40. miza_datahub-1.0.0/src/miza_datahub/readers/__pycache__/base_reader.cpython-311.pyc +0 -0
  41. miza_datahub-1.0.0/src/miza_datahub/readers/__pycache__/finished_product_quality_analyzer.cpython-311.pyc +0 -0
  42. miza_datahub-1.0.0/src/miza_datahub/readers/__pycache__/oee_analyzer.cpython-311.pyc +0 -0
  43. miza_datahub-1.0.0/src/miza_datahub/readers/__pycache__/quality_analyzer.cpython-311.pyc +0 -0
  44. miza_datahub-1.0.0/src/miza_datahub/readers/base_reader.py +72 -0
  45. miza_datahub-1.0.0/src/miza_datahub/readers/oee_analyzer.py +71 -0
  46. miza_datahub-1.0.0/src/miza_datahub/readers/quality_analyzer.py +140 -0
  47. miza_datahub-1.0.0/src/miza_datahub/services/__init__.py +0 -0
  48. miza_datahub-1.0.0/src/miza_datahub/services/__pycache__/__init__.cpython-311.pyc +0 -0
  49. miza_datahub-1.0.0/src/miza_datahub/services/__pycache__/oee_service.cpython-311.pyc +0 -0
  50. miza_datahub-1.0.0/src/miza_datahub/services/__pycache__/reader_factory.cpython-311.pyc +0 -0
  51. miza_datahub-1.0.0/src/miza_datahub/services/oee_service.py +44 -0
  52. miza_datahub-1.0.0/src/miza_datahub/services/reader_factory.py +36 -0
  53. miza_datahub-1.0.0/src/miza_datahub.egg-info/PKG-INFO +42 -0
  54. miza_datahub-1.0.0/src/miza_datahub.egg-info/SOURCES.txt +56 -0
  55. miza_datahub-1.0.0/src/miza_datahub.egg-info/dependency_links.txt +1 -0
  56. miza_datahub-1.0.0/src/miza_datahub.egg-info/requires.txt +4 -0
  57. miza_datahub-1.0.0/src/miza_datahub.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 chanelcolgate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ graft src
2
+ recursive-exclude __pycache__ *.py[cod]
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: miza-datahub
3
+ Version: 1.0.0
4
+ Summary: This package does amazing things.
5
+ Home-page: http://github.com/chanelcolgate/miza-datahub
6
+ Author: chanelcolgate
7
+ Author-email: "chanelcolgate" <github@chanelcolgate.com>
8
+ License: MIT
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy
13
+ Requires-Dist: pandas
14
+ Requires-Dist: requests
15
+ Requires-Dist: openpyxl
16
+ Dynamic: license-file
17
+
18
+ ## Miza DataHub Library
19
+ ### How to install
20
+ - Cài pip
21
+ ```bash
22
+ pip install --upgrade pip setuptools wheel
23
+ ```
24
+ - Cách khác
25
+ ```bash
26
+ python -m ensurepip --upgrade
27
+ ```
28
+ - Cách cài đặt và chạy
29
+ ```
30
+ pyproject-build
31
+ python -m pip install -e .
32
+ ```
33
+ - Cách test
34
+ ```
35
+ python -m pip install pytest
36
+ python -m pytest
37
+ python -m pip install mypy
38
+ python -m mypy
39
+ python -m pip install tox
40
+ tox -e typecheck
41
+ tox -e lint
42
+ ```
@@ -0,0 +1,25 @@
1
+ ## Miza DataHub Library
2
+ ### How to install
3
+ - Cài pip
4
+ ```bash
5
+ pip install --upgrade pip setuptools wheel
6
+ ```
7
+ - Cách khác
8
+ ```bash
9
+ python -m ensurepip --upgrade
10
+ ```
11
+ - Cách cài đặt và chạy
12
+ ```
13
+ pyproject-build
14
+ python -m pip install -e .
15
+ ```
16
+ - Cách test
17
+ ```
18
+ python -m pip install pytest
19
+ python -m pytest
20
+ python -m pip install mypy
21
+ python -m mypy
22
+ python -m pip install tox
23
+ tox -e typecheck
24
+ tox -e lint
25
+ ```
@@ -0,0 +1,16 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.black]
6
+ line-length = 80
7
+ target-version = ['py311']
8
+
9
+ [dependency-groups]
10
+ dev = [
11
+ "numpy>=2.4.6",
12
+ ]
13
+
14
+ [[tool.mypy.overrides]]
15
+ module = ["pandas.*", "numpy.*", "requests"]
16
+ ignore_missing_imports = true
@@ -0,0 +1,73 @@
1
+ [metadata]
2
+ name = miza-datahub
3
+ version = 1.0.0
4
+ url = http://github.com/chanelcolgate/miza-datahub
5
+ author = chanelcolgate
6
+ author_email = "chanelcolgate" <github@chanelcolgate.com>
7
+ description = This package does amazing things.
8
+ long_description = file: README.md
9
+ long_description_content_type = text/markdown
10
+ license = MIT
11
+ license_files = LICENSE
12
+ classifiers =
13
+ License :: OSI Approved :: MIT License
14
+
15
+ [options]
16
+ package_dir =
17
+ =src
18
+ packages = find:
19
+ include_package_data = True
20
+ install_requires =
21
+ numpy
22
+ pandas
23
+ requests
24
+ openpyxl
25
+
26
+ [options.packages.find]
27
+ where = src
28
+ exclude =
29
+ test*
30
+
31
+ [tox:tox]
32
+ isolated_build = True
33
+ envlist = py311
34
+
35
+ [flake8]
36
+ max-line-length = 80
37
+
38
+ [testenv]
39
+ deps =
40
+ pytest
41
+ pytest-cov
42
+ commands =
43
+ pytest {posargs}
44
+
45
+ [testenv:typecheck]
46
+ deps =
47
+ black
48
+ mypy
49
+ pytest
50
+ types-termcolor
51
+ commands =
52
+ black {posargs:--check --diff src test}
53
+ mypy src test
54
+
55
+ [testenv:format]
56
+ skip_install = True
57
+ deps =
58
+ black
59
+ commands =
60
+ black {posargs:--check --diff src test}
61
+
62
+ [testenv:lint]
63
+ skip_install = True
64
+ deps =
65
+ flake8
66
+ flake8-bugbear
67
+ commands =
68
+ flake8 {posargs:--ignore=E203,W503 src test}
69
+
70
+ [egg_info]
71
+ tag_build =
72
+ tag_date = 0
73
+
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: logic
3
+ Version: 0.0.1
4
+ Summary: This package does amazing things.
5
+ Home-page: http://github.com/chanelcolgate/miza-datahub
6
+ Author: chanelcolgate
7
+ Author-email: "chanelcolgate" <github@chanelcolgate.com>
8
+ License: MIT
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Dynamic: license-file
@@ -0,0 +1,17 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.cfg
6
+ src/logic.egg-info/PKG-INFO
7
+ src/logic.egg-info/SOURCES.txt
8
+ src/logic.egg-info/dependency_links.txt
9
+ src/logic.egg-info/top_level.txt
10
+ src/miza_datahub/__init__.py
11
+ src/miza_datahub/common/__init__.py
12
+ src/miza_datahub/common/config_const.py
13
+ src/miza_datahub/common/config_util.py
14
+ src/miza_datahub/common/singleton.py
15
+ src/miza_datahub/readers/__init__.py
16
+ src/miza_datahub/readers/base_reader.py
17
+ src/miza_datahub/readers/finished_product_quality_analyzer.py
@@ -0,0 +1 @@
1
+ miza_datahub
File without changes
File without changes
@@ -0,0 +1,14 @@
1
+ EXCEL = "Excel"
2
+ DATA_PATH = "data_path"
3
+
4
+ TELEGRAM = "Telegram"
5
+ TOKEN = "token"
6
+ URL_GET_FILE_PATH = "https://api.telegram.org/bot{token}/getFile"
7
+ URL_GET_FILE_CONTENT = "https://api.telegram.org/file/bot{token}/{file_path}"
8
+
9
+ INFLUX = "Influx"
10
+ INFLUX_HOST = "host"
11
+ INFLUX_PORT = "port"
12
+ INFLUX_DB = "db"
13
+
14
+ DEFAULT_CONFIG_FILE_NAME = "./config/miza_datahub_config.props"
@@ -0,0 +1,74 @@
1
+ import os
2
+ import configparser
3
+ import logging
4
+
5
+ from miza_datahub.common.singleton import Singleton
6
+ from miza_datahub.common import config_const as ConfigConst
7
+
8
+
9
+ class ConfigUtil(metaclass=Singleton):
10
+ config_file = ConfigConst.DEFAULT_CONFIG_FILE_NAME
11
+ config_parser = configparser.ConfigParser()
12
+ is_loaded = False
13
+
14
+ def __init__(self, config_file: str | None = None) -> None:
15
+ if config_file is not None:
16
+ self.config_file = config_file
17
+
18
+ self._load_config()
19
+ logging.info(f"Creted instance of ConfigUtil: {self}")
20
+
21
+ def _load_config(self):
22
+ if os.path.exists(self.config_file):
23
+ logging.info(f"Loading config: {self.config_file}")
24
+ self.config_parser.read(self.config_file)
25
+ self.is_loaded = True
26
+ else:
27
+ logging.info(f"""Can't load {self.config_file}.
28
+ Trying default: {ConfigConst.DEFAULT_CONFIG_FILE_NAME}""")
29
+ self.config_file = ConfigConst.DEFAULT_CONFIG_FILE_NAME
30
+ self.config_parser.read(self.config_file)
31
+ self.is_loaded = True
32
+
33
+ logging.debug(f"Config: {self.config_parser.sections()}")
34
+
35
+ def _get_config(
36
+ self, force_reload: bool = False
37
+ ) -> configparser.ConfigParser:
38
+ if not self.is_loaded or force_reload:
39
+ self._load_config()
40
+
41
+ return self.config_parser
42
+
43
+ def get_property(
44
+ self,
45
+ section: str,
46
+ key: str,
47
+ default_val: str | None = None,
48
+ force_reload: bool = False,
49
+ ):
50
+ return self._get_config(force_reload).get(
51
+ section, key, fallback=default_val
52
+ )
53
+
54
+ def get_float(
55
+ self,
56
+ section: str,
57
+ key: str,
58
+ default_val: float = 0.0,
59
+ force_reload: bool = False,
60
+ ):
61
+ return self._get_config(force_reload).getfloat(
62
+ section, key, fallback=default_val
63
+ )
64
+
65
+ def get_int(
66
+ self,
67
+ section: str,
68
+ key: str,
69
+ default_val: int = 0,
70
+ force_reload: bool = False,
71
+ ):
72
+ return self._get_config(force_reload).getint(
73
+ section, key, fallback=default_val
74
+ )
@@ -0,0 +1,11 @@
1
+ from typing import Any, Dict
2
+
3
+
4
+ class Singleton(type):
5
+ _instances: Dict[type, Any] = {}
6
+
7
+ def __call__(c, *args, **kwargs):
8
+ if c not in c._instances:
9
+ c._instances[c] = super().__call__(*args, **kwargs)
10
+
11
+ return c._instances[c]
@@ -0,0 +1,15 @@
1
+ class InfluxRepository:
2
+ def __init__(self, client):
3
+ self.client = client
4
+
5
+ def query(self, sql):
6
+ return self.client.query(sql)
7
+
8
+ def write(self, line_protocol):
9
+ return self.client.write(line_protocol)
10
+
11
+ @staticmethod
12
+ def escape_string(string):
13
+ return string.translate(
14
+ string.maketrans({",": r"\,", " ": r"\ ", "=": r"\="})
15
+ )
@@ -0,0 +1,26 @@
1
+ import requests
2
+
3
+
4
+ class InfluxRestClient:
5
+ def __init__(self, host: str, port: int, database: str):
6
+ self.database = database
7
+ self.query_url = f"http://{host}:{port}/query"
8
+ self.write_url = f"http://{host}:{port}/write"
9
+
10
+ def query(self, sql: str):
11
+ response = requests.get(
12
+ self.query_url, params={"db": self.database, "q": sql}
13
+ )
14
+
15
+ response.raise_for_status()
16
+ return response.json()
17
+
18
+ def write(self, payload: str):
19
+ response = requests.post(
20
+ self.write_url,
21
+ params={"db": self.database, "precision": "s"},
22
+ data=payload,
23
+ )
24
+
25
+ response.raise_for_status()
26
+ return response.text
@@ -0,0 +1,110 @@
1
+ from miza_datahub.influxdb.influx_repository import InfluxRepository
2
+
3
+
4
+ class PaperMachineRepository(InfluxRepository):
5
+ def get_actual_production(self, start_time: str, end_time: str) -> float:
6
+ query = f"""
7
+ SELECT integral("ton_per_min",1m)
8
+ FROM (
9
+ SELECT
10
+ (
11
+ mean("reel_speed")
12
+ * 4.8
13
+ * mean("basic_weight")
14
+ * 0.9
15
+ ) / 1000000 AS ton_per_min
16
+ FROM miza_realtime
17
+ WHERE
18
+ line='Máy giấy PM3'
19
+ AND machine='Scanner'
20
+ AND time >= '{start_time}'
21
+ AND time <= '{end_time}'
22
+ GROUP BY time(1m)
23
+ )
24
+ """
25
+
26
+ result = self.query(query)
27
+ print(result)
28
+ return result["results"][0]["series"][0]["values"][0][1]
29
+
30
+ def get_plan_production(self, start_time: str, end_time: str) -> float:
31
+ query = f"""
32
+ SELECT integral("ton_per_min",1m)
33
+ FROM (
34
+ SELECT
35
+ (
36
+ mean("nominal_speed")
37
+ * 4.8
38
+ * mean("nominal_basic_weight")
39
+ * mean("nominal_efficiency")
40
+ ) / 100000000 AS ton_per_min
41
+ FROM miza_realtime
42
+ WHERE
43
+ line='Máy giấy PM3'
44
+ AND machine='Scanner'
45
+ AND time >= '{start_time}'
46
+ AND time <= '{end_time}'
47
+ GROUP BY time(1m)
48
+ )
49
+ """
50
+ result = self.query(query)
51
+ return result["results"][0]["series"][0]["values"][0][1]
52
+
53
+ def get_actual_production_daily(self, start_time: str, end_time: str):
54
+ query = f"""
55
+ SELECT integral("ton_per_min",1m)
56
+ FROM (
57
+ SELECT
58
+ (
59
+ mean("reel_speed")
60
+ * 4.8
61
+ * mean("basic_weight")
62
+ * 0.9
63
+ ) / 1000000 AS ton_per_min
64
+ FROM miza_realtime
65
+ WHERE
66
+ line='Máy giấy PM3'
67
+ AND machine='Scanner'
68
+ AND time >= '{start_time}'
69
+ AND time <= '{end_time}'
70
+ GROUP BY time(1m)
71
+ )
72
+ GROUP BY time(1d, 6h)
73
+ fill(none)
74
+ TZ('Asia/Ho_Chi_Minh')
75
+ """
76
+
77
+ result = self.query(query)
78
+ # {'results': [{'statement_id': 0}]}
79
+ if "series" in result["results"][0]:
80
+ return result["results"][0]["series"][0]["values"]
81
+ return []
82
+
83
+ def get_plan_production_daily(self, start_time: str, end_time: str):
84
+ query = f"""
85
+ SELECT integral("ton_per_min",1m)
86
+ FROM (
87
+ SELECT
88
+ (
89
+ mean("nominal_speed")
90
+ * 4.8
91
+ * mean("nominal_basic_weight")
92
+ * mean("nominal_efficiency")
93
+ ) / 100000000 AS ton_per_min
94
+ FROM miza_realtime
95
+ WHERE
96
+ line='Máy giấy PM3'
97
+ AND machine='Scanner'
98
+ AND time >= '{start_time}'
99
+ AND time <= '{end_time}'
100
+ GROUP BY time(1m)
101
+ )
102
+ GROUP BY time(1d, 6h)
103
+ fill(none)
104
+ TZ('Asia/Ho_Chi_Minh')
105
+ """
106
+
107
+ result = self.query(query)
108
+ if "series" in result["results"][0]:
109
+ return result["results"][0]["series"][0]["values"]
110
+ return []
@@ -0,0 +1,97 @@
1
+ from calendar import monthrange
2
+
3
+ from miza_datahub.influxdb.influx_repository import InfluxRepository
4
+
5
+
6
+ class PaperOEEQuery(InfluxRepository):
7
+ def get_daily_availability(self, date: str):
8
+ query = f"""
9
+ SELECT mean("A") FROM (
10
+ SELECT mean("b_status") * 100 as "A"
11
+ FROM "miza_realtime"
12
+ WHERE
13
+ ("machine"::tag = 'Động cơ D31')
14
+ AND time >= '{date}T06:00:00+07:00'
15
+ AND time <= '{date}T06:00:00+07:00' + 1d
16
+ GROUP BY time(1m) fill(null)
17
+ )
18
+ GROUP BY time(1d, 6h)
19
+ fill(none)
20
+ TZ('Asia/Ho_Chi_Minh')
21
+ """
22
+ result = self.query(query)
23
+ return result["results"][0]["series"][0]["values"]
24
+
25
+ def get_daily_performance_quality(self, date: str):
26
+ query = f"""
27
+ SELECT mean("P"), mean("Q")
28
+ FROM "paper_daily_oee"
29
+ WHERE
30
+ time >= '{date}T06:00:00+07:00'
31
+ AND time <= '{date}T06:00:00+07:00' + 1d
32
+ GROUP BY time(1m) fill(none)
33
+ """
34
+ result = self.query(query)
35
+ return result["results"][0]["series"][0]["values"]
36
+
37
+ def get_monthly_availability(self, year: int, month: int):
38
+ last_day = monthrange(year, month)[1]
39
+ query = f"""
40
+ SELECT mean("A") FROM (
41
+ SELECT mean("b_status") * 100 as "A"
42
+ FROM "miza_realtime"
43
+ WHERE
44
+ ("machine"::tag = 'Động cơ D31')
45
+ AND time >= '{year}-{month:02d}-01T06:00:00+07:00'
46
+ AND time <= '{year}-{month:02d}-{last_day}T06:00:00+07:00' + 1d
47
+ GROUP BY time(1m) fill(null)
48
+ )
49
+ GROUP BY time(4w, 6h)
50
+ fill(none)
51
+ TZ('Asia/Ho_Chi_Minh')
52
+ """
53
+ result = self.query(query)
54
+ return result["results"][0]["series"][0]["values"]
55
+
56
+ def get_monthly_performance_quality(self, year: int, month: int):
57
+ last_day = monthrange(year, month)[1]
58
+ query = f"""
59
+ SELECT mean("P"), mean("Q")
60
+ FROM "paper_daily_oee"
61
+ WHERE
62
+ time >= '{year}-{month:02d}-01T06:00:00+07:00'
63
+ AND time <= '{year}-{month:02d}-{last_day}T06:00:00+07:00' + 1d
64
+ TZ('Asia/Ho_Chi_Minh')
65
+ """
66
+ result = self.query(query)
67
+ return result["results"][0]["series"][0]["values"]
68
+
69
+ def get_yearly_availability(self, year: int):
70
+ query = f"""
71
+ SELECT mean("A") FROM (
72
+ SELECT mean("b_status") * 100 as "A"
73
+ FROM "miza_realtime"
74
+ WHERE
75
+ ("machine"::tag = 'Động cơ D31')
76
+ AND time >= '{year}-01-01T06:00:00+07:00'
77
+ AND time <= '{year+1}-01-01T06:00:00+07:00'
78
+ GROUP BY time(1m) fill(null)
79
+ )
80
+ GROUP BY time(52w, 6h)
81
+ fill(none)
82
+ TZ('Asia/Ho_Chi_Minh')
83
+ """
84
+ result = self.query(query)
85
+ return result["results"][0]["series"][0]["values"]
86
+
87
+ def get_yearly_performance_quality(self, year: int):
88
+ query = f"""
89
+ SELECT mean("P"), mean("Q")
90
+ FROM "paper_daily_oee"
91
+ WHERE
92
+ time >= '{year}-01-01T06:00:00+07:00'
93
+ AND time <= '{year+1}-01-01T06:00:00+07:00'
94
+ TZ('Asia/Ho_Chi_Minh')
95
+ """
96
+ result = self.query(query)
97
+ return result["results"][0]["series"][0]["values"]
@@ -0,0 +1,51 @@
1
+ from miza_datahub.influxdb.influx_repository import InfluxRepository
2
+
3
+
4
+ class ProductionTimeQuery(InfluxRepository):
5
+ def get_production_run_time(self, date: str, group_by: str):
6
+ query = f"""
7
+ SELECT sum("cnt")
8
+ FROM (
9
+ SELECT
10
+ last("b_run_2") / 2 AS "cnt"
11
+ FROM "miza_realtime"
12
+ WHERE
13
+ "machine" = 'Động cơ D31'
14
+ AND time >= '{date}T06:00:00+07:00'
15
+ AND time <= '{date}T06:00:00+07:00' + 1d
16
+ GROUP BY time(1m)
17
+ fill(0)
18
+ )
19
+ GROUP BY time({group_by}, 6h)
20
+ fill(none)
21
+ TZ('Asia/Ho_Chi_Minh')
22
+ """
23
+ result = self.query(query)
24
+ return result["results"][0]["series"][0]["values"]
25
+
26
+ def get_production_down_time(self, date: str, group_by: str):
27
+ product_time = ""
28
+ if group_by == "1d":
29
+ product_time = "1440"
30
+ elif group_by == "1h":
31
+ product_time = "60"
32
+
33
+ query = f"""
34
+ SELECT {product_time} - sum("cnt")
35
+ FROM (
36
+ SELECT
37
+ last("b_run_2") / 2 AS "cnt"
38
+ FROM "miza_realtime"
39
+ WHERE
40
+ "machine" = 'Động cơ D31'
41
+ AND time >= '{date}T06:00:00+07:00'
42
+ AND time <= '{date}T06:00:00+07:00' + 1d
43
+ GROUP BY time(1m)
44
+ fill(0)
45
+ )
46
+ GROUP BY time({group_by}, 6h)
47
+ fill(none)
48
+ TZ('Asia/Ho_Chi_Minh')
49
+ """
50
+ result = self.query(query)
51
+ return result["results"][0]["series"]["values"]
@@ -0,0 +1,80 @@
1
+ import pandas as pd
2
+
3
+ from miza_datahub.influxdb.influx_repository import InfluxRepository
4
+
5
+
6
+ class PaperDailyOEEWriter(InfluxRepository):
7
+ MEASUREMENT = "paper_daily_oee"
8
+
9
+ def write_apq(self, df):
10
+ lines = []
11
+ mapping = {
12
+ "Sản lượng": "actual",
13
+ "plan": "plan",
14
+ "Hàng lỗi": "defect",
15
+ "run_time": "run_time",
16
+ "ĐG + DM": "down_time",
17
+ "% Hiệu suất": "A",
18
+ "% SL": "P",
19
+ "% Chất lượng": "Q",
20
+ "OEE": "OEE",
21
+ }
22
+
23
+ for _, row in df.iterrows():
24
+ timestamp = int(row["production_day"].timestamp())
25
+
26
+ tags = [
27
+ f"factory={PaperDailyOEEWriter.escape_string('MIZA Nghi Sơn')}",
28
+ "line=PM3",
29
+ "machine=Scanner",
30
+ ]
31
+
32
+ values = [
33
+ f"{influx_field}={row[df_field]}"
34
+ for df_field, influx_field in mapping.items()
35
+ if pd.notna(row[df_field])
36
+ ]
37
+
38
+ line = (
39
+ f'{self.MEASUREMENT},{",".join(tags)} '
40
+ f'{",".join(values)} '
41
+ f"{timestamp}"
42
+ )
43
+
44
+ lines.append(line)
45
+
46
+ self.client.write("\n".join(lines))
47
+
48
+ def write_pq(self, df):
49
+ lines = []
50
+ mapping = {
51
+ "actual": "actual",
52
+ "plan": "plan",
53
+ "B": "defect",
54
+ "P": "P",
55
+ "Q": "Q",
56
+ }
57
+
58
+ for _, row in df.iterrows():
59
+ timestamp = int(row["production_day"].timestamp())
60
+
61
+ tags = [
62
+ f"factory={PaperDailyOEEWriter.escape_string('MIZA Nghi Sơn')}",
63
+ "line=PM3",
64
+ "machine=Scanner",
65
+ ]
66
+
67
+ values = [
68
+ f"{influx_field}={row[df_field]}"
69
+ for df_field, influx_field in mapping.items()
70
+ if pd.notna(row[df_field])
71
+ ]
72
+
73
+ line = (
74
+ f'{self.MEASUREMENT},{",".join(tags)} '
75
+ f'{",".join(values)} '
76
+ f"{timestamp}"
77
+ )
78
+ lines.append(line)
79
+
80
+ self.client.write("\n".join(lines))
@@ -0,0 +1,72 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ import requests
4
+
5
+ from miza_datahub.common.config_util import ConfigUtil
6
+ from miza_datahub.common import config_const as ConfigConst
7
+ from miza_datahub.influxdb.influx_rest_client import InfluxRestClient
8
+
9
+
10
+ class BaseReader(ABC):
11
+ def __init__(self, file_id=None, file_path=None):
12
+ config_util = ConfigUtil()
13
+
14
+ # Telegram
15
+ if file_id:
16
+ token = config_util.get_property(
17
+ section=ConfigConst.TELEGRAM, key=ConfigConst.TOKEN
18
+ )
19
+
20
+ r = requests.get(
21
+ ConfigConst.URL_GET_FILE_PATH.format(token=token),
22
+ params={"file_id": file_id},
23
+ ).json()
24
+ if not r.get("ok"):
25
+ raise ValueError(f"Telegram error: {r.get('description')}")
26
+
27
+ file_path = r["result"]["file_path"]
28
+
29
+ self.file_bytes = requests.get(
30
+ ConfigConst.URL_GET_FILE_CONTENT.format(
31
+ token=token, file_path=file_path
32
+ )
33
+ ).content
34
+
35
+ # file local
36
+ elif file_path:
37
+ with open(file_path, "rb") as f:
38
+ self.file_bytes = f.read()
39
+
40
+ # InfluxDB
41
+ influx_host = config_util.get_property(
42
+ section=ConfigConst.INFLUX,
43
+ key=ConfigConst.INFLUX_HOST,
44
+ default_val="192.168.10.2",
45
+ )
46
+ influx_port = config_util.get_int(
47
+ section=ConfigConst.INFLUX,
48
+ key=ConfigConst.INFLUX_PORT,
49
+ default_val=8090,
50
+ )
51
+ influx_db = config_util.get_property(
52
+ section=ConfigConst.INFLUX,
53
+ key=ConfigConst.INFLUX_DB,
54
+ default_val="miza_new",
55
+ )
56
+ self.influx = InfluxRestClient(influx_host, influx_port, influx_db)
57
+
58
+ @abstractmethod
59
+ def load(self):
60
+ pass
61
+
62
+ @abstractmethod
63
+ def write(self):
64
+ pass
65
+
66
+
67
+ class TempReader(BaseReader):
68
+ def load(self):
69
+ pass
70
+
71
+ def write(self):
72
+ pass
@@ -0,0 +1,71 @@
1
+ from io import BytesIO
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+
6
+ from miza_datahub.readers.base_reader import BaseReader
7
+ from miza_datahub.influxdb.writers.paper_daily_oee_writer import (
8
+ PaperDailyOEEWriter,
9
+ )
10
+
11
+
12
+ class OEEAnalyzer(BaseReader):
13
+ def load(self):
14
+ excel_file = pd.ExcelFile(BytesIO(self.file_bytes))
15
+ df_raw = pd.read_excel(
16
+ BytesIO(self.file_bytes), sheet_name="OEE", header=None
17
+ )
18
+
19
+ sheet_name = excel_file.sheet_names[0]
20
+ month_str, year_str = sheet_name.split(".")
21
+ month = int(month_str)
22
+ year = 2000 + int(year_str)
23
+
24
+ time_markers = df_raw.iloc[0, 2:].tolist()
25
+
26
+ timeline = []
27
+ for marker in time_markers:
28
+ current_day = int(marker)
29
+ full_timestamp = pd.to_datetime(
30
+ f"{current_day}/{month}/{year} 06:00", dayfirst=True
31
+ )
32
+ timeline.append(full_timestamp)
33
+
34
+ df_matrix = df_raw.iloc[1:10, 2:]
35
+ error_list = ["#DIV/0!", "#ERROR!", "#VALUE!", "#REF!", "#NAME?"]
36
+ df_matrix = df_matrix.replace(error_list, np.nan)
37
+
38
+ row_8_data = df_matrix.iloc[8]
39
+ clean_columns_condition = row_8_data.notna()
40
+
41
+ df_clean = df_matrix.loc[:, clean_columns_condition]
42
+ df_final = df_clean.T
43
+
44
+ df_final.index = timeline[: len(df_final.index)]
45
+ df_final.columns = [
46
+ "Sản lượng",
47
+ "Hàng lỗi",
48
+ "% Hàng lỗi",
49
+ "ĐG + DM",
50
+ "Rỗng",
51
+ "% SL",
52
+ "% Chất lượng",
53
+ "% Hiệu suất",
54
+ "OEE",
55
+ ]
56
+ df_final["plan"] = np.where(
57
+ df_final["% SL"] > 0,
58
+ df_final["Sản lượng"] / df_final["% SL"],
59
+ np.nan,
60
+ )
61
+ df_final["run_time"] = 1440 - df_final["ĐG + DM"]
62
+ df_final = df_final.reset_index().rename(
63
+ columns={"index": "production_day"}
64
+ )
65
+ self.df = df_final
66
+
67
+ def write(self):
68
+ self.load()
69
+ paper_oee = PaperDailyOEEWriter(self.influx)
70
+ paper_oee.write_apq(self.df)
71
+ return True
@@ -0,0 +1,140 @@
1
+ from io import BytesIO
2
+
3
+ # import numpy as np
4
+ import pandas as pd
5
+
6
+ from miza_datahub.readers.base_reader import BaseReader
7
+ from miza_datahub.influxdb.queries.paper_machine_query import (
8
+ PaperMachineRepository,
9
+ )
10
+ from miza_datahub.influxdb.writers.paper_daily_oee_writer import (
11
+ PaperDailyOEEWriter,
12
+ )
13
+ from miza_datahub.services.oee_service import OEEService
14
+
15
+
16
+ class QualityAnalyzer(BaseReader):
17
+ def load(self):
18
+ df = pd.read_excel(
19
+ BytesIO(self.file_bytes),
20
+ sheet_name="Chi_Tiet_Chat_Luong",
21
+ skiprows=5,
22
+ usecols="C:F,H:O,AA:AF,AO:AZ,BB:BF",
23
+ names=[
24
+ "Ngày SX",
25
+ "Loại Giấy",
26
+ "Khách hàng",
27
+ "Trưởng ca",
28
+ "Mã cuộn",
29
+ "Ngày cắt cuộn",
30
+ "Giờ ra quả Xeo",
31
+ "Khổ giấy (cm)",
32
+ "Tổng khổ (cm)",
33
+ "Định lượng YC (g/m2)",
34
+ "Định lượng TB (g/m2)",
35
+ "Định lượng TT (g/m2)",
36
+ "Số vết nối TT",
37
+ "Số vết nối YC",
38
+ "Độ bục TB",
39
+ "Cường độ bục TT",
40
+ "Độ bục YC",
41
+ "Cường độ bục YC",
42
+ "Độ nhẵn (s)",
43
+ "Chống thấm YC",
44
+ "Chiều dài cuộn (m)",
45
+ "Chiều dài cuộn theo CT",
46
+ "Đánh giá chiều dài cuộn",
47
+ "Trọng lượng (kg)",
48
+ "Người đóng gói",
49
+ "Nhân viên QC",
50
+ "Độ dương khổ (mm)",
51
+ "Đường kính quả",
52
+ "Ghi Chú",
53
+ "Mã quả Xeo",
54
+ "Loại CL",
55
+ "Chỉ số màu L*",
56
+ "Chỉ số màu a*",
57
+ "Chỉ số màu b*",
58
+ "Loại SP",
59
+ ],
60
+ )
61
+
62
+ # 1. Chuẩn hóa giờ: đổi ; thành :
63
+ df["Giờ ra quả Xeo"] = (
64
+ df["Giờ ra quả Xeo"].astype(str).str.replace(";", ":", regex=False)
65
+ )
66
+
67
+ # 2. Loại bỏ NaN / NaT / chuỗi lỗi
68
+ df = df[df["Giờ ra quả Xeo"].notna()]
69
+ df = df[df["Giờ ra quả Xeo"].str.lower() != "nat"]
70
+
71
+ # 3. Tạo datetime
72
+ df["Thời điểm ra quả xeo"] = pd.to_datetime(
73
+ df["Ngày SX"].astype(str) + " " + df["Giờ ra quả Xeo"],
74
+ errors="coerce",
75
+ )
76
+
77
+ # 4. Loại bỏ dòng parse lỗi lần cuối
78
+ df = df.dropna(subset=["Thời điểm ra quả xeo"])
79
+
80
+ df = df.set_index(["Thời điểm ra quả xeo", "Mã cuộn", "Ngày cắt cuộn"])
81
+ # df["Mã quả Xeo"] = df["Mã quả Xeo"].astype(np.uint32)
82
+ self.df = df
83
+
84
+ def write(self):
85
+ self.load()
86
+ df_quality = self.calculate_defect_weight()
87
+
88
+ paper = PaperMachineRepository(self.influx)
89
+ paper_oee = PaperDailyOEEWriter(self.influx)
90
+
91
+ actual = paper.get_actual_production_daily(
92
+ start_time=(df_quality["production_day"].min()).strftime(
93
+ "%Y-%m-%dT00:00:00Z"
94
+ ),
95
+ end_time=(
96
+ df_quality["production_day"].max() + pd.Timedelta(days=1)
97
+ ).strftime("%Y-%m-%dT00:00:00Z"),
98
+ )
99
+
100
+ plan = paper.get_plan_production_daily(
101
+ start_time=(df_quality["production_day"].min()).strftime(
102
+ "%Y-%m-%dT00:00:00Z"
103
+ ),
104
+ end_time=(
105
+ df_quality["production_day"].max() + pd.Timedelta(days=1)
106
+ ).strftime("%Y-%m-%dT00:00:00Z"),
107
+ )
108
+ df_final = OEEService.calculate_pq(actual, plan, df_quality)
109
+ paper_oee.write_pq(df_final)
110
+ return True
111
+
112
+ def calculate_defect_weight(self):
113
+ time_idx = self.df.index.get_level_values("Thời điểm ra quả xeo")
114
+ quality_df = (
115
+ self.df.assign(
116
+ production_day=(time_idx - pd.Timedelta(hours=6)).floor("D")
117
+ )
118
+ .groupby(["production_day", "Loại CL"])["Trọng lượng (kg)"]
119
+ .sum()
120
+ .unstack(fill_value=0)
121
+ )
122
+
123
+ quality_df = quality_df.reset_index()
124
+ # quality_df["scrap_kg"] = quality_df.get("B", 0)
125
+ # quality_df["good_kg"] = quality_df.get("A", 0)
126
+ # print(quality_df)
127
+ return quality_df
128
+
129
+ def summarize_columns(self):
130
+ print(f"{'Column':35} {'Type':15} {'Unique':>10} {'Memory(MB)':>12}")
131
+ print("-" * 75)
132
+
133
+ for c in self.df.columns:
134
+ print(
135
+ f"{c:35} "
136
+ f"{str(self.df[c].dtype):15} "
137
+ f"{self.df[c].nunique(dropna=False):>10,} "
138
+ f"{self.df[c].memory_usage(deep=True)/1024**2:>12.2f}"
139
+ )
140
+ self.df.info(memory_usage="deep")
@@ -0,0 +1,44 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+
4
+
5
+ class OEEService:
6
+ @staticmethod
7
+ def production_dataframe(data: list, value_column: str) -> pd.DataFrame:
8
+ if not data:
9
+ return pd.DataFrame(columns=["production_day", value_column])
10
+ df = pd.DataFrame(data, columns=["time", value_column])
11
+ df["production_day"] = (
12
+ pd.to_datetime(df["time"]).dt.tz_localize(None).dt.normalize()
13
+ )
14
+ return df[["production_day", value_column]]
15
+
16
+ @staticmethod
17
+ def calculate_pq(actual, plan, df_quality):
18
+ df_actual = OEEService.production_dataframe(actual, "actual")
19
+ df_plan = OEEService.production_dataframe(plan, "plan")
20
+
21
+ if df_quality is not None:
22
+ df_quality = pd.DataFrame(columns=["production_day", "B"])
23
+
24
+ df_final = df_actual.merge(
25
+ df_quality[["production_day", "B"]],
26
+ on="production_day",
27
+ how="outer",
28
+ ).merge(df_plan, on="production_day", how="left")
29
+
30
+ if df_final.empty:
31
+ return pd.DataFrame(
32
+ columns=["production_day", "actual", "plan", "B", "P", "Q"]
33
+ )
34
+
35
+ df_final["P"] = (df_final["actual"] / df_final["plan"] * 100).round(2)
36
+ df_final["Q"] = (
37
+ (df_final["actual"] - df_final["B"] / 1000)
38
+ / df_final["actual"]
39
+ * 100
40
+ ).round(2)
41
+ df_final = df_final.replace([np.inf, -np.inf], np.nan)
42
+ df_final = df_final.astype(object)
43
+ df_final = df_final.where(pd.notnull(df_final), None)
44
+ return df_final
@@ -0,0 +1,36 @@
1
+ from io import BytesIO
2
+
3
+ import pandas as pd
4
+
5
+ from miza_datahub.readers.base_reader import TempReader
6
+ from miza_datahub.readers.oee_analyzer import OEEAnalyzer
7
+ from miza_datahub.readers.quality_analyzer import (
8
+ QualityAnalyzer,
9
+ )
10
+
11
+
12
+ def detect_file_types(file_bytes):
13
+ excel = pd.ExcelFile(BytesIO(file_bytes))
14
+ sheets = excel.sheet_names
15
+
16
+ if "OEE" in sheets:
17
+ return "oee"
18
+
19
+ if "Chi_Tiet_Chat_Luong" in sheets:
20
+ return "quality"
21
+
22
+ return ValueError(f"Don't read file. Sheets={sheets}")
23
+
24
+
25
+ class ReaderFactory:
26
+ @staticmethod
27
+ def create(file_id=None, file_path=None):
28
+ base = TempReader(file_id=file_id, file_path=file_path)
29
+
30
+ file_type = detect_file_types(base.file_bytes)
31
+
32
+ if file_type == "oee":
33
+ return OEEAnalyzer(file_id=file_id, file_path=file_path)
34
+
35
+ if file_type == "quality":
36
+ return QualityAnalyzer(file_id=file_id, file_path=file_path)
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: miza-datahub
3
+ Version: 1.0.0
4
+ Summary: This package does amazing things.
5
+ Home-page: http://github.com/chanelcolgate/miza-datahub
6
+ Author: chanelcolgate
7
+ Author-email: "chanelcolgate" <github@chanelcolgate.com>
8
+ License: MIT
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy
13
+ Requires-Dist: pandas
14
+ Requires-Dist: requests
15
+ Requires-Dist: openpyxl
16
+ Dynamic: license-file
17
+
18
+ ## Miza DataHub Library
19
+ ### How to install
20
+ - Cài pip
21
+ ```bash
22
+ pip install --upgrade pip setuptools wheel
23
+ ```
24
+ - Cách khác
25
+ ```bash
26
+ python -m ensurepip --upgrade
27
+ ```
28
+ - Cách cài đặt và chạy
29
+ ```
30
+ pyproject-build
31
+ python -m pip install -e .
32
+ ```
33
+ - Cách test
34
+ ```
35
+ python -m pip install pytest
36
+ python -m pytest
37
+ python -m pip install mypy
38
+ python -m mypy
39
+ python -m pip install tox
40
+ tox -e typecheck
41
+ tox -e lint
42
+ ```
@@ -0,0 +1,56 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.cfg
6
+ src/logic.egg-info/PKG-INFO
7
+ src/logic.egg-info/SOURCES.txt
8
+ src/logic.egg-info/dependency_links.txt
9
+ src/logic.egg-info/top_level.txt
10
+ src/miza_datahub/__init__.py
11
+ src/miza_datahub.egg-info/PKG-INFO
12
+ src/miza_datahub.egg-info/SOURCES.txt
13
+ src/miza_datahub.egg-info/dependency_links.txt
14
+ src/miza_datahub.egg-info/requires.txt
15
+ src/miza_datahub.egg-info/top_level.txt
16
+ src/miza_datahub/__pycache__/__init__.cpython-311.pyc
17
+ src/miza_datahub/common/__init__.py
18
+ src/miza_datahub/common/config_const.py
19
+ src/miza_datahub/common/config_util.py
20
+ src/miza_datahub/common/singleton.py
21
+ src/miza_datahub/common/__pycache__/__init__.cpython-311.pyc
22
+ src/miza_datahub/common/__pycache__/config_const.cpython-311.pyc
23
+ src/miza_datahub/common/__pycache__/config_util.cpython-311.pyc
24
+ src/miza_datahub/common/__pycache__/singleton.cpython-311.pyc
25
+ src/miza_datahub/influxdb/__init__.py
26
+ src/miza_datahub/influxdb/influx_repository.py
27
+ src/miza_datahub/influxdb/influx_rest_client.py
28
+ src/miza_datahub/influxdb/__pycache__/__init__.cpython-311.pyc
29
+ src/miza_datahub/influxdb/__pycache__/influx_repository.cpython-311.pyc
30
+ src/miza_datahub/influxdb/__pycache__/influx_rest_client.cpython-311.pyc
31
+ src/miza_datahub/influxdb/queries/__init__.py
32
+ src/miza_datahub/influxdb/queries/paper_machine_query.py
33
+ src/miza_datahub/influxdb/queries/paper_oee_query.py
34
+ src/miza_datahub/influxdb/queries/production_time_query.py
35
+ src/miza_datahub/influxdb/queries/__pycache__/__init__.cpython-311.pyc
36
+ src/miza_datahub/influxdb/queries/__pycache__/paper_machine_query.cpython-311.pyc
37
+ src/miza_datahub/influxdb/queries/__pycache__/paper_oee_query.cpython-311.pyc
38
+ src/miza_datahub/influxdb/writers/__init__.py
39
+ src/miza_datahub/influxdb/writers/paper_daily_oee_writer.py
40
+ src/miza_datahub/influxdb/writers/__pycache__/__init__.cpython-311.pyc
41
+ src/miza_datahub/influxdb/writers/__pycache__/paper_daily_oee_writer.cpython-311.pyc
42
+ src/miza_datahub/readers/__init__.py
43
+ src/miza_datahub/readers/base_reader.py
44
+ src/miza_datahub/readers/oee_analyzer.py
45
+ src/miza_datahub/readers/quality_analyzer.py
46
+ src/miza_datahub/readers/__pycache__/__init__.cpython-311.pyc
47
+ src/miza_datahub/readers/__pycache__/base_reader.cpython-311.pyc
48
+ src/miza_datahub/readers/__pycache__/finished_product_quality_analyzer.cpython-311.pyc
49
+ src/miza_datahub/readers/__pycache__/oee_analyzer.cpython-311.pyc
50
+ src/miza_datahub/readers/__pycache__/quality_analyzer.cpython-311.pyc
51
+ src/miza_datahub/services/__init__.py
52
+ src/miza_datahub/services/oee_service.py
53
+ src/miza_datahub/services/reader_factory.py
54
+ src/miza_datahub/services/__pycache__/__init__.cpython-311.pyc
55
+ src/miza_datahub/services/__pycache__/oee_service.cpython-311.pyc
56
+ src/miza_datahub/services/__pycache__/reader_factory.cpython-311.pyc
@@ -0,0 +1,4 @@
1
+ numpy
2
+ pandas
3
+ requests
4
+ openpyxl
@@ -0,0 +1 @@
1
+ miza_datahub