|
|
|
@@ -3,6 +3,7 @@ import sys
|
|
|
|
|
|
|
|
|
|
import psycopg2
|
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
from influxdb_client_3 import InfluxDBClient3
|
|
|
|
|
from neo4j import GraphDatabase
|
|
|
|
|
from psycopg2 import sql
|
|
|
|
|
from psycopg2.errors import DuplicateDatabase
|
|
|
|
@@ -30,6 +31,11 @@ AGE_PORT = os.getenv("AGE_PORT", POSTGRES_PORT)
|
|
|
|
|
AGE_DB = os.getenv("AGE_DB", POSTGRES_DB)
|
|
|
|
|
AGE_GRAPH_NAME = os.getenv("AGE_GRAPH_NAME", "movie_graph")
|
|
|
|
|
|
|
|
|
|
INFLUX_ACTIVE = os.getenv("INFLUX_ACTIVE", "false").lower() == "true"
|
|
|
|
|
INFLUXDB3_HOST = os.getenv("INFLUXDB3_HOST", "http://localhost:8181")
|
|
|
|
|
INFLUXDB3_AUTH_TOKEN = os.getenv("INFLUXDB3_AUTH_TOKEN")
|
|
|
|
|
INFLUXDB3_DATABASE = os.getenv("INFLUXDB3_DATABASE", "sensors")
|
|
|
|
|
|
|
|
|
|
USER_SEED_DATA = [
|
|
|
|
|
(1, "Ivan", 15),
|
|
|
|
|
(2, "Igor", 22),
|
|
|
|
@@ -154,6 +160,48 @@ def select_age_movies(cur):
|
|
|
|
|
return [str(row[0]).strip('"') for row in cur.fetchall()]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def connect_influx():
|
|
|
|
|
return InfluxDBClient3(
|
|
|
|
|
host=INFLUXDB3_HOST,
|
|
|
|
|
token=INFLUXDB3_AUTH_TOKEN,
|
|
|
|
|
database=INFLUXDB3_DATABASE,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def insert_influx_sensor_data(client):
|
|
|
|
|
client.write(
|
|
|
|
|
"""temperature,location=room1,sensor_id=s01 value=22.5
|
|
|
|
|
temperature,location=room2,sensor_id=s02 value=24.1
|
|
|
|
|
temperature,location=room1,sensor_id=s01 value=23.0
|
|
|
|
|
humidity,location=room1,sensor_id=s01 value=55.2
|
|
|
|
|
humidity,location=room2,sensor_id=s02 value=60.8"""
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def select_influx_sensor_data(client):
|
|
|
|
|
table = client.query(
|
|
|
|
|
query="""
|
|
|
|
|
SELECT measurement, location, sensor_id, value, CAST(time AS STRING) AS time
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT 'temperature' AS measurement, location, sensor_id, value, time FROM temperature
|
|
|
|
|
UNION ALL
|
|
|
|
|
SELECT 'humidity' AS measurement, location, sensor_id, value, time FROM humidity
|
|
|
|
|
)
|
|
|
|
|
ORDER BY time, measurement
|
|
|
|
|
""",
|
|
|
|
|
language="sql",
|
|
|
|
|
mode="all",
|
|
|
|
|
)
|
|
|
|
|
rows = table.to_pylist()
|
|
|
|
|
|
|
|
|
|
if not rows:
|
|
|
|
|
return ["measurement", "location", "sensor_id", "value", "time"], []
|
|
|
|
|
|
|
|
|
|
headers = list(rows[0].keys())
|
|
|
|
|
values = [tuple(row.get(header) for header in headers) for row in rows]
|
|
|
|
|
return headers, values
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_users():
|
|
|
|
|
admin_conn = connect_postgres("postgres")
|
|
|
|
|
try:
|
|
|
|
@@ -180,7 +228,7 @@ class MainWindow(QMainWindow):
|
|
|
|
|
central_widget = QWidget(self)
|
|
|
|
|
self.setCentralWidget(central_widget)
|
|
|
|
|
|
|
|
|
|
grid_layout = QGridLayout(self)
|
|
|
|
|
grid_layout = QGridLayout()
|
|
|
|
|
central_widget.setLayout(grid_layout)
|
|
|
|
|
|
|
|
|
|
self.table = QTableWidget(self)
|
|
|
|
@@ -206,40 +254,49 @@ class MainWindow(QMainWindow):
|
|
|
|
|
self.table.resizeColumnsToContents()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GraphWindow(QWidget):
|
|
|
|
|
def __init__(self, title, parent_window):
|
|
|
|
|
class DataWindow(QWidget):
|
|
|
|
|
def __init__(self, title, headers, parent_window, window_index=0):
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
|
|
self.setWindowTitle(title)
|
|
|
|
|
self.parent_window = parent_window
|
|
|
|
|
self.window_index = window_index
|
|
|
|
|
|
|
|
|
|
grid_layout = QGridLayout(self)
|
|
|
|
|
self.setLayout(grid_layout)
|
|
|
|
|
|
|
|
|
|
self.table = QTableWidget(self)
|
|
|
|
|
self.table.setColumnCount(1)
|
|
|
|
|
self.table.setColumnCount(len(headers))
|
|
|
|
|
self.table.setRowCount(0)
|
|
|
|
|
self.table.setHorizontalHeaderLabels(["Info"])
|
|
|
|
|
self.table.horizontalHeaderItem(0).setToolTip("Info")
|
|
|
|
|
self.table.horizontalHeaderItem(0).setTextAlignment(Qt.AlignHCenter)
|
|
|
|
|
self.table.setHorizontalHeaderLabels(headers)
|
|
|
|
|
for index, header in enumerate(headers):
|
|
|
|
|
self.table.horizontalHeaderItem(index).setToolTip(header)
|
|
|
|
|
self.table.horizontalHeaderItem(index).setTextAlignment(Qt.AlignHCenter)
|
|
|
|
|
|
|
|
|
|
grid_layout.addWidget(self.table, 0, 0)
|
|
|
|
|
self.position_relative_to_parent(parent_window)
|
|
|
|
|
self.position_relative_to_parent()
|
|
|
|
|
|
|
|
|
|
def position_relative_to_parent(self, parent_window):
|
|
|
|
|
parent_frame = parent_window.frameGeometry()
|
|
|
|
|
self.move(parent_frame.x() + parent_frame.width() + 5, parent_frame.y())
|
|
|
|
|
def position_relative_to_parent(self):
|
|
|
|
|
parent = self.parent_window.frameGeometry()
|
|
|
|
|
screen = QApplication.primaryScreen().availableGeometry()
|
|
|
|
|
self.move(
|
|
|
|
|
max(screen.x(), min(parent.right() + 6 + self.window_index * (self.width() + 5), screen.right() - self.width() - 10)),
|
|
|
|
|
max(screen.y(), min(parent.y(), screen.bottom() - self.height() - 10)),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def load_data(self, rows):
|
|
|
|
|
self.table.setRowCount(len(rows))
|
|
|
|
|
for row_number, item in enumerate(rows):
|
|
|
|
|
self.table.setItem(row_number, 0, QTableWidgetItem(str(item)))
|
|
|
|
|
for row_number, row in enumerate(rows):
|
|
|
|
|
values = row if isinstance(row, (list, tuple)) else [row]
|
|
|
|
|
for column_number, value in enumerate(values):
|
|
|
|
|
self.table.setItem(row_number, column_number, QTableWidgetItem(str(value)))
|
|
|
|
|
self.table.resizeColumnsToContents()
|
|
|
|
|
self.table.resizeRowsToContents()
|
|
|
|
|
|
|
|
|
|
margins = self.layout().contentsMargins()
|
|
|
|
|
width = (
|
|
|
|
|
self.table.verticalHeader().width()
|
|
|
|
|
+ self.table.columnWidth(0)
|
|
|
|
|
+ sum(self.table.columnWidth(column) for column in range(self.table.columnCount()))
|
|
|
|
|
+ self.table.frameWidth() * 2
|
|
|
|
|
+ margins.left()
|
|
|
|
|
+ margins.right()
|
|
|
|
@@ -254,7 +311,11 @@ class GraphWindow(QWidget):
|
|
|
|
|
+ 24
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.resize(min(max(width, 220), 700), min(max(height, 120), 500))
|
|
|
|
|
screen_geometry = QApplication.primaryScreen().availableGeometry()
|
|
|
|
|
max_width = max(screen_geometry.width() - 40, 220)
|
|
|
|
|
max_height = max(screen_geometry.height() - 40, 120)
|
|
|
|
|
self.resize(min(max(width, 220), max_width), min(max(height, 120), max_height))
|
|
|
|
|
self.position_relative_to_parent()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
@@ -269,8 +330,8 @@ if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
if NEO_ACTIVE:
|
|
|
|
|
try:
|
|
|
|
|
neo_window = GraphWindow("neo4j", main_window)
|
|
|
|
|
neo_window.load_data(fetch_neo_movies())
|
|
|
|
|
neo_window = DataWindow("neo4j", ["Info"], main_window, len(graph_windows))
|
|
|
|
|
neo_window.load_data([(title,) for title in fetch_neo_movies()])
|
|
|
|
|
neo_window.show()
|
|
|
|
|
graph_windows.append(neo_window)
|
|
|
|
|
except Exception as error:
|
|
|
|
@@ -291,11 +352,24 @@ if __name__ == "__main__":
|
|
|
|
|
create_age_movies(cur)
|
|
|
|
|
age_movies = select_age_movies(cur)
|
|
|
|
|
|
|
|
|
|
age_window = GraphWindow("apache age", main_window)
|
|
|
|
|
age_window.load_data(age_movies)
|
|
|
|
|
age_window = DataWindow("apache age", ["Info"], main_window, len(graph_windows))
|
|
|
|
|
age_window.load_data([(title,) for title in age_movies])
|
|
|
|
|
age_window.show()
|
|
|
|
|
graph_windows.append(age_window)
|
|
|
|
|
except Exception as error:
|
|
|
|
|
print(f"Apache AGE load failed: {error}")
|
|
|
|
|
|
|
|
|
|
if INFLUX_ACTIVE:
|
|
|
|
|
try:
|
|
|
|
|
with connect_influx() as influx_client:
|
|
|
|
|
insert_influx_sensor_data(influx_client)
|
|
|
|
|
influx_headers, influx_rows = select_influx_sensor_data(influx_client)
|
|
|
|
|
|
|
|
|
|
influx_window = DataWindow("influxdb 3 core", influx_headers, main_window, len(graph_windows))
|
|
|
|
|
influx_window.load_data(influx_rows)
|
|
|
|
|
influx_window.show()
|
|
|
|
|
graph_windows.append(influx_window)
|
|
|
|
|
except Exception as error:
|
|
|
|
|
print(f"InfluxDB 3 Core load failed: {error}")
|
|
|
|
|
|
|
|
|
|
sys.exit(app.exec())
|