|
|
import gradio as gr |
|
|
import sqlite3 |
|
|
import pandas as pd |
|
|
from datetime import datetime |
|
|
import folium |
|
|
from folium import plugins |
|
|
import webbrowser |
|
|
import os |
|
|
|
|
|
|
|
|
def init_db(): |
|
|
conn = sqlite3.connect('locations.db', check_same_thread=False) |
|
|
cursor = conn.cursor() |
|
|
cursor.execute(''' |
|
|
CREATE TABLE IF NOT EXISTS locations ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
device_id TEXT NOT NULL, |
|
|
device_name TEXT NOT NULL, |
|
|
latitude REAL NOT NULL, |
|
|
longitude REAL NOT NULL, |
|
|
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, |
|
|
accuracy REAL, |
|
|
battery_level INTEGER |
|
|
) |
|
|
''') |
|
|
conn.commit() |
|
|
conn.close() |
|
|
|
|
|
init_db() |
|
|
|
|
|
|
|
|
def add_location(device_id, device_name, latitude, longitude, accuracy=10, battery=100): |
|
|
try: |
|
|
lat = float(latitude) |
|
|
lng = float(longitude) |
|
|
|
|
|
if not (-90 <= lat <= 90) or not (-180 <= lng <= 180): |
|
|
return "❌ Erro: Coordenadas inválidas!" |
|
|
|
|
|
conn = sqlite3.connect('locations.db', check_same_thread=False) |
|
|
cursor = conn.cursor() |
|
|
|
|
|
cursor.execute(''' |
|
|
INSERT INTO locations (device_id, device_name, latitude, longitude, accuracy, battery_level) |
|
|
VALUES (?, ?, ?, ?, ?, ?) |
|
|
''', (device_id, device_name, lat, lng, accuracy, battery)) |
|
|
|
|
|
conn.commit() |
|
|
conn.close() |
|
|
|
|
|
return f"✅ Localização atualizada!\n📍 {lat:.6f}, {lng:.6f}\n⏰ {datetime.now().strftime('%H:%M:%S')}" |
|
|
|
|
|
except Exception as e: |
|
|
return f"❌ Erro: {str(e)}" |
|
|
|
|
|
|
|
|
def create_auto_gps_page(device_id, device_name): |
|
|
html_content = f""" |
|
|
<!DOCTYPE html> |
|
|
<html> |
|
|
<head> |
|
|
<title>Compartilhamento de Localização</title> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<style> |
|
|
body {{ font-family: Arial, sans-serif; padding: 20px; text-align: center; }} |
|
|
.status {{ font-size: 18px; margin: 20px 0; font-weight: bold; }} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<h1>Compartilhando Localização</h1> |
|
|
<div id="status" class="status">Obtendo sua localização...</div> |
|
|
|
|
|
<script> |
|
|
function sendToGradio(latitude, longitude, accuracy) {{ |
|
|
window.location.href = `gradio://localhost:7860/?device_id={device_id}&device_name={device_name}&latitude=${{latitude}}&longitude=${{longitude}}&accuracy=${{accuracy}}`; |
|
|
}} |
|
|
|
|
|
function getLocation() {{ |
|
|
if (navigator.geolocation) {{ |
|
|
navigator.geolocation.watchPosition( |
|
|
position => {{ |
|
|
const lat = position.coords.latitude; |
|
|
const lng = position.coords.longitude; |
|
|
const acc = position.coords.accuracy; |
|
|
|
|
|
document.getElementById('status').textContent = "Localização compartilhada com sucesso!"; |
|
|
sendToGradio(lat, lng, acc); |
|
|
}}, |
|
|
error => {{ |
|
|
document.getElementById('status').textContent = "Erro: " + error.message; |
|
|
}}, |
|
|
{{ enableHighAccuracy: true }} |
|
|
); |
|
|
}} else {{ |
|
|
document.getElementById('status').textContent = "Geolocalização não suportada."; |
|
|
}} |
|
|
}} |
|
|
|
|
|
window.onload = getLocation; |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
""" |
|
|
with open("gps_auto_capture.html", "w") as f: |
|
|
f.write(html_content) |
|
|
return os.path.abspath("gps_auto_capture.html") |
|
|
|
|
|
def start_auto_gps(device_id, device_name): |
|
|
page_path = create_auto_gps_page(device_id, device_name) |
|
|
webbrowser.open(f"file://{page_path}") |
|
|
return "🌍 Captura automática iniciada! Permita o acesso à localização." |
|
|
|
|
|
|
|
|
def get_updated_map(): |
|
|
try: |
|
|
conn = sqlite3.connect('locations.db', check_same_thread=False) |
|
|
df = pd.read_sql_query(''' |
|
|
SELECT device_name, latitude, longitude, timestamp, accuracy |
|
|
FROM locations |
|
|
ORDER BY timestamp DESC |
|
|
LIMIT 50 |
|
|
''', conn) |
|
|
conn.close() |
|
|
|
|
|
if df.empty: |
|
|
m = folium.Map(location=[-14.235, -51.9253], zoom_start=4) |
|
|
folium.Marker([-14.235, -51.9253], popup="Nenhum dado disponível").add_to(m) |
|
|
return m._repr_html_() |
|
|
|
|
|
m = folium.Map(location=[df.iloc[0]['latitude'], df.iloc[0]['longitude']], zoom_start=15) |
|
|
|
|
|
for _, row in df.iterrows(): |
|
|
folium.Marker( |
|
|
[row['latitude'], row['longitude']], |
|
|
popup=f"{row['device_name']}<br>{row['timestamp']}", |
|
|
icon=folium.Icon(color='blue') |
|
|
).add_to(m) |
|
|
|
|
|
plugins.Fullscreen().add_to(m) |
|
|
return m._repr_html_() |
|
|
except Exception as e: |
|
|
return f"<div style='color:red;padding:20px;'>Erro: {str(e)}</div>" |
|
|
|
|
|
|
|
|
def create_interface(): |
|
|
with gr.Blocks(title="📍 Monitor GPS Automático") as demo: |
|
|
gr.Markdown("## 📍 Monitor de Localização em Tempo Real") |
|
|
|
|
|
with gr.Row(): |
|
|
device_id = gr.Textbox(label="ID do Dispositivo", value="celular_1") |
|
|
device_name = gr.Textbox(label="Nome do Dispositivo", value="Meu Celular") |
|
|
auto_gps_btn = gr.Button("📍 Iniciar Captura Automática", variant="primary") |
|
|
|
|
|
gps_status = gr.Textbox(label="Status", interactive=False) |
|
|
|
|
|
auto_gps_btn.click( |
|
|
start_auto_gps, |
|
|
inputs=[device_id, device_name], |
|
|
outputs=gps_status |
|
|
) |
|
|
|
|
|
with gr.Tab("Mapa"): |
|
|
map_html = gr.HTML(get_updated_map()) |
|
|
gr.Timer(5.0, get_updated_map, None, map_html) |
|
|
|
|
|
with gr.Tab("Dados"): |
|
|
gr.Dataframe( |
|
|
lambda: pd.read_sql_query( |
|
|
"SELECT device_name, latitude, longitude, timestamp, accuracy FROM locations ORDER BY timestamp DESC", |
|
|
sqlite3.connect('locations.db') |
|
|
), |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
@demo.load(inputs=None, outputs=None) |
|
|
def handle_gps_data(request: gr.Request): |
|
|
params = request.query_params |
|
|
if 'latitude' in params and 'longitude' in params: |
|
|
add_location( |
|
|
params.get('device_id', 'unknown'), |
|
|
params.get('device_name', 'Dispositivo Móvel'), |
|
|
params['latitude'], |
|
|
params['longitude'], |
|
|
params.get('accuracy', 10) |
|
|
) |
|
|
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo = create_interface() |
|
|
demo.launch(server_name="0.0.0.0", server_port=7860) |