patrickligardes commited on
Commit
210cae4
·
verified ·
1 Parent(s): 111f294

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -246
app.py CHANGED
@@ -1,248 +1,81 @@
 
 
1
  import gradio as gr
2
- import requests
3
- import time
4
- from datetime import datetime
5
- import json
6
- import threading
7
- import queue
8
-
9
- class EzvizTuyaAutomation:
10
- def __init__(self):
11
- self.ezviz_base_url = "https://open.ezviz.com/api"
12
- self.tuya_base_url = "https://openapi.tuyaus.com"
13
- self.credentials = {
14
- 'ezviz_app_key': '',
15
- 'ezviz_app_secret': '',
16
- 'tuya_client_id': '',
17
- 'tuya_secret': ''
18
- }
19
- self.ezviz_access_token = None
20
- self.tuya_access_token = None
21
- self.selected_camera = None
22
- self.selected_light = None
23
- self.is_running = False
24
- self.status_queue = queue.Queue()
25
-
26
- def fetch_ezviz_token(self):
27
- """Fetch and set EZVIZ access token"""
28
- url = f"{self.ezviz_base_url}/oauth/token"
29
- payload = {
30
- "appKey": self.credentials['ezviz_app_key'],
31
- "appSecret": self.credentials['ezviz_app_secret']
32
- }
33
- try:
34
- response = requests.post(url, json=payload)
35
- if response.status_code == 200:
36
- self.ezviz_access_token = response.json().get("accessToken")
37
- return "EZVIZ token fetched successfully."
38
- else:
39
- return f"Failed to fetch EZVIZ token: {response.text}"
40
- except Exception as e:
41
- return f"Error fetching EZVIZ token: {str(e)}"
42
-
43
- def get_ezviz_devices(self):
44
- """Get list of EZVIZ cameras"""
45
- if not self.ezviz_access_token:
46
- return []
47
-
48
- url = f"{self.ezviz_base_url}/devices"
49
- headers = {"Authorization": f"Bearer {self.ezviz_access_token}"}
50
- response = requests.get(url, headers=headers)
51
- if response.status_code == 200:
52
- devices = response.json().get("devices", [])
53
- return [{"name": dev["name"], "id": dev["deviceSerial"]} for dev in devices]
54
- print(f"EZVIZ API Response: {response.text}") # Debugging
55
- return []
56
-
57
- def get_tuya_devices(self):
58
- """Get list of Tuya devices"""
59
- if not self.tuya_access_token:
60
- return []
61
-
62
- url = f"{self.tuya_base_url}/v1.0/devices"
63
- headers = {
64
- "Authorization": f"Bearer {self.tuya_access_token}",
65
- "Content-Type": "application/json"
66
- }
67
- response = requests.get(url, headers=headers)
68
- if response.status_code == 200:
69
- devices = response.json().get("devices", [])
70
- return [{"name": dev["name"], "id": dev["id"]} for dev in devices]
71
- print(f"Tuya API Response: {response.text}") # Debugging
72
- return []
73
-
74
- def validate_tokens(self):
75
- if not self.ezviz_access_token:
76
- return "EZVIZ access token is missing or invalid."
77
- if not self.tuya_access_token:
78
- return "Tuya access token is missing or invalid."
79
- return "Tokens validated successfully."
80
-
81
- def check_motion(self):
82
- """Check for motion events from selected EZVIZ camera"""
83
- if not self.ezviz_access_token or not self.selected_camera:
84
- return False
85
-
86
- url = f"{self.ezviz_base_url}/devices/{self.selected_camera}/events"
87
- headers = {"Authorization": f"Bearer {self.ezviz_access_token}"}
88
- response = requests.get(url, headers=headers)
89
- if response.status_code == 200:
90
- events = response.json().get("events", [])
91
- current_time = time.time()
92
- for event in events:
93
- if (event.get("type") == "motion" and
94
- current_time - event.get("timestamp", 0) <= 30):
95
- return True
96
- return False
97
-
98
- def control_light(self, turn_on=True):
99
- """Control selected Tuya device"""
100
- if not self.tuya_access_token or not self.selected_light:
101
- return False
102
-
103
- url = f"{self.tuya_base_url}/v1.0/devices/{self.selected_light}/commands"
104
- headers = {
105
- "Authorization": f"Bearer {self.tuya_access_token}",
106
- "Content-Type": "application/json"
107
- }
108
- command = {
109
- "commands": [
110
- {
111
- "code": "switch_led",
112
- "value": turn_on
113
- }
114
- ]
115
- }
116
- response = requests.post(url, headers=headers, json=command)
117
- return response.status_code == 200
118
-
119
- def automation_loop(self):
120
- """Main automation loop"""
121
- last_motion_time = 0
122
- while self.is_running:
123
- try:
124
- if self.check_motion():
125
- current_time = time.time()
126
- if current_time - last_motion_time > 30:
127
- message = f"Motion detected at {datetime.now()}"
128
- self.status_queue.put(message)
129
- if self.control_light(True):
130
- self.status_queue.put("Light turned on successfully")
131
- last_motion_time = current_time
132
- else:
133
- self.status_queue.put("Failed to control light")
134
- time.sleep(5)
135
- except Exception as e:
136
- self.status_queue.put(f"Error: {str(e)}")
137
- time.sleep(30)
138
-
139
- def create_ui():
140
- automation = EzvizTuyaAutomation()
141
 
