Skip to content

Commit f6ebbdb

Browse files
authored
Merge pull request #451 from leiweibau/next_update
Next update
2 parents b8fc399 + b4ece9e commit f6ebbdb

22 files changed

+379
-109
lines changed

back/pialert-cli

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
SCRIPTVERSION='v1.30'
2+
SCRIPTVERSION='v1.31'
33
SCRIPT=$(readlink -f $0)
44
SCRIPTPATH=`dirname $SCRIPT`
55
PIA_CONF_FILE=${SCRIPTPATH}'/../config/pialert.conf'
@@ -653,6 +653,41 @@ EOM
653653
# ICMP_Mon_Connections
654654
echo -e "...Insert new table 'ICMP_Mon_Connections' to DB"
655655
sqlite3 $PIA_DB_FILE "CREATE TABLE IF NOT EXISTS 'ICMP_Mon_Connections' ('icmpeve_ip' NUMERIC NOT NULL,'icmpeve_DateTime' TEXT NOT NULL,'icmpeve_Present' INTEGER,'icmpeve_EventType' STRING(50) NOT NULL COLLATE NOCASE, 'icmpeve_AdditionalInfo' STRING(250) DEFAULT (''));"
656+
# Devices.dev_Scan_Validation
657+
echo -e "...Insert new column 'dev_Scan_Validation' to table 'Devices' to DB"
658+
existing=$(sqlite3 $PIA_DB_FILE "PRAGMA table_info('Devices');" | awk -F\| '{print $2}' | grep -wci "dev_Scan_Validation")
659+
if [ $existing -eq 0 ]; then
660+
sqlite3 $PIA_DB_FILE "ALTER TABLE 'Devices' ADD COLUMN 'dev_Scan_Validation' INTEGER NOT NULL DEFAULT 0;"
661+
else
662+
echo " Column 'dev_Scan_Validation' already exists in the 'Devices' table."
663+
fi
664+
# Devices.dev_Scan_Validation_State
665+
echo -e "...Insert new column 'dev_Scan_Validation_State' to table 'Devices' to DB"
666+
existing=$(sqlite3 $PIA_DB_FILE "PRAGMA table_info('Devices');" | awk -F\| '{print $2}' | grep -wci "dev_Scan_Validation_State")
667+
if [ $existing -eq 0 ]; then
668+
sqlite3 $PIA_DB_FILE "ALTER TABLE 'Devices' ADD COLUMN 'dev_Scan_Validation_State' INTEGER NOT NULL DEFAULT 0;"
669+
else
670+
echo " Column 'dev_Scan_Validation_State' already exists in the 'Devices' table."
671+
fi
672+
# ICMP_Mon.icmp_Scan_Validation
673+
echo -e "...Insert new column 'icmp_Scan_Validation' to table 'ICMP_Mon' to DB"
674+
existing=$(sqlite3 $PIA_DB_FILE "PRAGMA table_info('ICMP_Mon');" | awk -F\| '{print $2}' | grep -wci "icmp_Scan_Validation")
675+
if [ $existing -eq 0 ]; then
676+
sqlite3 $PIA_DB_FILE "ALTER TABLE 'ICMP_Mon' ADD COLUMN 'icmp_Scan_Validation' INTEGER NOT NULL DEFAULT 0;"
677+
else
678+
echo " Column 'icmp_Scan_Validation' already exists in the 'ICMP_Mon' table."
679+
fi
680+
# ICMP_Mon.icmp_Scan_Validation_State
681+
echo -e "...Insert new column 'icmp_Scan_Validation_State' to table 'ICMP_Mon' to DB"
682+
existing=$(sqlite3 $PIA_DB_FILE "PRAGMA table_info('ICMP_Mon');" | awk -F\| '{print $2}' | grep -wci "icmp_Scan_Validation_State")
683+
if [ $existing -eq 0 ]; then
684+
sqlite3 $PIA_DB_FILE "ALTER TABLE 'ICMP_Mon' ADD COLUMN 'icmp_Scan_Validation_State' INTEGER NOT NULL DEFAULT 0;"
685+
else
686+
echo " Column 'icmp_Scan_Validation_State' already exists in the 'ICMP_Mon' table."
687+
fi
688+
689+
690+
656691

