Teapack1 commited on
Commit
b52caaa
1 Parent(s): 9f96bc1

Upload 8 files

Browse files
Files changed (8) hide show
  1. app.py +77 -0
  2. camesa.py +30 -0
  3. config.py +3 -0
  4. device_blueprints.py +85 -0
  5. device_core.py +156 -0
  6. device_routes.py +20 -0
  7. models.py +27 -0
  8. requirements.txt +6 -0
app.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify, Response
2
+ from flask_bootstrap import Bootstrap
3
+ from flask_sqlalchemy import SQLAlchemy
4
+ from datetime import datetime
5
+ import json
6
+ import plotly
7
+ import requests
8
+ from device_core import Camera, Sensor
9
+ from models import init_db, Device
10
+ from device_routes import SENSORS, CAMERAS, LIGHTING_DATA
11
+ from config import Config
12
+ from flask import Flask, render_template, jsonify
13
+ from device_blueprints import sensor_blueprint, camera_blueprint
14
+
15
+ app = Flask(__name__)
16
+ app.config.from_object(Config)
17
+ Bootstrap(app)
18
+ init_db(app)
19
+
20
+ # from main import app, db, Device
21
+ # app.app_context().push()
22
+ # db.create_all()
23
+
24
+ app.register_blueprint(sensor_blueprint, url_prefix='/sensors')
25
+ app.register_blueprint(camera_blueprint, url_prefix='/cameras')
26
+
27
+ # ---------------------------------------------------------------------------------------------
28
+
29
+ @app.route('/')
30
+ def home():
31
+ # Filter sensors based on their types
32
+ thermo = [sensor for sensor in SENSORS if sensor.id.startswith('t')]
33
+ ele = [sensor for sensor in SENSORS if sensor.id.startswith('e')]
34
+
35
+ # Render the index template with the plot data and sensor lists
36
+ return render_template('index.html', thermo=thermo, ele=ele, cameras=CAMERAS)
37
+
38
+
39
+ @app.route('/lighting-data/', methods=['POST', 'GET'])
40
+ def receive_data():
41
+ global LIGHTING_DATA
42
+ print(LIGHTING_DATA)
43
+
44
+ try:
45
+ if request.method == 'POST':
46
+ address_value = request.json.get('address')
47
+ intensity_value = request.json.get('value')
48
+
49
+ if intensity_value is None:
50
+ return jsonify({"error": "Value not provided"}), 400
51
+ if address_value is None:
52
+ return jsonify({"error": "Address not provided"}), 400
53
+ address_value = int(address_value)
54
+
55
+ LIGHTING_DATA[address_value] = intensity_value
56
+
57
+ response = requests.post(f"http://127.0.0.1:1880/", json={"daliData_flask":[address_value, intensity_value]}, timeout=1)
58
+ response.raise_for_status()
59
+
60
+ return jsonify({"address": address_value, "value": intensity_value}), 200
61
+
62
+ elif request.method == 'GET':
63
+ address_value = request.args.get('address')
64
+ if not address_value:
65
+ return jsonify({"error": "Address not provided"}), 400
66
+ address_value = int(address_value)
67
+ intensity_value = LIGHTING_DATA.get(address_value, 0)
68
+
69
+ return jsonify({"address": address_value, "value": intensity_value}), 200
70
+
71
+ except requests.RequestException as e:
72
+ print("debug")
73
+ return jsonify({"error": str(e)}), 500
74
+
75
+
76
+ if __name__ == '__main__':
77
+ app.run(host='localhost', port=5000, debug=True)
camesa.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+
3
+ # Replace with your camera's RTSP URL
4
+ rtsp_url = 'rtsp://169.254.0.99:554/live.sdp'
5
+ rtsp_url = 0
6
+
7
+ # Create a VideoCapture object
8
+ cap = cv2.VideoCapture(rtsp_url)
9
+
10
+ while True:
11
+ # Capture frame-by-frame
12
+ ret, frame = cap.read()
13
+
14
+ # If frame is read correctly, ret is True
15
+ if not ret:
16
+ print("Can't receive frame (stream end?). Exiting ...")
17
+ break
18
+
19
+ # Display the resulting frame
20
+ cv2.imshow('IP Camera stream', frame)
21
+
22
+ # Press 'q' on keyboard to exit
23
+ if cv2.waitKey(1) == ord('q'):
24
+ break
25
+
26
+ # When everything done, release the VideoCapture object
27
+ cap.release()
28
+
29
+ # Close all OpenCV windows
30
+ cv2.destroyAllWindows()
config.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ class Config:
2
+ SQLALCHEMY_DATABASE_URI = 'sqlite:///devices.db'
3
+ # Other configurations
device_blueprints.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, render_template, jsonify, request, Response
2
+ from models import Device, db # Assuming Device is your database model from models.py
3
+ from device_core import Sensor, Camera # Import your Sensor class
4
+ from device_routes import SENSORS, CAMERAS # Import your SENSORS list
5
+ import json
6
+ import plotly
7
+
8
+ sensor_blueprint = Blueprint('sensor_blueprint', __name__, template_folder='templates')
9
+ camera_blueprint = Blueprint('camera_blueprint', __name__, template_folder='templates')
10
+
11
+ @sensor_blueprint.route('/plot/<sensor_id>')
12
+ def generate_plot(sensor_id):
13
+ sensor = Sensor.find(SENSORS, sensor_id) # Assuming SENSORS is accessible here
14
+ if not sensor:
15
+ return jsonify({"error": "Sensor not found"}), 404
16
+
17
+ fig = sensor.plot(Device, title=sensor.name)
18
+ return json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
19
+
20
+
21
+ @sensor_blueprint.route('/postplain/', methods=['POST'])
22
+ def post_plain():
23
+ data = request.get_json()
24
+ if not data:
25
+ return jsonify({'message': 'No input data provided'}), 400
26
+
27
+ device_id = data.get('id')
28
+ device_values = data.get('values')
29
+ device_units = data.get('units')
30
+
31
+ if device_values and device_id:
32
+ sensor = Sensor.find(SENSORS, device_id)
33
+ if sensor:
34
+ sensor.update_values(device_values, device_units)
35
+
36
+ device = Device(
37
+ sensor_id=device_id,
38
+ name=sensor.name,
39
+ time=sensor.time,
40
+ )
41
+
42
+ for i, value in enumerate(sensor.values):
43
+ setattr(device, f"value{i + 1}", value)
44
+ for i, unit in enumerate(sensor.units):
45
+ setattr(device, f"unit{i + 1}", unit)
46
+
47
+ db.session.add(device)
48
+ db.session.commit()
49
+
50
+ return jsonify({'message': 'Success!'}), 200
51
+ else:
52
+ return jsonify({'message': 'Sensor not found'}), 404
53
+ else:
54
+ return jsonify({'message': 'Missing data'}), 400
55
+
56
+
57
+ # -------------- CAMERA ROUTES --------------
58
+
59
+
60
+ @camera_blueprint.route('/video_feed/<camera_id>')
61
+ def stream_camera(camera_id):
62
+ """
63
+ Stream the video feed from a specific camera.
64
+ """
65
+ camera = next((cam for cam in CAMERAS if cam.id == camera_id), None)
66
+ if not camera:
67
+ return Response("Camera not found or could not be opened", status=404)
68
+
69
+ return Response(camera.gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
70
+
71
+
72
+ @camera_blueprint.route('/refresh_camera')
73
+ def refresh_camera():
74
+ success = True
75
+ message = "All cameras refreshed successfully."
76
+
77
+ for cam in CAMERAS:
78
+ cam.close_camera()
79
+ try:
80
+ cam.__init__(cam.id, cam.name, cam.index)
81
+ except:
82
+ success = False
83
+ message = "Error occurred while refreshing cameras."
84
+
85
+ return jsonify({"success": success, "message": message})
device_core.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ from datetime import datetime, timedelta
3
+ from plotly.subplots import make_subplots
4
+ import plotly.graph_objects as go
5
+ import threading
6
+ import os
7
+ import time
8
+
9
+ class Camera:
10
+ def __init__(self, id, name, index=0, fps=1, save_duration=0.1, rtsp=None):
11
+ self.name = name
12
+ self.id = id
13
+ self.fps = fps
14
+ self.save_duration = save_duration
15
+ self.index = rtsp if rtsp else index
16
+
17
+ # Initialize camera in a separate thread to avoid blocking
18
+ self.out = None
19
+ self.cap = None
20
+ self.frame_width = 1980
21
+ self.frame_height = 720
22
+ self.frame_count = 0
23
+ self.start_time = time.time()
24
+ self.initialization_thread = threading.Thread(target=self.initialize_camera)
25
+ self.initialization_thread.start()
26
+
27
+ def initialize_camera(self):
28
+ self.cap = cv2.VideoCapture(self.index)
29
+ self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.frame_width)
30
+ self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.frame_height)
31
+ self.cap.set(cv2.CAP_PROP_FPS, self.fps)
32
+
33
+ # Wait for camera to open or timeout after 10 seconds
34
+ start_time = time.time()
35
+ while not self.cap.isOpened():
36
+ time.sleep(0.1)
37
+ if time.time() - start_time > 10: # 10 seconds timeout
38
+ print(f"Timeout: Unable to open camera {self.id} - {self.name}")
39
+ break
40
+
41
+
42
+ def save_frame(self, frame):
43
+ filename = "video/frames/frame_{}.jpg".format(self.frame_count)
44
+ cv2.imwrite(filename, frame)
45
+ self.frame_count += 1
46
+
47
+ def create_video_from_frames(self):
48
+ filename = "video/outpy_{}.mp4".format(time.strftime("%Y%m%d-%H%M%S"))
49
+ self.out = cv2.VideoWriter(filename, cv2.VideoWriter_fourcc(*'mp4v'), self.fps, (self.frame_width, self.frame_height))
50
+ for i in range(self.frame_count):
51
+ frame = cv2.imread("video/frames/frame_{}.jpg".format(i))
52
+ self.out.write(frame)
53
+ os.remove("video/frames/frame_{}.jpg".format(i))
54
+ self.out.release()
55
+ self.frame_count = 0
56
+
57
+ def gen_frames(self):
58
+ i = 0
59
+ if not self.cap or not self.cap.isOpened():
60
+ yield b'' # Return empty bytes if camera is not available
61
+ return
62
+ while True:
63
+ success, frame = self.cap.read()
64
+ if not success:
65
+ break
66
+ else:
67
+ if i % 20 == 0:
68
+ self.save_frame(frame)
69
+ ret, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 100])
70
+ frame = buffer.tobytes()
71
+ yield (b'--frame\r\n'
72
+ b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
73
+ i += 1
74
+ if time.time() - self.start_time > self.save_duration * 3600:
75
+ self.create_video_from_frames()
76
+ self.start_time = time.time()
77
+
78
+ def close_camera(self):
79
+ try:
80
+ self.cap.release()
81
+ except: print("No camera to release")
82
+ try:
83
+ self.out.release()
84
+ except: print("No video to release")
85
+
86
+
87
+ class Sensor:
88
+ def __init__(self, id, name):
89
+ self.id = id
90
+ self.name = name
91
+ self.time = datetime.now()
92
+ self.measurement = ["Spotřeba","Napětí","Výkon","Teplota","Vlhkost","Vlhkost"]
93
+ self.values = [12,None,50,None,None,None] # store sensor values in a dictionary
94
+ self.units = ["A","V","D",None,None,None] # store sensor units in a dictionary
95
+
96
+ def update_values(self, data, units):
97
+ self.values = [round(float(d), 4) for d in data]
98
+ self.units = units
99
+ self.time = datetime.now()
100
+ print(self.values, self.units)
101
+
102
+ def find(devices, id):
103
+ for device in devices:
104
+ if device.id == id:
105
+ return device
106
+ return None # device not found
107
+
108
+ def plot(self, Db_class, title = "graph"):
109
+ # Get the current date and time
110
+ now = datetime.now()
111
+
112
+ # Calculate the date and time 10 days ago
113
+ ten_days_ago = now - timedelta(days=300)
114
+
115
+ # Query the database for records from the last 10 days
116
+
117
+ ele_1 = Db_class.query.filter(Db_class.sensor_id == self.id, Db_class.time >= ten_days_ago).all()
118
+
119
+ x = [record.time for record in ele_1]
120
+ y1 = [record.value4 for record in ele_1]
121
+ y2 = [record.value3 for record in ele_1] # Assuming value2 exists
122
+
123
+ fig = make_subplots(specs=[[{"secondary_y": True}]])
124
+
125
+ # Add traces
126
+ fig.add_trace(
127
+ go.Scatter(x=x, y=y1, name="Spotřeba['kWh'])"),
128
+ secondary_y=False,
129
+ )
130
+
131
+ fig.add_trace(
132
+ go.Scatter(x=x, y=y2, name="Aktuální výkon['W']"),
133
+ secondary_y=True,
134
+ )
135
+
136
+ fig.update_layout(
137
+ autosize=True,
138
+ title=title,
139
+ width=1200,
140
+ height=512,
141
+ margin=dict(
142
+ l=40,
143
+ r=20,
144
+ b=20,
145
+ t=60,
146
+ pad=2
147
+ ),
148
+ paper_bgcolor='#F5F5F5',
149
+ plot_bgcolor='#FFFFFF'
150
+ )
151
+
152
+ fig.update_xaxes(title_text='Datum a čas')
153
+ fig.update_yaxes(title_text="Spotřeba [kWh]", secondary_y=False)
154
+ fig.update_yaxes(title_text="Aktuální výkon [W]", secondary_y=True)
155
+
156
+ return fig
device_routes.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from device_core import Camera, Sensor
2
+
3
+ # Define devices
4
+ SENSORS = [
5
+ Sensor("e1", "elektro spodní byt"),
6
+ Sensor("e2", "elektro horní byt"),
7
+ Sensor("e3", "elektro dílna"),
8
+ Sensor("e4", "elektro čerpadlo"),
9
+ Sensor("t1", "teplota spodní kuchyň"),
10
+ Sensor("t2", "teplota horní kuchyň"),
11
+ Sensor("t3", "teplota půda"),
12
+ Sensor("t4", "teplota venkovní"),
13
+ ]
14
+
15
+ CAMERAS = [
16
+ #Camera(id="c1", name="Garáže", rtsp='rtsp://169.254.0.99:554/live.sdp'),
17
+ Camera(id="c2", name="Kůlna", index=0)
18
+ ]
19
+
20
+ LIGHTING_DATA = {}
models.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask_sqlalchemy import SQLAlchemy
2
+ from datetime import datetime
3
+
4
+ db = SQLAlchemy()
5
+
6
+ class Device(db.Model):
7
+ id = db.Column(db.Integer, primary_key=True)
8
+ time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
9
+ sensor_id = db.Column(db.String(64), nullable=False)
10
+ name = db.Column(db.String(50), nullable=False)
11
+ value1 = db.Column(db.Float, nullable=False)
12
+ value2 = db.Column(db.Float)
13
+ value3 = db.Column(db.Float)
14
+ value4 = db.Column(db.Float)
15
+ value5 = db.Column(db.Float)
16
+ value6 = db.Column(db.Float)
17
+ unit1 = db.Column(db.String(10))
18
+ unit2 = db.Column(db.String(10))
19
+ unit3 = db.Column(db.String(10))
20
+ unit4 = db.Column(db.String(10))
21
+ unit5 = db.Column(db.String(10))
22
+ unit6 = db.Column(db.String(10))
23
+
24
+ def init_db(app):
25
+ db.init_app(app)
26
+ with app.app_context():
27
+ db.create_all()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ pip install Flask
2
+ pip install Flask-SQLAlchemy
3
+ pip install Flask-Bootstrap
4
+ pip install plotly
5
+ pip install requests
6
+ pip install opencv-python