142
- def update_credentials(ezviz_key, ezviz_secret, tuya_id, tuya_secret):
143
- automation.credentials.update({
144
- 'ezviz_app_key': ezviz_key,
145
- 'ezviz_app_secret': ezviz_secret,
146
- 'tuya_client_id': tuya_id,
147
- 'tuya_secret': tuya_secret
148
- })
149
- ezviz_status = automation.fetch_ezviz_token()
150
- return f"Credentials updated. {ezviz_status}"
151
-
152
- def get_devices():
153
- # Attempt to fetch devices
154
- try:
155
- ezviz_devices = automation.get_ezviz_devices()
156
- tuya_devices = automation.get_tuya_devices()
157
-
158
- if not ezviz_devices:
159
- ezviz_choices = ["No devices found or invalid credentials."]
160
- else:
161
- ezviz_choices = [f"{dev['name']} ({dev['id']})" for dev in ezviz_devices]
162
-
163
- if not tuya_devices:
164
- tuya_choices = ["No devices found or invalid credentials."]
165
- else:
166
- tuya_choices = [f"{dev['name']} ({dev['id']})" for dev in tuya_devices]
167
-
168
- return ezviz_choices, tuya_choices
169
-
170
- except Exception as e:
171
- print(f"Error fetching devices: {e}")
172
- return ["Error fetching EZVIZ devices"], ["Error fetching Tuya devices"]
173
-
174
- def start_automation(camera_choice, light_choice):
175
- if not camera_choice or not light_choice:
176
- return "Please select both a camera and a light device"
177
-
178
- automation.selected_camera = camera_choice.split('(')[1].rstrip(')')
179
- automation.selected_light = light_choice.split('(')[1].rstrip(')')
180
- automation.is_running = True
181
-
182
- # Start automation in a separate thread
183
- thread = threading.Thread(target=automation.automation_loop)
184
- thread.daemon = True
185
- thread.start()
186
-
187
- return "Automation started"
188
-
189
- def stop_automation():
190
- automation.is_running = False
191
- return "Automation stopped"
192
-
193
- def get_status():
194
- status_messages = []
195
- while not automation.status_queue.empty():
196
- status_messages.append(automation.status_queue.get())
197
- return "\n".join(status_messages) if status_messages else "No new updates"
198
-
199
- with gr.Blocks(title="EZVIZ-Tuya Automation") as app:
200
- with gr.Row():
201
- with gr.Column():
202
- gr.Markdown("### API Credentials")
203
- ezviz_key = gr.Textbox(label="EZVIZ App Key")
204
- ezviz_secret = gr.Textbox(label="EZVIZ App Secret", type="password")
205
- tuya_id = gr.Textbox(label="Tuya Client ID")
206
- tuya_secret = gr.Textbox(label="Tuya Secret", type="password")
207
- save_btn = gr.Button("Save Credentials")
208
- validate_btn = gr.Button("Validate Tokens")
209
- validate_status = gr.Textbox(label="Token Validation Status", interactive=False)
210
-
211
- with gr.Row():
212
- refresh_btn = gr.Button("Refresh Device Lists")
213
- camera_dropdown = gr.Dropdown(label="Select EZVIZ Camera", choices=[])
214
- light_dropdown = gr.Dropdown(label="Select Tuya Light", choices=[])
215
-
216
- with gr.Row():
217
- start_btn = gr.Button("Start Automation")
218
- stop_btn = gr.Button("Stop Automation")
219
-
220
- status_text = gr.Textbox(label="Status", interactive=False)
221
-
222
- # Update status every 5 seconds
223
- status_text.change(get_status, None, status_text, every=5)
224
-
225
- # Button click handlers
226
- save_btn.click(update_credentials,
227
- inputs=[ezviz_key, ezviz_secret, tuya_id, tuya_secret],
228
- outputs=gr.Textbox(label="Status"))
229
-
230
- validate_btn.click(automation.validate_tokens, None, validate_status)
231
-
232
- refresh_btn.click(get_devices,
233
- None,
234
- outputs=[camera_dropdown, light_dropdown])
235
-
236
- start_btn.click(start_automation,
237
- inputs=[camera_dropdown, light_dropdown],
238
- outputs=gr.Textbox(label="Status"))
239
-
240
- stop_btn.click(stop_automation,
241
- None,
242
- outputs=gr.Textbox(label="Status"))
243
-
244
- return app
245
-
246
- if __name__ == "__main__":
247
- app = create_ui()
248
- app.launch()
 