657692
echo -e "\nUpdate finished!\n"
658693

back/pialert.py

Lines changed: 108 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -891,12 +891,6 @@ def scan_network():
891891
sql_connection.commit()
892892
closeDB()
893893

894-
# Issue #370
895-
# new column for example "dev_alarm_delay" (True/False) and config parameter (2) scan counter
896-
# For devices that are in the “Current_Scan” table and for which “alarm_delay” is set to True,
897-
# “Pending_Alert” is reset if the time interval is less than the desired one.
898-
# maybe a new function like "apply_notifivation_delay()""
899-
900894
# Web Service Monitoring
901895
if SCAN_WEBSERVICES:
902896
if str(startTime)[15] == "0":
@@ -909,8 +903,6 @@ def scan_network():
909903
print('\nLooking for Rogue DHCP Servers...')
910904
rogue_dhcp_detection()
911905

912-
913-
914906
return 0
915907

916908
#-------------------------------------------------------------------------------
@@ -1385,31 +1377,20 @@ def read_openwrt_clients():
13851377
print(' Missing python package')
13861378
return
13871379

1388-
13891380
try:
13901381
router = OpenWrtRpc(str(OPENWRT_IP), str(OPENWRT_USER), str(OPENWRT_PASS))
13911382
result = router.get_all_connected_devices(only_reachable=True)
13921383

1393-
# devices_info = []
1394-
13951384
for device in result:
13961385
if str(device.hostname) == 'None':
13971386
hostname = '(unknown)'
13981387
else:
13991388
hostname = device.hostname
14001389

1401-
# device_data = {
1402-
# 'mac': device.mac,
1403-
# 'hostname': hostname,
1404-
# 'ip': device.ip
1405-
# }
1406-
# devices_info.append(device_data)
1407-
14081390
sql.execute ("INSERT INTO Openwrt_Network (OWRT_MAC, OWRT_IP, UF_Name, OWRT_Vendor) "+
1409-
"VALUES (?, ?, ?, ?) ", (device.mac, device.ip, hostname, '(unknown)') )
1391+
"VALUES (?, ?, ?, ?) ", (device.mac.lower(), device.ip, hostname, '(unknown)') )
14101392

14111393
except Exception as e:
1412-
#print(f"Es ist ein Fehler aufgetreten")
14131394
print(f"Error")
14141395

14151396
#-------------------------------------------------------------------------------
@@ -1566,7 +1547,7 @@ def process_satellites(satellite_list):
15661547

15671548
for result in data['scan_results']:
15681549
if result['cur_ScanMethod'] != 'Internet Check':
1569-
sat_MAC = result['cur_MAC']
1550+
sat_MAC = result['cur_MAC'].lower()
15701551
sat_IP = result['cur_IP']
15711552
sat_hostname = result['cur_hostname']
15721553
sat_Vendor = result['cur_Vendor']
@@ -1654,6 +1635,42 @@ def cleanup_satellite_scans(satellite_list):
16541635
if os.path.exists(WORKING_DIR+token+".json"):
16551636
os.remove(WORKING_DIR+token+".json")
16561637

