mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-03-30 23:03:03 -07:00
BE+FE: Unstable devices list (3 status changes in 1h)
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -314,6 +314,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="devices.php#archived" onclick="forceLoadUrl('devices.php#archived')" > <?= lang("Device_Shortcut_Archived");?> </a>
|
<a href="devices.php#archived" onclick="forceLoadUrl('devices.php#archived')" > <?= lang("Device_Shortcut_Archived");?> </a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="devices.php#unstable_devices" onclick="forceLoadUrl('devices.php#unstable_devices')" > <?= lang("Device_Shortcut_Unstable");?> </a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="devices.php#all_devices" onclick="forceLoadUrl('devices.php#all_devices')" > <?= lang("Gen_All_Devices");?> </a>
|
<a href="devices.php#all_devices" onclick="forceLoadUrl('devices.php#all_devices')" > <?= lang("Gen_All_Devices");?> </a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "المفضلة",
|
"Device_Shortcut_Favorites": "المفضلة",
|
||||||
"Device_Shortcut_NewDevices": "أجهزة جديدة",
|
"Device_Shortcut_NewDevices": "أجهزة جديدة",
|
||||||
"Device_Shortcut_OnlineChart": "مخطط الاتصال",
|
"Device_Shortcut_OnlineChart": "مخطط الاتصال",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "تنبيه عدم الاتصال",
|
"Device_TableHead_AlertDown": "تنبيه عدم الاتصال",
|
||||||
"Device_TableHead_Connected_Devices": "الأجهزة المتصلة",
|
"Device_TableHead_Connected_Devices": "الأجهزة المتصلة",
|
||||||
"Device_TableHead_CustomProps": "خصائص مخصصة",
|
"Device_TableHead_CustomProps": "خصائص مخصصة",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "نظام",
|
"settings_system_label": "نظام",
|
||||||
"settings_update_item_warning": "قم بتحديث القيمة أدناه. احرص على اتباع التنسيق السابق. <b>لم يتم إجراء التحقق.</b>",
|
"settings_update_item_warning": "قم بتحديث القيمة أدناه. احرص على اتباع التنسيق السابق. <b>لم يتم إجراء التحقق.</b>",
|
||||||
"test_event_tooltip": "احفظ التغييرات أولاً قبل اختبار الإعدادات."
|
"test_event_tooltip": "احفظ التغييرات أولاً قبل اختبار الإعدادات."
|
||||||
}
|
}
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favorits",
|
"Device_Shortcut_Favorites": "Favorits",
|
||||||
"Device_Shortcut_NewDevices": "Nous dispositius",
|
"Device_Shortcut_NewDevices": "Nous dispositius",
|
||||||
"Device_Shortcut_OnlineChart": "Dispositius detectats",
|
"Device_Shortcut_OnlineChart": "Dispositius detectats",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Cancel·lar alerta",
|
"Device_TableHead_AlertDown": "Cancel·lar alerta",
|
||||||
"Device_TableHead_Connected_Devices": "Connexions",
|
"Device_TableHead_Connected_Devices": "Connexions",
|
||||||
"Device_TableHead_CustomProps": "Props / Accions",
|
"Device_TableHead_CustomProps": "Props / Accions",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "",
|
"Device_Shortcut_Favorites": "",
|
||||||
"Device_Shortcut_NewDevices": "",
|
"Device_Shortcut_NewDevices": "",
|
||||||
"Device_Shortcut_OnlineChart": "",
|
"Device_Shortcut_OnlineChart": "",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "",
|
"Device_TableHead_AlertDown": "",
|
||||||
"Device_TableHead_Connected_Devices": "",
|
"Device_TableHead_Connected_Devices": "",
|
||||||
"Device_TableHead_CustomProps": "",
|
"Device_TableHead_CustomProps": "",
|
||||||
|
|||||||
@@ -222,6 +222,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favoriten",
|
"Device_Shortcut_Favorites": "Favoriten",
|
||||||
"Device_Shortcut_NewDevices": "Neue Geräte",
|
"Device_Shortcut_NewDevices": "Neue Geräte",
|
||||||
"Device_Shortcut_OnlineChart": "Gerätepräsenz im Laufe der Zeit",
|
"Device_Shortcut_OnlineChart": "Gerätepräsenz im Laufe der Zeit",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Alarm aus",
|
"Device_TableHead_AlertDown": "Alarm aus",
|
||||||
"Device_TableHead_Connected_Devices": "Verbindungen",
|
"Device_TableHead_Connected_Devices": "Verbindungen",
|
||||||
"Device_TableHead_CustomProps": "Eigenschaften / Aktionen",
|
"Device_TableHead_CustomProps": "Eigenschaften / Aktionen",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favorites",
|
"Device_Shortcut_Favorites": "Favorites",
|
||||||
"Device_Shortcut_NewDevices": "New devices",
|
"Device_Shortcut_NewDevices": "New devices",
|
||||||
"Device_Shortcut_OnlineChart": "Device presence",
|
"Device_Shortcut_OnlineChart": "Device presence",
|
||||||
|
"Device_Shortcut_Unstable": "Unstable",
|
||||||
"Device_TableHead_AlertDown": "Alert Down",
|
"Device_TableHead_AlertDown": "Alert Down",
|
||||||
"Device_TableHead_Connected_Devices": "Connections",
|
"Device_TableHead_Connected_Devices": "Connections",
|
||||||
"Device_TableHead_CustomProps": "Props / Actions",
|
"Device_TableHead_CustomProps": "Props / Actions",
|
||||||
|
|||||||
@@ -220,6 +220,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favorito(s)",
|
"Device_Shortcut_Favorites": "Favorito(s)",
|
||||||
"Device_Shortcut_NewDevices": "Nuevos dispositivos",
|
"Device_Shortcut_NewDevices": "Nuevos dispositivos",
|
||||||
"Device_Shortcut_OnlineChart": "Presencia del dispositivo a lo largo del tiempo",
|
"Device_Shortcut_OnlineChart": "Presencia del dispositivo a lo largo del tiempo",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Alerta desactivada",
|
"Device_TableHead_AlertDown": "Alerta desactivada",
|
||||||
"Device_TableHead_Connected_Devices": "Conexiones",
|
"Device_TableHead_Connected_Devices": "Conexiones",
|
||||||
"Device_TableHead_CustomProps": "Propiedades / Acciones",
|
"Device_TableHead_CustomProps": "Propiedades / Acciones",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "",
|
"Device_Shortcut_Favorites": "",
|
||||||
"Device_Shortcut_NewDevices": "",
|
"Device_Shortcut_NewDevices": "",
|
||||||
"Device_Shortcut_OnlineChart": "",
|
"Device_Shortcut_OnlineChart": "",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "",
|
"Device_TableHead_AlertDown": "",
|
||||||
"Device_TableHead_Connected_Devices": "",
|
"Device_TableHead_Connected_Devices": "",
|
||||||
"Device_TableHead_CustomProps": "",
|
"Device_TableHead_CustomProps": "",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favoris",
|
"Device_Shortcut_Favorites": "Favoris",
|
||||||
"Device_Shortcut_NewDevices": "Nouveaux appareils",
|
"Device_Shortcut_NewDevices": "Nouveaux appareils",
|
||||||
"Device_Shortcut_OnlineChart": "Présence de l'appareil",
|
"Device_Shortcut_OnlineChart": "Présence de l'appareil",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Alerter si En panne",
|
"Device_TableHead_AlertDown": "Alerter si En panne",
|
||||||
"Device_TableHead_Connected_Devices": "Connexions",
|
"Device_TableHead_Connected_Devices": "Connexions",
|
||||||
"Device_TableHead_CustomProps": "Champs / Actions",
|
"Device_TableHead_CustomProps": "Champs / Actions",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "Système",
|
"settings_system_label": "Système",
|
||||||
"settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>",
|
"settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>",
|
||||||
"test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage."
|
"test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage."
|
||||||
}
|
}
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Preferiti",
|
"Device_Shortcut_Favorites": "Preferiti",
|
||||||
"Device_Shortcut_NewDevices": "Nuovi dispositivi",
|
"Device_Shortcut_NewDevices": "Nuovi dispositivi",
|
||||||
"Device_Shortcut_OnlineChart": "Presenza dispositivo",
|
"Device_Shortcut_OnlineChart": "Presenza dispositivo",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Avviso disconnessione",
|
"Device_TableHead_AlertDown": "Avviso disconnessione",
|
||||||
"Device_TableHead_Connected_Devices": "Connessioni",
|
"Device_TableHead_Connected_Devices": "Connessioni",
|
||||||
"Device_TableHead_CustomProps": "Proprietà/Azioni",
|
"Device_TableHead_CustomProps": "Proprietà/Azioni",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "Sistema",
|
"settings_system_label": "Sistema",
|
||||||
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
|
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
|
||||||
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni."
|
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni."
|
||||||
}
|
}
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "お気に入り",
|
"Device_Shortcut_Favorites": "お気に入り",
|
||||||
"Device_Shortcut_NewDevices": "新規デバイス",
|
"Device_Shortcut_NewDevices": "新規デバイス",
|
||||||
"Device_Shortcut_OnlineChart": "デバイス検出",
|
"Device_Shortcut_OnlineChart": "デバイス検出",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "ダウンアラート",
|
"Device_TableHead_AlertDown": "ダウンアラート",
|
||||||
"Device_TableHead_Connected_Devices": "接続",
|
"Device_TableHead_Connected_Devices": "接続",
|
||||||
"Device_TableHead_CustomProps": "属性 / アクション",
|
"Device_TableHead_CustomProps": "属性 / アクション",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "システム",
|
"settings_system_label": "システム",
|
||||||
"settings_update_item_warning": "以下の値を更新してください。以前のフォーマットに従うよう注意してください。<b>検証は行われません。</b>",
|
"settings_update_item_warning": "以下の値を更新してください。以前のフォーマットに従うよう注意してください。<b>検証は行われません。</b>",
|
||||||
"test_event_tooltip": "設定をテストする前に、まず変更を保存してください。"
|
"test_event_tooltip": "設定をテストする前に、まず変更を保存してください。"
|
||||||
}
|
}
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favoritter",
|
"Device_Shortcut_Favorites": "Favoritter",
|
||||||
"Device_Shortcut_NewDevices": "Nye Enheter",
|
"Device_Shortcut_NewDevices": "Nye Enheter",
|
||||||
"Device_Shortcut_OnlineChart": "Enhetens tilstedeværelse",
|
"Device_Shortcut_OnlineChart": "Enhetens tilstedeværelse",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "",
|
"Device_TableHead_AlertDown": "",
|
||||||
"Device_TableHead_Connected_Devices": "Tilkoblinger",
|
"Device_TableHead_Connected_Devices": "Tilkoblinger",
|
||||||
"Device_TableHead_CustomProps": "",
|
"Device_TableHead_CustomProps": "",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Ulubione",
|
"Device_Shortcut_Favorites": "Ulubione",
|
||||||
"Device_Shortcut_NewDevices": "Nowe urządzenia",
|
"Device_Shortcut_NewDevices": "Nowe urządzenia",
|
||||||
"Device_Shortcut_OnlineChart": "Obecność urządzenia",
|
"Device_Shortcut_OnlineChart": "Obecność urządzenia",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Alert niedostępny",
|
"Device_TableHead_AlertDown": "Alert niedostępny",
|
||||||
"Device_TableHead_Connected_Devices": "Połączenia",
|
"Device_TableHead_Connected_Devices": "Połączenia",
|
||||||
"Device_TableHead_CustomProps": "Właściwości / Akcje",
|
"Device_TableHead_CustomProps": "Właściwości / Akcje",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favoritos",
|
"Device_Shortcut_Favorites": "Favoritos",
|
||||||
"Device_Shortcut_NewDevices": "Novos dispositivos",
|
"Device_Shortcut_NewDevices": "Novos dispositivos",
|
||||||
"Device_Shortcut_OnlineChart": "Presença do dispositivo",
|
"Device_Shortcut_OnlineChart": "Presença do dispositivo",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Alerta em baixo",
|
"Device_TableHead_AlertDown": "Alerta em baixo",
|
||||||
"Device_TableHead_Connected_Devices": "Conexões",
|
"Device_TableHead_Connected_Devices": "Conexões",
|
||||||
"Device_TableHead_CustomProps": "",
|
"Device_TableHead_CustomProps": "",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favoritos",
|
"Device_Shortcut_Favorites": "Favoritos",
|
||||||
"Device_Shortcut_NewDevices": "Novo dispostivo",
|
"Device_Shortcut_NewDevices": "Novo dispostivo",
|
||||||
"Device_Shortcut_OnlineChart": "Presença do dispositivo",
|
"Device_Shortcut_OnlineChart": "Presença do dispositivo",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Alerta em baixo",
|
"Device_TableHead_AlertDown": "Alerta em baixo",
|
||||||
"Device_TableHead_Connected_Devices": "Conexões",
|
"Device_TableHead_Connected_Devices": "Conexões",
|
||||||
"Device_TableHead_CustomProps": "Propriedades / Ações",
|
"Device_TableHead_CustomProps": "Propriedades / Ações",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Избранные",
|
"Device_Shortcut_Favorites": "Избранные",
|
||||||
"Device_Shortcut_NewDevices": "Новые устройства",
|
"Device_Shortcut_NewDevices": "Новые устройства",
|
||||||
"Device_Shortcut_OnlineChart": "Присутствие устройств",
|
"Device_Shortcut_OnlineChart": "Присутствие устройств",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Оповещение о сост. ВЫКЛ",
|
"Device_TableHead_AlertDown": "Оповещение о сост. ВЫКЛ",
|
||||||
"Device_TableHead_Connected_Devices": "Соединения",
|
"Device_TableHead_Connected_Devices": "Соединения",
|
||||||
"Device_TableHead_CustomProps": "Свойства / Действия",
|
"Device_TableHead_CustomProps": "Свойства / Действия",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "Система",
|
"settings_system_label": "Система",
|
||||||
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
|
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
|
||||||
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
|
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
|
||||||
}
|
}
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "",
|
"Device_Shortcut_Favorites": "",
|
||||||
"Device_Shortcut_NewDevices": "",
|
"Device_Shortcut_NewDevices": "",
|
||||||
"Device_Shortcut_OnlineChart": "",
|
"Device_Shortcut_OnlineChart": "",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "",
|
"Device_TableHead_AlertDown": "",
|
||||||
"Device_TableHead_Connected_Devices": "",
|
"Device_TableHead_Connected_Devices": "",
|
||||||
"Device_TableHead_CustomProps": "",
|
"Device_TableHead_CustomProps": "",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Favoriler",
|
"Device_Shortcut_Favorites": "Favoriler",
|
||||||
"Device_Shortcut_NewDevices": "Yeni Cİhazlar",
|
"Device_Shortcut_NewDevices": "Yeni Cİhazlar",
|
||||||
"Device_Shortcut_OnlineChart": "Cihaz Durumu",
|
"Device_Shortcut_OnlineChart": "Cihaz Durumu",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Çalışmama Alarmı",
|
"Device_TableHead_AlertDown": "Çalışmama Alarmı",
|
||||||
"Device_TableHead_Connected_Devices": "Bağlantılar",
|
"Device_TableHead_Connected_Devices": "Bağlantılar",
|
||||||
"Device_TableHead_CustomProps": "Özellikler / Eylemler",
|
"Device_TableHead_CustomProps": "Özellikler / Eylemler",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "Вибране",
|
"Device_Shortcut_Favorites": "Вибране",
|
||||||
"Device_Shortcut_NewDevices": "Нові пристрої",
|
"Device_Shortcut_NewDevices": "Нові пристрої",
|
||||||
"Device_Shortcut_OnlineChart": "Наявність пристрою",
|
"Device_Shortcut_OnlineChart": "Наявність пристрою",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "Агент Вниз",
|
"Device_TableHead_AlertDown": "Агент Вниз",
|
||||||
"Device_TableHead_Connected_Devices": "Зв'язки",
|
"Device_TableHead_Connected_Devices": "Зв'язки",
|
||||||
"Device_TableHead_CustomProps": "Реквізит / дії",
|
"Device_TableHead_CustomProps": "Реквізит / дії",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "Система",
|
"settings_system_label": "Система",
|
||||||
"settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>",
|
"settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>",
|
||||||
"test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни."
|
"test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни."
|
||||||
}
|
}
|
||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "",
|
"Device_Shortcut_Favorites": "",
|
||||||
"Device_Shortcut_NewDevices": "",
|
"Device_Shortcut_NewDevices": "",
|
||||||
"Device_Shortcut_OnlineChart": "",
|
"Device_Shortcut_OnlineChart": "",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "",
|
"Device_TableHead_AlertDown": "",
|
||||||
"Device_TableHead_Connected_Devices": "",
|
"Device_TableHead_Connected_Devices": "",
|
||||||
"Device_TableHead_CustomProps": "",
|
"Device_TableHead_CustomProps": "",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"Device_Shortcut_Favorites": "收藏",
|
"Device_Shortcut_Favorites": "收藏",
|
||||||
"Device_Shortcut_NewDevices": "新设备",
|
"Device_Shortcut_NewDevices": "新设备",
|
||||||
"Device_Shortcut_OnlineChart": "设备统计",
|
"Device_Shortcut_OnlineChart": "设备统计",
|
||||||
|
"Device_Shortcut_Unstable": "",
|
||||||
"Device_TableHead_AlertDown": "提醒宕机",
|
"Device_TableHead_AlertDown": "提醒宕机",
|
||||||
"Device_TableHead_Connected_Devices": "链接",
|
"Device_TableHead_Connected_Devices": "链接",
|
||||||
"Device_TableHead_CustomProps": "属性",
|
"Device_TableHead_CustomProps": "属性",
|
||||||
@@ -789,4 +790,4 @@
|
|||||||
"settings_system_label": "系统",
|
"settings_system_label": "系统",
|
||||||
"settings_update_item_warning": "更新下面的值。请注意遵循先前的格式。<b>未执行验证。</b>",
|
"settings_update_item_warning": "更新下面的值。请注意遵循先前的格式。<b>未执行验证。</b>",
|
||||||
"test_event_tooltip": "在测试设置之前,请先保存更改。"
|
"test_event_tooltip": "在测试设置之前,请先保存更改。"
|
||||||
}
|
}
|
||||||
@@ -100,6 +100,7 @@ class Device(ObjectType):
|
|||||||
devParentPortSource = String(description="Source tracking for devParentPort (USER, LOCKED, NEWDEV, or plugin prefix)")
|
devParentPortSource = String(description="Source tracking for devParentPort (USER, LOCKED, NEWDEV, or plugin prefix)")
|
||||||
devParentRelTypeSource = String(description="Source tracking for devParentRelType (USER, LOCKED, NEWDEV, or plugin prefix)")
|
devParentRelTypeSource = String(description="Source tracking for devParentRelType (USER, LOCKED, NEWDEV, or plugin prefix)")
|
||||||
devVlanSource = String(description="Source tracking for devVlan")
|
devVlanSource = String(description="Source tracking for devVlan")
|
||||||
|
devFlapping = String(description="ndicates flapping device (device changing between online/offline states frequently)")
|
||||||
|
|
||||||
|
|
||||||
class DeviceResult(ObjectType):
|
class DeviceResult(ObjectType):
|
||||||
@@ -266,7 +267,7 @@ class Query(ObjectType):
|
|||||||
filtered.append(device)
|
filtered.append(device)
|
||||||
|
|
||||||
devices_data = filtered
|
devices_data = filtered
|
||||||
# 🔻 START If you change anything here, also update get_device_condition_by_status
|
# 🔻 START If you change anything here, also update get_device_conditions
|
||||||
elif status == "connected":
|
elif status == "connected":
|
||||||
devices_data = [
|
devices_data = [
|
||||||
device
|
device
|
||||||
@@ -323,7 +324,25 @@ class Query(ObjectType):
|
|||||||
for device in devices_data
|
for device in devices_data
|
||||||
if device["devType"] in network_dev_types and device["devPresentLastScan"] == 0 and device["devIsArchived"] == 0
|
if device["devType"] in network_dev_types and device["devPresentLastScan"] == 0 and device["devIsArchived"] == 0
|
||||||
]
|
]
|
||||||
# 🔺 END If you change anything here, also update get_device_condition_by_status
|
elif status == "unstable_devices":
|
||||||
|
devices_data = [
|
||||||
|
device
|
||||||
|
for device in devices_data
|
||||||
|
if device["devIsArchived"] == 0 and device["devFlapping"] == 1
|
||||||
|
]
|
||||||
|
elif status == "unstable_favorites":
|
||||||
|
devices_data = [
|
||||||
|
device
|
||||||
|
for device in devices_data
|
||||||
|
if device["devIsArchived"] == 0 and device["devFavorite"] == 1 and device["devFlapping"] == 1
|
||||||
|
]
|
||||||
|
elif status == "unstable_network_devices":
|
||||||
|
devices_data = [
|
||||||
|
device
|
||||||
|
for device in devices_data
|
||||||
|
if device["devIsArchived"] == 0 and device["devType"] in network_dev_types and device["devFlapping"] == 1
|
||||||
|
]
|
||||||
|
# 🔺 END If you change anything here, also update get_device_conditions
|
||||||
elif status == "all_devices":
|
elif status == "all_devices":
|
||||||
devices_data = devices_data # keep all
|
devices_data = devices_data # keep all
|
||||||
|
|
||||||
|
|||||||
@@ -58,70 +58,13 @@ NULL_EQUIVALENTS = ["", "null", "(unknown)", "(Unknown)", "(name not found)"]
|
|||||||
# Convert list to SQL string: wrap each value in single quotes and escape single quotes if needed
|
# Convert list to SQL string: wrap each value in single quotes and escape single quotes if needed
|
||||||
NULL_EQUIVALENTS_SQL = ",".join("'" + v.replace("'", "''") + "'" for v in NULL_EQUIVALENTS)
|
NULL_EQUIVALENTS_SQL = ",".join("'" + v.replace("'", "''") + "'" for v in NULL_EQUIVALENTS)
|
||||||
|
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
# SQL queries
|
# SQL queries
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
sql_devices_all = """
|
sql_devices_all = """
|
||||||
SELECT
|
SELECT
|
||||||
rowid,
|
*
|
||||||
IFNULL(devMac, '') AS devMac,
|
FROM DevicesView
|
||||||
IFNULL(devName, '') AS devName,
|
|
||||||
IFNULL(devOwner, '') AS devOwner,
|
|
||||||
IFNULL(devType, '') AS devType,
|
|
||||||
IFNULL(devVendor, '') AS devVendor,
|
|
||||||
IFNULL(devFavorite, '') AS devFavorite,
|
|
||||||
IFNULL(devGroup, '') AS devGroup,
|
|
||||||
IFNULL(devComments, '') AS devComments,
|
|
||||||
IFNULL(devFirstConnection, '') AS devFirstConnection,
|
|
||||||
IFNULL(devLastConnection, '') AS devLastConnection,
|
|
||||||
IFNULL(devLastIP, '') AS devLastIP,
|
|
||||||
IFNULL(devPrimaryIPv4, '') AS devPrimaryIPv4,
|
|
||||||
IFNULL(devPrimaryIPv6, '') AS devPrimaryIPv6,
|
|
||||||
IFNULL(devVlan, '') AS devVlan,
|
|
||||||
IFNULL(devForceStatus, '') AS devForceStatus,
|
|
||||||
IFNULL(devStaticIP, '') AS devStaticIP,
|
|
||||||
IFNULL(devScan, '') AS devScan,
|
|
||||||
IFNULL(devLogEvents, '') AS devLogEvents,
|
|
||||||
IFNULL(devAlertEvents, '') AS devAlertEvents,
|
|
||||||
IFNULL(devAlertDown, '') AS devAlertDown,
|
|
||||||
IFNULL(devSkipRepeated, '') AS devSkipRepeated,
|
|
||||||
IFNULL(devLastNotification, '') AS devLastNotification,
|
|
||||||
IFNULL(devPresentLastScan, 0) AS devPresentLastScan,
|
|
||||||
IFNULL(devIsNew, '') AS devIsNew,
|
|
||||||
IFNULL(devLocation, '') AS devLocation,
|
|
||||||
IFNULL(devIsArchived, '') AS devIsArchived,
|
|
||||||
IFNULL(devParentMAC, '') AS devParentMAC,
|
|
||||||
IFNULL(devParentPort, '') AS devParentPort,
|
|
||||||
IFNULL(devIcon, '') AS devIcon,
|
|
||||||
IFNULL(devGUID, '') AS devGUID,
|
|
||||||
IFNULL(devSite, '') AS devSite,
|
|
||||||
IFNULL(devSSID, '') AS devSSID,
|
|
||||||
IFNULL(devSyncHubNode, '') AS devSyncHubNode,
|
|
||||||
IFNULL(devSourcePlugin, '') AS devSourcePlugin,
|
|
||||||
IFNULL(devCustomProps, '') AS devCustomProps,
|
|
||||||
IFNULL(devFQDN, '') AS devFQDN,
|
|
||||||
IFNULL(devParentRelType, '') AS devParentRelType,
|
|
||||||
IFNULL(devReqNicsOnline, '') AS devReqNicsOnline,
|
|
||||||
IFNULL(devMacSource, '') AS devMacSource,
|
|
||||||
IFNULL(devNameSource, '') AS devNameSource,
|
|
||||||
IFNULL(devFQDNSource, '') AS devFQDNSource,
|
|
||||||
IFNULL(devLastIPSource, '') AS devLastIPSource,
|
|
||||||
IFNULL(devVendorSource, '') AS devVendorSource,
|
|
||||||
IFNULL(devSSIDSource, '') AS devSSIDSource,
|
|
||||||
IFNULL(devParentMACSource, '') AS devParentMACSource,
|
|
||||||
IFNULL(devParentPortSource, '') AS devParentPortSource,
|
|
||||||
IFNULL(devParentRelTypeSource, '') AS devParentRelTypeSource,
|
|
||||||
IFNULL(devVlanSource, '') AS devVlanSource,
|
|
||||||
CASE
|
|
||||||
WHEN devIsNew = 1 THEN 'New'
|
|
||||||
WHEN devPresentLastScan = 1 THEN 'On-line'
|
|
||||||
WHEN devPresentLastScan = 0 AND devAlertDown != 0 THEN 'Down'
|
|
||||||
WHEN devIsArchived = 1 THEN 'Archived'
|
|
||||||
WHEN devPresentLastScan = 0 THEN 'Off-line'
|
|
||||||
ELSE 'Unknown status'
|
|
||||||
END AS devStatus
|
|
||||||
FROM Devices
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
sql_appevents = """select * from AppEvents order by DateTimeCreated desc"""
|
sql_appevents = """select * from AppEvents order by DateTimeCreated desc"""
|
||||||
|
|||||||
@@ -14,22 +14,28 @@ from const import NULL_EQUIVALENTS_SQL # noqa: E402 [flake8 lint suppression]
|
|||||||
def get_device_conditions():
|
def get_device_conditions():
|
||||||
network_dev_types = ",".join("'" + v.replace("'", "''") + "'" for v in get_setting_value("NETWORK_DEVICE_TYPES"))
|
network_dev_types = ",".join("'" + v.replace("'", "''") + "'" for v in get_setting_value("NETWORK_DEVICE_TYPES"))
|
||||||
|
|
||||||
# DO NOT CHANGE ORDER
|
# Base archived condition
|
||||||
|
base_active = "devIsArchived=0"
|
||||||
|
|
||||||
|
# DO NOT CHANGE ORDER - if you add or change something update graphql endpoint as well
|
||||||
conditions = {
|
conditions = {
|
||||||
"all": "WHERE devIsArchived=0",
|
"all": f"WHERE {base_active}",
|
||||||
"my": "WHERE devIsArchived=0",
|
"my": f"WHERE {base_active}",
|
||||||
"connected": "WHERE devPresentLastScan=1",
|
"connected": "WHERE devPresentLastScan=1",
|
||||||
"favorites": "WHERE devIsArchived=0 AND devFavorite=1",
|
"favorites": f"WHERE {base_active} AND devFavorite=1",
|
||||||
"new": "WHERE devIsArchived=0 AND devIsNew=1",
|
"new": f"WHERE {base_active} AND devIsNew=1",
|
||||||
"down": "WHERE devIsArchived=0 AND devAlertDown != 0 AND devPresentLastScan=0",
|
"down": f"WHERE {base_active} AND devAlertDown != 0 AND devPresentLastScan=0",
|
||||||
"offline": "WHERE devIsArchived=0 AND devPresentLastScan=0",
|
"offline": f"WHERE {base_active} AND devPresentLastScan=0",
|
||||||
"archived": "WHERE devIsArchived=1",
|
"archived": "WHERE devIsArchived=1",
|
||||||
"network_devices": f"WHERE devIsArchived=0 AND devType in ({network_dev_types})",
|
"network_devices": f"WHERE {base_active} AND devType IN ({network_dev_types})",
|
||||||
"network_devices_down": f"WHERE devIsArchived=0 AND devType in ({network_dev_types}) AND devPresentLastScan=0",
|
"network_devices_down": f"WHERE {base_active} AND devType IN ({network_dev_types}) AND devPresentLastScan=0",
|
||||||
"unknown": f"WHERE devIsArchived=0 AND devName in ({NULL_EQUIVALENTS_SQL})",
|
"unknown": f"WHERE {base_active} AND devName IN ({NULL_EQUIVALENTS_SQL})",
|
||||||
"known": f"WHERE devIsArchived=0 AND devName not in ({NULL_EQUIVALENTS_SQL})",
|
"known": f"WHERE {base_active} AND devName NOT IN ({NULL_EQUIVALENTS_SQL})",
|
||||||
"favorites_offline": "WHERE devIsArchived=0 AND devFavorite=1 AND devPresentLastScan=0",
|
"favorites_offline": f"WHERE {base_active} AND devFavorite=1 AND devPresentLastScan=0",
|
||||||
"new_online": "WHERE devIsArchived=0 AND devIsNew=1 AND devPresentLastScan=0",
|
"new_online": f"WHERE {base_active} AND devIsNew=1 AND devPresentLastScan=0",
|
||||||
|
"unstable_devices": f"WHERE {base_active} AND devFlapping=1",
|
||||||
|
"unstable_favorites": f"WHERE {base_active} AND devFavorite=1 AND devFlapping=1",
|
||||||
|
"unstable_network_devices": f"WHERE {base_active} AND devType IN ({network_dev_types}) AND devFlapping=1",
|
||||||
}
|
}
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
|
|||||||
@@ -232,6 +232,87 @@ def ensure_views(sql) -> bool:
|
|||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
FLAP_THRESHOLD = 3
|
||||||
|
FLAP_WINDOW_HOURS = 1
|
||||||
|
|
||||||
|
sql.execute(""" DROP VIEW IF EXISTS DevicesView;""")
|
||||||
|
sql.execute(f""" CREATE VIEW DevicesView AS
|
||||||
|
SELECT
|
||||||
|
rowid,
|
||||||
|
IFNULL(devMac, '') AS devMac,
|
||||||
|
IFNULL(devName, '') AS devName,
|
||||||
|
IFNULL(devOwner, '') AS devOwner,
|
||||||
|
IFNULL(devType, '') AS devType,
|
||||||
|
IFNULL(devVendor, '') AS devVendor,
|
||||||
|
IFNULL(devFavorite, '') AS devFavorite,
|
||||||
|
IFNULL(devGroup, '') AS devGroup,
|
||||||
|
IFNULL(devComments, '') AS devComments,
|
||||||
|
IFNULL(devFirstConnection, '') AS devFirstConnection,
|
||||||
|
IFNULL(devLastConnection, '') AS devLastConnection,
|
||||||
|
IFNULL(devLastIP, '') AS devLastIP,
|
||||||
|
IFNULL(devPrimaryIPv4, '') AS devPrimaryIPv4,
|
||||||
|
IFNULL(devPrimaryIPv6, '') AS devPrimaryIPv6,
|
||||||
|
IFNULL(devVlan, '') AS devVlan,
|
||||||
|
IFNULL(devForceStatus, '') AS devForceStatus,
|
||||||
|
IFNULL(devStaticIP, '') AS devStaticIP,
|
||||||
|
IFNULL(devScan, '') AS devScan,
|
||||||
|
IFNULL(devLogEvents, '') AS devLogEvents,
|
||||||
|
IFNULL(devAlertEvents, '') AS devAlertEvents,
|
||||||
|
IFNULL(devAlertDown, '') AS devAlertDown,
|
||||||
|
IFNULL(devSkipRepeated, '') AS devSkipRepeated,
|
||||||
|
IFNULL(devLastNotification, '') AS devLastNotification,
|
||||||
|
IFNULL(devPresentLastScan, 0) AS devPresentLastScan,
|
||||||
|
IFNULL(devIsNew, '') AS devIsNew,
|
||||||
|
IFNULL(devLocation, '') AS devLocation,
|
||||||
|
IFNULL(devIsArchived, '') AS devIsArchived,
|
||||||
|
IFNULL(devParentMAC, '') AS devParentMAC,
|
||||||
|
IFNULL(devParentPort, '') AS devParentPort,
|
||||||
|
IFNULL(devIcon, '') AS devIcon,
|
||||||
|
IFNULL(devGUID, '') AS devGUID,
|
||||||
|
IFNULL(devSite, '') AS devSite,
|
||||||
|
IFNULL(devSSID, '') AS devSSID,
|
||||||
|
IFNULL(devSyncHubNode, '') AS devSyncHubNode,
|
||||||
|
IFNULL(devSourcePlugin, '') AS devSourcePlugin,
|
||||||
|
IFNULL(devCustomProps, '') AS devCustomProps,
|
||||||
|
IFNULL(devFQDN, '') AS devFQDN,
|
||||||
|
IFNULL(devParentRelType, '') AS devParentRelType,
|
||||||
|
IFNULL(devReqNicsOnline, '') AS devReqNicsOnline,
|
||||||
|
IFNULL(devMacSource, '') AS devMacSource,
|
||||||
|
IFNULL(devNameSource, '') AS devNameSource,
|
||||||
|
IFNULL(devFQDNSource, '') AS devFQDNSource,
|
||||||
|
IFNULL(devLastIPSource, '') AS devLastIPSource,
|
||||||
|
IFNULL(devVendorSource, '') AS devVendorSource,
|
||||||
|
IFNULL(devSSIDSource, '') AS devSSIDSource,
|
||||||
|
IFNULL(devParentMACSource, '') AS devParentMACSource,
|
||||||
|
IFNULL(devParentPortSource, '') AS devParentPortSource,
|
||||||
|
IFNULL(devParentRelTypeSource, '') AS devParentRelTypeSource,
|
||||||
|
IFNULL(devVlanSource, '') AS devVlanSource,
|
||||||
|
CASE
|
||||||
|
WHEN devIsNew = 1 THEN 'New'
|
||||||
|
WHEN devPresentLastScan = 1 THEN 'On-line'
|
||||||
|
WHEN devPresentLastScan = 0 AND devAlertDown != 0 THEN 'Down'
|
||||||
|
WHEN devIsArchived = 1 THEN 'Archived'
|
||||||
|
WHEN devPresentLastScan = 0 THEN 'Off-line'
|
||||||
|
ELSE 'Unknown status'
|
||||||
|
END AS devStatus,
|
||||||
|
CASE
|
||||||
|
WHEN EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM Events e
|
||||||
|
WHERE e.eve_MAC = Devices.devMac
|
||||||
|
AND e.eve_EventType IN ('Connected','Disconnected','Device Down','Down Reconnected')
|
||||||
|
AND e.eve_DateTime >= datetime('now', '-{FLAP_WINDOW_HOURS} hours')
|
||||||
|
GROUP BY e.eve_MAC
|
||||||
|
HAVING COUNT(*) >= {FLAP_THRESHOLD}
|
||||||
|
)
|
||||||
|
THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END AS devFlapping
|
||||||
|
|
||||||
|
FROM Devices
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ class DeviceInstance:
|
|||||||
for key, condition in conditions.items():
|
for key, condition in conditions.items():
|
||||||
# Make sure the alias is SQL-safe (no spaces or special chars)
|
# Make sure the alias is SQL-safe (no spaces or special chars)
|
||||||
alias = key.replace(" ", "_").lower()
|
alias = key.replace(" ", "_").lower()
|
||||||
sub_queries.append(f'(SELECT COUNT(*) FROM Devices {condition}) AS "{alias}"')
|
sub_queries.append(f'(SELECT COUNT(*) FROM DevicesView {condition}) AS "{alias}"')
|
||||||
|
|
||||||
# Join all sub-selects with commas
|
# Join all sub-selects with commas
|
||||||
query = "SELECT\n " + ",\n ".join(sub_queries)
|
query = "SELECT\n " + ",\n ".join(sub_queries)
|
||||||
@@ -360,7 +360,7 @@ class DeviceInstance:
|
|||||||
for key, condition in conditions.items():
|
for key, condition in conditions.items():
|
||||||
# Make sure the alias is SQL-safe (no spaces or special chars)
|
# Make sure the alias is SQL-safe (no spaces or special chars)
|
||||||
alias = key.replace(" ", "_").lower()
|
alias = key.replace(" ", "_").lower()
|
||||||
sub_queries.append(f'(SELECT COUNT(*) FROM Devices {condition}) AS "{alias}"')
|
sub_queries.append(f'(SELECT COUNT(*) FROM DevicesView {condition}) AS "{alias}"')
|
||||||
|
|
||||||
# Join all sub-selects with commas
|
# Join all sub-selects with commas
|
||||||
query = "SELECT\n " + ",\n ".join(sub_queries)
|
query = "SELECT\n " + ",\n ".join(sub_queries)
|
||||||
@@ -381,7 +381,8 @@ class DeviceInstance:
|
|||||||
# Build condition for SQL
|
# Build condition for SQL
|
||||||
condition = get_device_condition_by_status(status) if status else ""
|
condition = get_device_condition_by_status(status) if status else ""
|
||||||
|
|
||||||
query = f"SELECT * FROM Devices {condition}"
|
# Only DevicesView has devFlapping
|
||||||
|
query = f"SELECT * FROM DevicesView {condition}"
|
||||||
sql.execute(query)
|
sql.execute(query)
|
||||||
|
|
||||||
table_data = []
|
table_data = []
|
||||||
|
|||||||
@@ -218,3 +218,50 @@ class EventInstance:
|
|||||||
|
|
||||||
# Return as list
|
# Return as list
|
||||||
return [row[0], row[1], row[2], row[3], row[4], row[5]]
|
return [row[0], row[1], row[2], row[3], row[4], row[5]]
|
||||||
|
|
||||||
|
def get_unstable_devices(self, hours: int = 1, threshold: int = 3, macs_only: bool = True):
|
||||||
|
"""
|
||||||
|
Return unstable devices based on flap detection.
|
||||||
|
|
||||||
|
A device is considered unstable if it has >= threshold events within the last `hours`.
|
||||||
|
|
||||||
|
Events considered:
|
||||||
|
- Connected
|
||||||
|
- Disconnected
|
||||||
|
- Device Down
|
||||||
|
- Down Reconnected
|
||||||
|
|
||||||
|
Args:
|
||||||
|
hours (int): Time window in hours (default: 1)
|
||||||
|
threshold (int): Minimum number of events to be considered unstable (default: 3)
|
||||||
|
macs_only (bool): If True, return only MAC addresses (set). Otherwise return full rows.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
set[str] OR list[dict]
|
||||||
|
"""
|
||||||
|
|
||||||
|
if hours <= 0 or threshold <= 0:
|
||||||
|
mylog("warn", f"[Events] get_unstable_devices invalid params: hours={hours}, threshold={threshold}")
|
||||||
|
return set() if macs_only else []
|
||||||
|
|
||||||
|
conn = self._conn()
|
||||||
|
|
||||||
|
sql = """
|
||||||
|
SELECT eve_MAC, COUNT(*) as event_count
|
||||||
|
FROM Events
|
||||||
|
WHERE eve_EventType IN ('Connected','Disconnected','Device Down','Down Reconnected')
|
||||||
|
AND eve_DateTime >= datetime('now', ?)
|
||||||
|
GROUP BY eve_MAC
|
||||||
|
HAVING COUNT(*) >= ?
|
||||||
|
"""
|
||||||
|
|
||||||
|
# SQLite expects "-1 hours" format
|
||||||
|
window = f"-{hours} hours"
|
||||||
|
|
||||||
|
rows = conn.execute(sql, (window, threshold)).fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if macs_only:
|
||||||
|
return {row["eve_MAC"] for row in rows}
|
||||||
|
|
||||||
|
return [dict(row) for row in rows]
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class PluginObjectInstance:
|
|||||||
"SELECT * FROM Plugins_Objects WHERE Plugin = ?", (plugin,)
|
"SELECT * FROM Plugins_Objects WHERE Plugin = ?", (plugin,)
|
||||||
)
|
)
|
||||||
|
|
||||||
def getLastNCreatedPerPLugin(self, plugin, entries=1):
|
def getLastNCreatedPerPlugin(self, plugin, entries=1):
|
||||||
return self._fetchall(
|
return self._fetchall(
|
||||||
"""
|
"""
|
||||||
SELECT *
|
SELECT *
|
||||||
|
|||||||
Reference in New Issue
Block a user