// Main JavaScript for MapVoyage Compass
// API Configuration
const API_BASE_URL = 'https://ocpp.neto.mx:8082/api';
const ACCESS_TOKEN = '1bc2b30bcde5c4a31a1e6d6e8637e149f16102f43c46db22ca19ddd1348cb745';
// Global variables
let map;
let chargePointMarkers = [];
let chargePointLayerGroup;
let refreshInterval;
// Initialize OpenStreetMap with Positron style
function initMap() {
// Default coordinates (centered on Mexico)
const defaultLat = 23.6345;
const defaultLng = -102.5528;
const defaultZoom = 5;
// Create map instance with zoom control disabled
map = L.map('map', {
zoomControl: false
}).setView([defaultLat, defaultLng], defaultZoom);
// Add Positron tile layer (CartoDB Positron)
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
attribution: '© OpenStreetMap contributors © CARTO',
subdomains: 'abcd',
maxZoom: 19,
}).addTo(map);
// Create a layer group for charge points
chargePointLayerGroup = L.layerGroup().addTo(map);
// Add a marker at the center
const marker = L.marker([defaultLat, defaultLng]).addTo(map);
marker.bindPopup('Welcome to MapVoyage Compass! đź§
Now showing electric vehicle charge points.').openPopup();
// Add click event to get coordinates
map.on('click', function(e) {
const popup = L.popup()
.setLatLng(e.latlng)
.setContent(`You clicked at:
${e.latlng.lat.toFixed(4)}, ${e.latlng.lng.toFixed(4)}`)
.openOn(map);
});
// Load charge points from API
loadChargePoints();
// Start auto‑refresh every 10 seconds
startAutoRefresh();
// Store map instance globally for other functions
window.map = map;
}
// Load charge points from API
async function loadChargePoints() {
try {
// Silent load: no notification
const response = await fetch(`${API_BASE_URL}/charge_points`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${ACCESS_TOKEN}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
const chargePoints = await response.json();
// Filter points with valid coordinates
const validPoints = chargePoints.filter(point =>
point.latitude && point.longitude &&
point.latitude !== 'null' && point.longitude !== 'null' &&
!isNaN(parseFloat(point.latitude)) && !isNaN(parseFloat(point.longitude))
);
if (validPoints.length === 0) {
// No valid points, but do nothing silently
return;
}
// Create a lookup of existing markers by IDs (or coordinates) to update/remove
// For simplicity, we'll clear and re‑add, but keep the map view.
// First, store current map view to preserve it.
const currentCenter = map.getCenter();
const currentZoom = map.getZoom();
// Clear existing markers
chargePointMarkers.forEach(marker => marker.remove());
chargePointMarkers = [];
chargePointLayerGroup.clearLayers();
// Create markers for each charge point
validPoints.forEach(point => {
const marker = createChargePointMarker(point);
chargePointMarkers.push(marker);
chargePointLayerGroup.addLayer(marker);
});
// Restore map view (no recentering)
map.setView(currentCenter, currentZoom);
// No success notification
} catch (error) {
console.error('Error loading charge points:', error);
// Silent fallback to demo data
loadDemoChargePoints();
}
}
// Start auto‑refresh every 10 seconds
function startAutoRefresh() {
if (refreshInterval) {
clearInterval(refreshInterval);
}
refreshInterval = setInterval(() => {
loadChargePoints();
console.log('Auto‑refresh executed at', new Date().toLocaleTimeString());
}, 10000); // 10 seconds
}
// Stop auto‑refresh (useful for manual control)
function stopAutoRefresh() {
if (refreshInterval) {
clearInterval(refreshInterval);
refreshInterval = null;
showNotification('Auto‑refresh stopped');
}
}
// Toggle auto‑refresh on/off
function toggleAutoRefresh() {
if (refreshInterval) {
stopAutoRefresh();
} else {
startAutoRefresh();
}
}
// Create a marker for a charge point
function createChargePointMarker(chargePoint) {
// Determine color based on status
let color = '#3b82f6'; // Default blue
let fillColor = '#8b5cf6';
if (chargePoint.last_heartbeat) {
const lastHeartbeat = new Date(chargePoint.last_heartbeat);
const now = new Date();
const hoursDiff = (now - lastHeartbeat) / (1000 * 60 * 60);
if (hoursDiff > 24) {
color = '#ef4444'; // Red for offline (>24h)
fillColor = '#f87171';
} else if (hoursDiff > 1) {
color = '#f59e0b'; // Yellow for stale (1-24h)
fillColor = '#fbbf24';
} else {
color = '#10b981'; // Green for recent (<1h)
fillColor = '#34d399';
}
}
// Create custom icon
const icon = L.divIcon({
html: `
${chargePoint.vendor || 'Unknown Vendor'}
Address:
${chargePoint.address}
Detailed information would be fetched from the API for point ID ${pointId}.
Charge Points
${message}