1638+
#-------------------------------------------------------------------------------
1639+
def update_scan_validation():
1640+
print(' Update Scan Validation...')
1641+
# 1. set dev_Scan_Validation_State to 0 for devices that are in CurrentScan and have dev_Scan_Validation > 0
1642+
sql.execute("""
1643+
UPDATE Devices
1644+
SET dev_Scan_Validation_State = 0
1645+
WHERE dev_Scan_Validation > 0
1646+
AND dev_MAC IN (SELECT cur_MAC FROM CurrentScan)
1647+
""")
1648+
1649+
# 2. find devices to be inserted in CurrentScan and save them in a list
1650+
sql.execute("""
1651+
SELECT dev_ScanCycle, dev_MAC, dev_LastIP, dev_Vendor, dev_ScanSource
1652+
FROM Devices
1653+
WHERE dev_Scan_Validation > 0
1654+
AND dev_Scan_Validation_State < dev_Scan_Validation
1655+
AND dev_MAC NOT IN (SELECT cur_MAC FROM CurrentScan)
1656+
""")
1657+
devices_to_insert = sql.fetchall()
1658+
1659+
# 3. Add the devices to CurrentScan
1660+
sql.executemany("""
1661+
INSERT INTO CurrentScan (cur_ScanCycle, cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod, cur_ScanSource)
1662+
VALUES (?, ?, ?, ?, NULL, ?)
1663+
""", devices_to_insert)
1664+
1665+
# 4. increase dev_Scan_Validation_State by 1 for the devices saved in point 2
1666+
mac_addresses = [device[1] for device in devices_to_insert]
1667+
if mac_addresses:
1668+
sql.executemany("""
1669+
UPDATE Devices
1670+
SET dev_Scan_Validation_State = dev_Scan_Validation_State + 1
1671+
WHERE dev_MAC = ?
1672+
""", [(mac,) for mac in mac_addresses])
1673+
16571674
#-------------------------------------------------------------------------------
16581675
def save_scanned_devices(p_arpscan_devices, p_cycle_interval):
16591676
# Delete previous scan data
@@ -1694,6 +1711,9 @@ def save_scanned_devices(p_arpscan_devices, p_cycle_interval):
16941711
WHERE cur_MAC = Sat_MAC )""",
16951712
(cycle) )
16961713

1714+
# Scan Validation
1715+
update_scan_validation()
1716+
16971717
if not OFFLINE_MODE :
16981718
# Check Internet connectivity
16991719
internet_IP = get_internet_IP()
@@ -2537,7 +2557,6 @@ def rogue_dhcp_detection():
25372557
# Flush Table
25382558
sql.execute("DELETE FROM Nmap_DHCP_Server")
25392559
sql_connection.commit()
2540-
25412560
closeDB()
25422561

25432562
# Execute 15 probes and insert in list
@@ -2547,7 +2566,6 @@ def rogue_dhcp_detection():
25472566
for _ in range(dhcp_probes):
25482567
stream = os.popen('sudo nmap --script broadcast-dhcp-discover 2>/dev/null | grep "Server Identifier" | awk \'{ print $4 }\'')
25492568
output = stream.read()
2550-
# dhcp_server_list.append(output.replace("\n", ""))
25512569

25522570
multiple_dhcp_ips = output.split("\n")
25532571

@@ -3090,12 +3108,8 @@ def icmp_monitoring():
30903108

30913109
closeDB()
30923110
scantime = startTime.strftime("%Y-%m-%d %H:%M")
3093-
30943111
icmp_scan_results = {}
3095-
30963112
icmphosts_all = len(icmphosts)
3097-
icmphosts_online = 0
3098-
icmphosts_offline = 0
30993113

31003114
try:
31013115
ping_retries = ICMP_ONLINE_TEST
@@ -3108,18 +3122,14 @@ def icmp_monitoring():
31083122
while icmphosts_index < icmphosts_all:
31093123
host_ip = icmphosts[icmphosts_index]
31103124
for i in range(ping_retries):
3111-
# print("Host %s retry %s" % (host_ip, str(i+1)))
31123125
icmp_status = ping(host_ip)
31133126
if icmp_status == "1":
31143127
break;
31153128

31163129
if icmp_status == "1":
31173130
icmp_rtt = ping_avg(host_ip)
3118-
# print("Host %s RTT %s" % (host_ip, str(icmp_rtt)))
3119-
icmphosts_online+=1
31203131
else:
31213132
icmp_rtt = "99999"
3122-
icmphosts_offline+=1
31233133

31243134
current_data = {
31253135
"host_ip": host_ip,
@@ -3133,18 +3143,20 @@ def icmp_monitoring():
31333143

31343144
icmphosts_index += 1
31353145

3136-
print(" Online Host(s) : " + str(icmphosts_online))
3137-
print(" Offline Host(s) : " + str(icmphosts_offline))
3138-
31393146
openDB()
31403147
# Save Scan Results
31413148
icmp_save_scandata(icmp_scan_results)
31423149

3150+
update_icmp_validation()
3151+
online, offline = get_online_offline_hosts()
3152+
print(" Online Host(s) : " + str(online))
3153+
print(" Offline Host(s) : " + str(offline))
3154+
31433155
print(" Create Events...")
31443156
icmp_create_events()
31453157

31463158
print(" Calculate Activity History...")
3147-
calc_activity_history_icmp(icmphosts_online, icmphosts_offline)
3159+
calc_activity_history_icmp(online, offline)
31483160

31493161
sql_connection.commit()
31503162
closeDB()
@@ -3153,6 +3165,67 @@ def icmp_monitoring():
31533165
# openDB()
31543166
print(" No Hosts(s) to monitor!")
31553167

3168+
3169+
#-------------------------------------------------------------------------------
3170+
def get_online_offline_hosts():
3171+
sql.execute("""
3172+
SELECT COUNT(*)
3173+
FROM ICMP_Mon_CurrentScan
3174+
WHERE cur_Present = 1
3175+
""")
3176+
icmphosts_online = sql.fetchone()[0]
3177+
3178+
sql.execute("""
3179+
SELECT COUNT(*)
3180+
FROM ICMP_Mon_CurrentScan
3181+
WHERE cur_Present = 0
3182+
""")
3183+
icmphosts_offline = sql.fetchone()[0]
3184+
3185+
return icmphosts_online, icmphosts_offline
3186+
3187+
#-------------------------------------------------------------------------------
3188+
def update_icmp_validation():
3189+
print(' Update ICMP Validation...')
3190+
# 1. Set dev_Scan_Validation_State to 0 for devices that are in Present in CurrentScan and have dev_Scan_Validation > 0
3191+
sql.execute("""
3192+
UPDATE ICMP_Mon
3193+
SET icmp_Scan_Validation_State = 0
3194+
WHERE icmp_Scan_Validation > 0
3195+
AND icmp_ip IN (
3196+
SELECT cur_ip FROM ICMP_Mon_CurrentScan WHERE cur_Present = 1
3197+
);
3198+
""")
3199+
# 2. Find devices in CurrentScan that have activated Scan_Validation and are not currently active
3200+
sql.execute("""
3201+
SELECT cur_ip
3202+
FROM ICMP_Mon_CurrentScan
3203+
WHERE cur_Present = 0
3204+
AND cur_ip IN (
3205+
SELECT icmp_ip
3206+
FROM ICMP_Mon
3207+
WHERE icmp_Scan_Validation > 0
3208+
AND icmp_Scan_Validation_State < icmp_Scan_Validation
3209+
)
3210+
""")
3211+
host_ips = [(row[0],) for row in sql.fetchall()]
3212+
# 3. Set the relevant devices as online
3213+
sql.executemany("""
3214+
UPDATE ICMP_Mon_CurrentScan
3215+
SET cur_Present = 1, cur_PresentChanged = 0, cur_avgrrt = 999
3216+
WHERE cur_ip = ?
3217+
""", host_ips)
3218+
# 4. increase dev_Scan_Validation_State by 1 for the devices saved in point 2
3219+
sql.executemany("""
3220+
UPDATE ICMP_Mon
3221+
SET icmp_Scan_Validation_State = icmp_Scan_Validation_State + 1,
3222+
icmp_PresentLastScan = 1,
3223+
icmp_avgrtt = 999
3224+
WHERE icmp_Scan_Validation > 0 AND icmp_ip = ?
3225+
""", host_ips)
3226+
3227+
sql_connection.commit()
3228+
31563229
# -----------------------------------------------------------------------------
31573230
def icmp_save_scandata(data):
31583231
print(" Save scan results...")
@@ -3163,7 +3236,6 @@ def icmp_save_scandata(data):
31633236

31643237
# -----------------------------------------------------------------------------
31653238
def icmp_create_events():
3166-
31673239
# Check new connections
31683240
print_log ('Events - New Connections')
31693241
sql.execute ("""INSERT INTO ICMP_Mon_Connections (icmpeve_ip, icmpeve_DateTime, icmpeve_Present, icmpeve_EventType)
@@ -3646,9 +3718,6 @@ def email_reporting():
36463718
' <td> <a href="{}{}"> {} </a> </td><td> {} </td>'+ \
36473719
' <td> {} </td><td> {} </td><td> {} </td></tr>\n'
36483720

