Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Animal Health Monitor</title> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --primary-color: #3498db; | |
| --secondary-color: #2ecc71; | |
| --background-color: #ecf0f1; | |
| --text-color: #34495e; | |
| --card-background: #ffffff; | |
| } | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background-color: var(--background-color); | |
| color: var(--text-color); | |
| margin: 0; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| h1 { | |
| color: var(--primary-color); | |
| text-align: center; | |
| margin-bottom: 30px; | |
| font-size: 2.5em; | |
| } | |
| .dashboard { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | |
| gap: 20px; | |
| } | |
| .card { | |
| background: var(--card-background); | |
| border-radius: 10px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| padding: 20px; | |
| text-align: center; | |
| transition: transform 0.3s ease; | |
| } | |
| .card:hover { | |
| transform: translateY(-5px); | |
| } | |
| .card-title { | |
| font-size: 1.2em; | |
| color: var(--primary-color); | |
| margin-bottom: 10px; | |
| } | |
| .card-value { | |
| font-size: 2em; | |
| font-weight: bold; | |
| margin: 10px 0; | |
| } | |
| .card i { | |
| font-size: 2em; | |
| margin-bottom: 10px; | |
| color: var(--secondary-color); | |
| } | |
| #map { | |
| height: 300px; | |
| border-radius: 10px; | |
| margin-top: 20px; | |
| } | |
| @media (max-width: 768px) { | |
| .dashboard { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Animal Health Monitor</h1> | |
| <div class="dashboard"> | |
| <div class="card"> | |
| <i class="fas fa-thermometer-half"></i> | |
| <div class="card-title">Temperature</div> | |
| <div class="card-value"><span id="tempCelsius">--</span>°C</div> | |
| <div class="card-value"><span id="tempFahrenheit">--</span>°F</div> | |
| </div> | |
| <div class="card"> | |
| <i class="fas fa-heartbeat"></i> | |
| <div class="card-title">Heart Rate</div> | |
| <div class="card-value"><span id="bpm">--</span> BPM</div> | |
| </div> | |
| <div class="card"> | |
| <i class="fas fa-lungs"></i> | |
| <div class="card-title">Blood Oxygen</div> | |
| <div class="card-value"><span id="spo2">--</span>%</div> | |
| </div> | |
| <div class="card"> | |
| <i class="fas fa-map-marker-alt"></i> | |
| <div class="card-title">GPS Location</div> | |
| <div class="card-value"> | |
| <div>Lat: <span id="latitude">--</span></div> | |
| <div>Long: <span id="longitude">--</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="map"></div> | |
| </div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/firebase/9.22.2/firebase-app-compat.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/firebase/9.22.2/firebase-database-compat.min.js"></script> | |
| <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAOVYRIgupAurZup5y1PRh8Ismb1A3lLao&callback=initMap" async defer></script> | |
| <script> | |
| // Initialize Google Map | |
| let map; | |
| let marker; | |
| function initMap() { | |
| try { | |
| map = new google.maps.Map(document.getElementById('map'), { | |
| center: {lat: 7.2297, lng: 3.4392}, // Center map at the original coordinates | |
| zoom: 15 // Adjust zoom level to focus on the area | |
| }); | |
| marker = new google.maps.Marker({ | |
| position: {lat: 7.2297, lng: 3.4392}, // Start marker at the original coordinates | |
| map: map | |
| }); | |
| console.log("Map initialized successfully"); | |
| } catch (error) { | |
| console.error("Error initializing map:", error); | |
| document.getElementById('map').innerHTML = '<p>Error loading map. Please check the console for details.</p>'; | |
| } | |
| } | |
| // Function to fetch the latest data from the FastAPI endpoint | |
| async function fetchLatestData() { | |
| try { | |
| const response = await fetch('http://localhost:8000/latest-data'); | |
| const data = await response.json(); | |
| return data; | |
| } catch (error) { | |
| console.error("Error fetching data:", error); | |
| return null; | |
| } | |
| } | |
| // Function to update the dashboard with real data | |
| async function updateDashboard() { | |
| const data = await fetchLatestData(); | |
| if (data) { | |
| document.getElementById('tempCelsius').textContent = data.temperature || '--'; | |
| document.getElementById('tempFahrenheit').textContent = data.temperature_in_F || '--'; | |
| document.getElementById('bpm').textContent = data.heart_rate || '--'; | |
| document.getElementById('spo2').textContent = data.blood_oxygen || '--'; | |
| document.getElementById('latitude').textContent = data.latitude || '--'; | |
| document.getElementById('longitude').textContent = data.longitude || '--'; | |
| if (map && marker && data.latitude && data.longitude) { | |
| try { | |
| const newPosition = new google.maps.LatLng(parseFloat(data.latitude), parseFloat(data.longitude)); | |
| marker.setPosition(newPosition); | |
| map.panTo(newPosition); | |
| } catch (error) { | |
| console.error("Error updating map:", error); | |
| } | |
| } else { | |
| console.warn("Map or marker not initialized or invalid data"); | |
| } | |
| } else { | |
| console.warn("No data fetched"); | |
| } | |
| } | |
| // Initialize the dashboard on load | |
| window.onload = function() { | |
| initMap(); | |
| updateDashboard(); | |
| }; | |
| // Update dashboard every 5 seconds | |
| setInterval(updateDashboard, 5000); | |
| </script> | |
| </body> | |
| </html> | |