1
+ import pandas as pd
2
+ from openpyxl import load_workbook
3
  import gradio as gr
4
+ import os
5
+
6
+ # Function to extract and map data from the input workbook
7
+ def transform_data(input_path, mapping_df):
8
+ # Load the input workbook
9
+ input_workbook = pd.ExcelFile(input_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # Initialize a dictionary to store data for output
12
+ output_data = {col: [] for col in mapping_df["PO Output Column"] if not pd.isna(col)}
13
+
14
+ # Iterate through each mapping rule
15
+ for _, row in mapping_df.iterrows():
16
+ output_column = row["PO Output Column"]
17
+ input_rule = row["UVM MMB POLY STICKER Column"]
18
+
19
+ if pd.isna(output_column) or pd.isna(input_rule):
20
+ continue
21
+
22
+ # Handle fixed values
23
+ if "Fixed" in input_rule:
24
+ fixed_value = input_rule.split("-")[0].strip()
25
+ output_data[output_column] = [fixed_value] * 1 # Placeholder for rows
26
+
27
+ # TODO: Add logic to map specific columns from input workbook
28
+
29
+ return pd.DataFrame(output_data)
30
+
31
+ # Main processing function
32
+ def process_files(input_workbook, mapping_file, output_template):
33
+ try:
34
+ # Load the data mapping file
35
+ mapping_df = pd.read_excel(mapping_file, sheet_name="Output")
36
+
37
+ # Transform the data
38
+ transformed_data = transform_data(input_workbook, mapping_df)
39
+
40
+ # Load the output template
41
+ output_workbook = load_workbook(output_template)
42
+ output_sheet = output_workbook["363040"]
43
+
44
+ # Write transformed data to the output sheet
45
+ for row_idx, row_data in enumerate(transformed_data.itertuples(index=False), start=2):
46
+ for col_idx, value in enumerate(row_data, start=1):
47
+ output_sheet.cell(row=row_idx, column=col_idx, value=value)
48
+
49
+ # Save the generated output file
50
+ output_file_path = "Generated_Output.xlsx"
51
+ output_workbook.save(output_file_path)
52
+
53
+ return output_file_path
54
+
55
+ except Exception as e:
56
+ return f"An error occurred: {e}"
57
+
58
+ # Define the Gradio interface
59
+ def generate_excel(input_workbook, mapping_file, output_template):
60
+ result = process_files(input_workbook.name, mapping_file.name, output_template.name)
61
+ if os.path.exists(result):
62
+ return result
63
+ else:
64
+ return "An error occurred during file generation."
65
+
66
+ with gr.Blocks() as app:
67
+ gr.Markdown("# Excel Sheet Generator")
68
+ gr.Markdown("Upload the input workbook, mapping file, and output template to generate the final Excel file.")
69
+
70
+ with gr.Row():
71
+ input_workbook = gr.File(label="Input Workbook", file_types=[".xlsx"])
72
+ mapping_file = gr.File(label="Mapping File", file_types=[".xlsx"])
73
+ output_template = gr.File(label="Output Template", file_types=[".xlsx"])
74
+
75
+ output_file = gr.File(label="Generated Excel File")
76
+ generate_button = gr.Button("Generate Excel File")
77
+
78
+ generate_button.click(generate_excel, inputs=[input_workbook, mapping_file, output_template], outputs=[output_file])
79
+
80
+ # Launch the app
81
+ app.launch()