diff --git a/front/php/server/events.php b/front/php/server/events.php deleted file mode 100755 index 7c3f0cb3..00000000 --- a/front/php/server/events.php +++ /dev/null @@ -1,418 +0,0 @@ -= date('now', '".$periodDateSQL."')) as all_events, - (SELECT Count(*) FROM Sessions as sessions WHERE ( ses_DateTimeConnection >= date('now', '".$periodDateSQL."') OR ses_DateTimeDisconnection >= date('now', '".$periodDateSQL."') OR ses_StillConnected = 1 )) as sessions, - (SELECT Count(*) FROM Sessions WHERE ((ses_DateTimeConnection IS NULL AND ses_DateTimeDisconnection >= date('now', '".$periodDateSQL."' )) OR (ses_DateTimeDisconnection IS NULL AND ses_StillConnected = 0 AND ses_DateTimeConnection >= date('now', '".$periodDateSQL."' )))) as missing, - (SELECT Count(*) FROM Events WHERE eve_DateTime >= date('now', '".$periodDateSQL."') AND eve_EventType LIKE 'VOIDED%' ) as voided, - (SELECT Count(*) FROM Events WHERE eve_DateTime >= date('now', '".$periodDateSQL."') AND eve_EventType LIKE 'New Device' ) as new, - (SELECT Count(*) FROM Events WHERE eve_DateTime >= date('now', '".$periodDateSQL."') AND eve_EventType LIKE 'Device Down' ) as down"; - - $result = $db->query($sql); - $row = $result -> fetchArray (SQLITE3_NUM); - $resultJSON = json_encode (array ($row[0], $row[1], $row[2], $row[3], $row[4], $row[5])); - - // save JSON result to cache - setCache("getEventsTotals".$days, $resultJSON ); - } - - // Return json - echo ($resultJSON); -} - - -//------------------------------------------------------------------------------ -// Query the List of events -//------------------------------------------------------------------------------ -function getEvents() { - global $db; - - // Request Parameters - $type = $_REQUEST ['type']; - $periodDate = getDateFromPeriod(); - - // SQL - $SQL1 = 'SELECT eve_DateTime AS eve_DateTimeOrder, devName, devOwner, eve_DateTime, eve_EventType, NULL, NULL, NULL, NULL, eve_IP, NULL, eve_AdditionalInfo, NULL, devMac, eve_PendingAlertEmail - FROM Events_Devices - WHERE eve_DateTime >= '. $periodDate; - - $SQL2 = 'SELECT IFNULL (ses_DateTimeConnection, ses_DateTimeDisconnection) ses_DateTimeOrder, - devName, devOwner, Null, Null, ses_DateTimeConnection, ses_DateTimeDisconnection, NULL, NULL, ses_IP, NULL, ses_AdditionalInfo, ses_StillConnected, devMac - FROM Sessions_Devices '; - - // SQL Variations for status - switch ($type) { - case 'all': $SQL = $SQL1; break; - case 'sessions': - $SQL = $SQL2 . ' WHERE ( ses_DateTimeConnection >= '. $periodDate .' OR ses_DateTimeDisconnection >= '. $periodDate .' OR ses_StillConnected = 1 ) '; - break; - case 'missing': - $SQL = $SQL2 . ' WHERE (ses_DateTimeConnection IS NULL AND ses_DateTimeDisconnection >= '. $periodDate .' ) - OR (ses_DateTimeDisconnection IS NULL AND ses_StillConnected = 0 AND ses_DateTimeConnection >= '. $periodDate .' )'; - break; - case 'voided': $SQL = $SQL1 .' AND eve_EventType LIKE "VOIDED%" '; break; - case 'new': $SQL = $SQL1 .' AND eve_EventType = "New Device" '; break; - case 'down': $SQL = $SQL1 .' AND eve_EventType = "Device Down" '; break; - default: $SQL = $SQL1 .' AND 1==0 '; break; - } - - // Query - $result = $db->query($SQL); - - $tableData = array(); - while ($row = $result -> fetchArray (SQLITE3_NUM)) { - if ($type == 'sessions' || $type == 'missing' ) { - // Duration - if (!empty ($row[5]) && !empty($row[6]) ) { - $row[7] = formatDateDiff ($row[5], $row[6]); - $row[8] = abs(strtotime($row[6]) - strtotime($row[5])); - } elseif ($row[12] == 1) { - $row[7] = formatDateDiff ($row[5], ''); - $row[8] = abs(strtotime("now") - strtotime($row[5])); - } else { - $row[7] = '...'; - $row[8] = 0; - } - - // Connection - if (!empty ($row[5]) ) { - $row[5] = formatDate ($row[5]); - } else { - $row[5] = ''; - } - - // Disconnection - if (!empty ($row[6]) ) { - $row[6] = formatDate ($row[6]); - } elseif ($row[12] == 0) { - $row[6] = ''; - } else { - $row[6] = '...'; - } - - } else { - // Event Date - $row[3] = formatDate ($row[3]); - } - - // IP Order - $row[10] = formatIPlong ($row[9]); - $tableData['data'][] = $row; - } - - // Control no rows - if (empty($tableData['data'])) { - $tableData['data'] = ''; - } - - // Return json - echo (json_encode ($tableData)); -} - - -//------------------------------------------------------------------------------ -// Query Device Sessions -//------------------------------------------------------------------------------ -function getDeviceSessions() { - global $db; - - // Request Parameters - $mac = $_REQUEST['mac']; - $periodDate = getDateFromPeriod(); - - // SQL - $SQL = 'SELECT IFNULL (ses_DateTimeConnection, ses_DateTimeDisconnection) ses_DateTimeOrder, - ses_EventTypeConnection, ses_DateTimeConnection, - ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_StillConnected, - ses_IP, ses_AdditionalInfo - FROM Sessions - WHERE ses_MAC="' . $mac .'" - AND ( ses_DateTimeConnection >= '. $periodDate .' - OR ses_DateTimeDisconnection >= '. $periodDate .' - OR ses_StillConnected = 1 ) '; - $result = $db->query($SQL); - - // arrays of rows - $tableData = array(); - while ($row = $result -> fetchArray (SQLITE3_ASSOC)) { - // Connection DateTime - if ($row['ses_EventTypeConnection'] == '') { - $ini = $row['ses_EventTypeConnection']; - } else { - $ini = formatDate ($row['ses_DateTimeConnection']); - } - - // Disconnection DateTime - if ($row['ses_StillConnected'] == true) { - $end = '...'; - } elseif ($row['ses_EventTypeDisconnection'] == '') { - $end = $row['ses_EventTypeDisconnection']; - } else { - $end = formatDate ($row['ses_DateTimeDisconnection']); - } - - // Duration - if ($row['ses_EventTypeConnection'] == '' || $row['ses_EventTypeConnection'] == NULL || $row['ses_EventTypeDisconnection'] == '' || $row['ses_EventTypeDisconnection'] == NULL) { - $dur = '...'; - } elseif ($row['ses_StillConnected'] == true) { - $dur = formatDateDiff ($row['ses_DateTimeConnection'], ''); //*********** - } else { - $dur = formatDateDiff ($row['ses_DateTimeConnection'], $row['ses_DateTimeDisconnection']); - } - - // Additional Info - $info = $row['ses_AdditionalInfo']; - if ($row['ses_EventTypeConnection'] == 'New Device' ) { - $info = $row['ses_EventTypeConnection'] .': '. $info; - } - - // Push row data - $tableData['data'][] = array($row['ses_DateTimeOrder'], $ini, $end, $dur, $row['ses_IP'], $info); - } - - // Control no rows - if (empty($tableData['data'])) { - $tableData['data'] = ''; - } - - // Return json - echo (json_encode ($tableData)); -} - - -//------------------------------------------------------------------------------ -// Query Device Presence Calendar -//------------------------------------------------------------------------------ -function getDevicePresence() { - global $db; - - // Request Parameters - $mac = $_REQUEST['mac']; - $startDate = '"'. formatDateISO ($_REQUEST ['start']) .'"'; - $endDate = '"'. formatDateISO ($_REQUEST ['end']) .'"'; - - // SQL - $SQL = 'SELECT ses_EventTypeConnection, ses_DateTimeConnection, - ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_IP, ses_AdditionalInfo, ses_StillConnected, - - CASE - WHEN ses_EventTypeConnection = "" THEN - IFNULL ((SELECT MAX(ses_DateTimeDisconnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeDisconnection < SES1.ses_DateTimeDisconnection), DATETIME(ses_DateTimeDisconnection, "-1 hour")) - ELSE ses_DateTimeConnection - END AS ses_DateTimeConnectionCorrected, - - CASE - WHEN ses_EventTypeDisconnection = "" OR ses_EventTypeDisconnection = NULL THEN - (SELECT MIN(ses_DateTimeConnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeConnection > SES1.ses_DateTimeConnection) - ELSE ses_DateTimeDisconnection - END AS ses_DateTimeDisconnectionCorrected - - FROM Sessions AS SES1 - WHERE ses_MAC="' . $mac .'" - AND (ses_DateTimeConnectionCorrected <= date('. $endDate .') - AND (ses_DateTimeDisconnectionCorrected >= date('. $startDate .') OR ses_StillConnected = 1 )) '; - $result = $db->query($SQL); - - // arrays of rows - while ($row = $result -> fetchArray (SQLITE3_ASSOC)) { - // Event color - if ($row['ses_EventTypeConnection'] == '' || $row['ses_EventTypeDisconnection'] == '') { - $color = '#f39c12'; - } elseif ($row['ses_StillConnected'] == 1 ) { - $color = '#00a659'; - } else { - $color = '#0073b7'; - } - - - // tooltip - $tooltip = 'Connection: ' . formatEventDate ($row['ses_DateTimeConnection'], $row['ses_EventTypeConnection']) . chr(13) . - 'Disconnection: ' . formatEventDate ($row['ses_DateTimeDisconnection'], $row['ses_EventTypeDisconnection']) . chr(13) . - 'IP: ' . $row['ses_IP']; - - // Save row data - $tableData[] = array( - 'title' => '', - 'start' => formatDateISO ($row['ses_DateTimeConnectionCorrected']), - 'end' => formatDateISO ($row['ses_DateTimeDisconnectionCorrected']), - 'color' => $color, - 'tooltip' => $tooltip - ); - } - - // Control no rows - if (empty($tableData)) { - $tableData = ''; - } - - // Return json - echo (json_encode($tableData)); -} - - -//------------------------------------------------------------------------------ -// Query Presence Calendar for all Devices -//------------------------------------------------------------------------------ -function getEventsCalendar() { - global $db; - - // Request Parameters - $startDate = '"'. $_REQUEST ['start'] .'"'; - $endDate = '"'. $_REQUEST ['end'] .'"'; - - // SQL - $SQL = 'SELECT SES1.ses_MAC, SES1.ses_EventTypeConnection, SES1.ses_DateTimeConnection, - SES1.ses_EventTypeDisconnection, SES1.ses_DateTimeDisconnection, SES1.ses_IP, - SES1.ses_AdditionalInfo, SES1.ses_StillConnected, - - CASE - WHEN SES1.ses_EventTypeConnection = "" THEN - IFNULL ( - (SELECT MAX(SES2.ses_DateTimeDisconnection) - FROM Sessions AS SES2 - WHERE SES2.ses_MAC = SES1.ses_MAC - AND SES2.ses_DateTimeDisconnection < SES1.ses_DateTimeDisconnection - AND SES2.ses_DateTimeDisconnection BETWEEN Date('. $startDate .') AND Date('. $endDate .') - ), - DATETIME(SES1.ses_DateTimeDisconnection, "-1 hour") - ) - ELSE SES1.ses_DateTimeConnection - END AS ses_DateTimeConnectionCorrected, - - CASE - WHEN SES1.ses_EventTypeDisconnection = "" THEN - (SELECT MIN(SES2.ses_DateTimeConnection) - FROM Sessions AS SES2 - WHERE SES2.ses_MAC = SES1.ses_MAC - AND SES2.ses_DateTimeConnection > SES1.ses_DateTimeConnection - AND SES2.ses_DateTimeConnection BETWEEN Date('. $startDate .') AND Date('. $endDate .') - ) - ELSE SES1.ses_DateTimeDisconnection - END AS ses_DateTimeDisconnectionCorrected - - FROM Sessions AS SES1 - WHERE (SES1.ses_DateTimeConnection BETWEEN Date('. $startDate .') AND Date('. $endDate .')) - OR (SES1.ses_DateTimeDisconnection BETWEEN Date('. $startDate .') AND Date('. $endDate .')) - OR SES1.ses_StillConnected = 1'; - - $result = $db->query($SQL); - - // arrays of rows - while ($row = $result -> fetchArray (SQLITE3_ASSOC)) { - // Event color - if ($row['ses_EventTypeConnection'] == '' || $row['ses_EventTypeDisconnection'] == '') { - $color = '#f39c12'; - } elseif ($row['ses_StillConnected'] == 1 ) { - $color = '#00a659'; - } else { - $color = '#0073b7'; - } - - // tooltip - $tooltip = 'Connection: ' . formatEventDate ($row['ses_DateTimeConnection'], $row['ses_EventTypeConnection']) . chr(13) . - 'Disconnection: ' . formatEventDate ($row['ses_DateTimeDisconnection'], $row['ses_EventTypeDisconnection']) . chr(13) . - 'IP: ' . $row['ses_IP']; - - // Save row data - $tableData[] = array( - 'resourceId' => $row['ses_MAC'], - 'title' => '', - 'start' => formatDateISO ($row['ses_DateTimeConnectionCorrected']), - 'end' => formatDateISO ($row['ses_DateTimeDisconnectionCorrected']), - 'color' => $color, - 'tooltip' => $tooltip, - 'className' => 'no-border' - ); - } - - // Control no rows - if (empty($tableData)) { - $tableData = ''; - } - - // Return json - echo (json_encode($tableData)); -} - -?> diff --git a/front/plugins/_publisher_mqtt/mqtt.py b/front/plugins/_publisher_mqtt/mqtt.py index 70a884ab..6d3f77d3 100755 --- a/front/plugins/_publisher_mqtt/mqtt.py +++ b/front/plugins/_publisher_mqtt/mqtt.py @@ -510,7 +510,7 @@ def mqtt_start(db): "group": device["devGroup"], "location": device["devLocation"], "network_parent_mac": device["devParentMAC"], - "network_parent_name": next((dev["devName"] for dev in devices if dev["devMAC"] == device["devParentMAC"]), "") + "network_parent_name": next((dev["devName"] for dev in devices if dev["devMac"] == device["devParentMAC"]), "") } # bulk update device sensors in home assistant diff --git a/front/presence.php b/front/presence.php index 6052abb2..a7c0c579 100755 --- a/front/presence.php +++ b/front/presence.php @@ -1,7 +1,7 @@ - + ?> - + @@ -147,7 +147,7 @@ -
+
@@ -236,7 +236,7 @@ function initializeCalendar () { height : 'auto', firstDay : 1, allDaySlot : false, - timeFormat : 'H:mm', + timeFormat : 'H:mm', resourceLabelText : '', resourceAreaWidth : '160px', @@ -291,24 +291,24 @@ function initializeCalendar () { slotDuration : '00:30:00' } }, - + // Needed due hack partial day events 23:59:59 dayRender: function (date, cell) { if ($('#calendar').fullCalendar('getView').name == 'timelineYear') { - cell.removeClass('fc-sat'); - cell.removeClass('fc-sun'); + cell.removeClass('fc-sat'); + cell.removeClass('fc-sun'); return; - }; + }; if (date.day() == 0) { cell.addClass('fc-sun'); }; - + if (date.day() == 6) { cell.addClass('fc-sat'); }; if (date.format('YYYY-MM-DD') == moment().format('YYYY-MM-DD')) { cell.addClass ('fc-today'); }; - + if ($('#calendar').fullCalendar('getView').name == 'timelineDay') { cell.removeClass('fc-sat'); cell.removeClass('fc-sun'); @@ -318,7 +318,7 @@ function initializeCalendar () { } }; }, - + resourceRender: function (resourceObj, labelTds, bodyTds) { labelTds.find('span.fc-cell-text').html ( ''+ resourceObj.title +''); @@ -326,7 +326,7 @@ function initializeCalendar () { // Resize heihgt // $(".fc-content table tbody tr .fc-widget-content div").addClass('fc-resized-row'); }, - + eventRender: function (event, element, view) { // $(element).tooltip({container: 'body', placement: 'bottom', title: event.tooltip}); tltp = event.tooltip.replace('\n',' | ') @@ -387,7 +387,7 @@ function getDevicesPresence (status) { case 'down': tableTitle = ''; color = 'red'; break; case 'archived': tableTitle = ''; color = 'gray'; break; default: tableTitle = ''; color = 'gray'; break; - } + } period = "7 days" @@ -421,12 +421,60 @@ function getDevicesPresence (status) { $('#tableDevicesBox')[0].className = 'box box-'+ color; $('#tableDevicesTitle').html (tableTitle); - // Define new datasource URL and reload - $('#calendar').fullCalendar ('option', 'resources', 'php/server/devices.php?action=getDevicesListCalendar&status='+ deviceStatus); - $('#calendar').fullCalendar ('refetchResources'); + const protocol = window.location.protocol.replace(':', ''); + const host = window.location.hostname; + const port = getSetting("GRAPHQL_PORT"); // Or Flask server port + const apiToken = getSetting("API_TOKEN"); + + const apiBase = `${protocol}://${host}:${port}`; + + // ----------------------------- + // Load Devices as Resources + // ----------------------------- + const devicesUrl = `${apiBase}/devices/by-status?status=${deviceStatus}`; + + $.ajax({ + url: devicesUrl, + method: "GET", + headers: { + "Authorization": `Bearer ${apiToken}` + }, + success: function(devices) { + // FullCalendar expects resources array + const resources = devices.map(dev => ({ + id: dev.devMac, + title: dev.devName + })); + + $('#calendar').fullCalendar('option', 'resources', resources); + $('#calendar').fullCalendar('refetchResources'); + } + }); + + // ----------------------------- + // Load Events + // ----------------------------- + const eventsUrl = `${apiBase}/sessions/calendar?start=${startDate}&end=${endDate}`; $('#calendar').fullCalendar('removeEventSources'); - $('#calendar').fullCalendar('addEventSource', { url: `php/server/events.php?period=${period}&start=${startDate}&end=${endDate}&action=getEventsCalendar` }); + $('#calendar').fullCalendar('addEventSource', { + url: eventsUrl, + method: "GET", + headers: { + "Authorization": `Bearer ${apiToken}` + }, + success: function(response) { + // Flask returns { "sessions": [...] } → FullCalendar needs array + const events = response.sessions || []; + $('#calendar').fullCalendar('removeEvents'); + $('#calendar').fullCalendar('renderEvents', events, true); + }, + error: function(err) { + console.error('Failed to load events:', err); + } + }); }; + + diff --git a/server/models/device_instance.py b/server/models/device_instance.py index 91812075..3d3a486c 100755 --- a/server/models/device_instance.py +++ b/server/models/device_instance.py @@ -176,10 +176,10 @@ class DeviceInstance: if "*" in mac: # Wildcard matching sql_pattern = mac.replace("*", "%") - cur.execute("DELETE FROM Devices WHERE devMAC LIKE ?", (sql_pattern,)) + cur.execute("DELETE FROM Devices WHERE devMac LIKE ?", (sql_pattern,)) else: # Exact match - cur.execute("DELETE FROM Devices WHERE devMAC = ?", (mac,)) + cur.execute("DELETE FROM Devices WHERE devMac = ?", (mac,)) deleted_count += cur.rowcount conn.commit() @@ -191,7 +191,7 @@ class DeviceInstance: """Delete devices with empty MAC addresses.""" conn = get_temp_db_connection() cur = conn.cursor() - cur.execute("DELETE FROM Devices WHERE devMAC IS NULL OR devMAC = ''") + cur.execute("DELETE FROM Devices WHERE devMac IS NULL OR devMac = ''") deleted = cur.rowcount conn.commit() conn.close()