3649-
# Issue #370
3650-
# AND eve_DateTime < datetime('now', '-{DELAY} minutes') for devices where dev_alarm_delay is true
3651-
36523721
sql.execute ("""SELECT * FROM Events_Devices
36533722
WHERE eve_PendingAlertEmail = 1
36543723
AND eve_EventType = 'Device Down'
@@ -3740,19 +3809,6 @@ def email_reporting():
37403809
sql.execute("""UPDATE Events SET eve_PendingAlertEmail = 0
37413810
WHERE eve_PendingAlertEmail = 1""")
37423811

3743-
# Issue #370
3744-
# Clean Pending Alert Events
3745-
# sql.execute("""UPDATE Devices SET dev_LastNotification = ?
3746-
# WHERE dev_MAC IN (SELECT eve_MAC FROM Events
3747-
# WHERE eve_PendingAlertEmail = 1 AND eve_EventType =='Device Down'
3748-
# AND eve_DateTime < datetime('now', '-{DELAY} minutes')
3749-
# """, (datetime.datetime.now(),))
3750-
# sql.execute ("""UPDATE Events SET eve_PendingAlertEmail = 0
3751-
# WHERE eve_PendingAlertEmail = 1
3752-
# AND eve_EventType =='Device Down'
3753-
# AND eve_DateTime < datetime('now', '-{DELAY} minutes')
3754-
# """)
3755-
37563812
# Set Notification Presets
37573813
sql.execute("""UPDATE Devices SET dev_AlertEvents = ?, dev_AlertDeviceDown = ?
37583814
WHERE dev_NewDevice = 1

config/version.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
VERSION = ''
22
VERSION_YEAR = '2025'
3-
VERSION_DATE = '2025-02-06'
3+
VERSION_DATE = '2025-02-16'

db/pialert.db

0 Bytes
Binary file not shown.

docs/DEVICE_MANAGEMENT.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ To edit device information:
2323
- **Serial Number**: Here you can enter any existing serial number for unique identification
2424
- **Group**: Select a grouper ('Always on', 'Personal', Friends') or type your own Group name
2525
- **Location**: Select a location ('Hall', 'Kitchen', ....) of the device
26+
- **Favorite**: Mark the device as favorite and then it will appears at the begining of the device list
2627
- **Comments**: Type any comments for the device
2728

2829
## Session Info
@@ -51,8 +52,9 @@ To edit device information:
5152
notification to this device for X hours
5253
- *(Useful to avoid notification saturation on devices that frequently
5354
connects and disconnects)*
54-
- **Favorite**: Mark the device as favorite and then it will appears at the
55-
begining of the device list
55+
- **Scan Validation**: The "Scan Validation" parameter determines how many consecutive scans
56+
must detect a device as offline before its status is officially changed to "offline" or
57+
"down." If a validation is pending, the device is marked as "online*" (with an asterisk as an indicator).
5658
- **Show on "Presence"**: The device can be hidden on the “Presence” page,
5759
e.g. to increase the overview or because presence tracking is not necessary.
5860

docs/FIRST_START_GUIDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Various badges can appear in the "Status" column:
2424
- "red" = offline, "Down" notification activated
2525
- "gray" = offline
2626
- "green" = online
27+
- "green" = online*, pending Scan Validation
2728
- "yellow, green" = new and online
2829
- "yellow, gray" = new and offline
2930

0 commit comments

Comments
 (0)