diff --git a/Dockerfile b/Dockerfile index b45a328f..02d225a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,8 @@ ENV USER=pi USER_ID=1000 USER_GID=1000 TZ=Europe/London PORT=20211 # Todo, do we still need all these packages? I can already see sudo which isn't needed RUN apt-get update \ - && apt-get install --no-install-recommends ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo lighttpd php php-cgi php-fpm php-sqlite3 sqlite3 dnsutils net-tools python iproute2 nmap -y \ + && apt-get install --no-install-recommends ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo lighttpd php php-cgi php-fpm php-sqlite3 sqlite3 dnsutils net-tools python iproute2 nmap python-pip -y \ + && pip install requests \ && apt-get clean autoclean \ && apt-get autoremove \ && rm -rf /var/lib/apt/lists/* \ diff --git a/README.md b/README.md index 5a9c074b..42901f45 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ A web frontal that allows: With the work of [jokob-sk/Pi.Alert](https://github.com/jokob-sk/Pi.Alert) and own extensions, the new maintenance page was added with various possibilities for maintenance and settings: - Status Infos (active scans, database size, backup counter) - Theme Selection (blue, red, green, yellow, black, purple) - - Language Selection (english, german) + - Language Selection (english, german, spanish) - Light/Dark-Mode Switch - Pause arp-scan - DB maintenance tools diff --git a/back/pialert.py b/back/pialert.py index b322a6f1..3cc7c5bb 100644 --- a/back/pialert.py +++ b/back/pialert.py @@ -27,7 +27,7 @@ import socket import io import smtplib import csv - +import requests #=============================================================================== # CONFIG CONSTANTS @@ -356,7 +356,7 @@ def scan_network (): # ScanCycle data cycle_interval = scanCycle_data['cic_EveryXmin'] - arpscan_retries = scanCycle_data['cic_arpscanCycles'] + # arpscan_retries = scanCycle_data['cic_arpscanCycles'] no longer needed # TESTING - Fast scan # arpscan_retries = 1 @@ -364,7 +364,7 @@ def scan_network (): print ('\nScanning...') print (' arp-scan Method...') print_log ('arp-scan starts...') - arpscan_devices = execute_arpscan (arpscan_retries) + arpscan_devices = execute_arpscan () print_log ('arp-scan ends') # DEBUG - print number of rows updated # print (arpscan_devices) @@ -450,7 +450,7 @@ def query_ScanCycle_Data (pOpenCloseDB = False): return sqlRow #------------------------------------------------------------------------------- -def execute_arpscan (pRetries): +def execute_arpscan (): # #101 - arp-scan subnet configuration # Prepare command arguments @@ -465,7 +465,7 @@ def execute_arpscan (pRetries): # Rolled back line(FROM) : #arpscan_args = ['sudo', 'arp-scan', '--ignoredups', '--bandwidth=512k', '--retry=3', SCAN_SUBNETS] # Rolled back line(TO) : - arpscan_args = ['sudo', 'arp-scan', '--ignoredups', '--retry=3'] + subnets + arpscan_args = ['sudo', 'arp-scan', '--ignoredups', '--retry=6'] + subnets # ---------------END------------------Rollback-----------------END--------------- # Default arp-scan @@ -711,12 +711,18 @@ def print_scan_stats (): sql.execute("SELECT * FROM Devices") History_All = sql.fetchall() History_All_Devices = len(History_All) + + sql.execute("SELECT * FROM Devices WHERE dev_Archived = 1") + History_Archived = sql.fetchall() + History_Archived_Devices = len(History_Archived) + sql.execute("""SELECT * FROM CurrentScan WHERE cur_ScanCycle = ? """, (cycle,)) History_Online = sql.fetchall() History_Online_Devices = len(History_Online) - History_Offline_Devices = History_All_Devices - History_Online_Devices - sql.execute ("INSERT INTO Online_History (Scan_Date, Online_Devices, Down_Devices, All_Devices) "+ - "VALUES ( ?, ?, ?, ?)", (startTime, History_Online_Devices, History_Offline_Devices, History_All_Devices ) ) + History_Offline_Devices = History_All_Devices - History_Archived_Devices - History_Online_Devices + + sql.execute ("INSERT INTO Online_History (Scan_Date, Online_Devices, Down_Devices, All_Devices, Archived_Devices) "+ + "VALUES ( ?, ?, ?, ?, ?)", (startTime, History_Online_Devices, History_Offline_Devices, History_All_Devices, History_Archived_Devices ) ) #------------------------------------------------------------------------------- def create_new_devices (): @@ -960,11 +966,11 @@ def update_devices_data_from_scan (): recordsToUpdate ) # New Apple devices -> Cycle 15 - print_log ('Update devices - 6 Cycle for Apple devices') - sql.execute ("""UPDATE Devices SET dev_ScanCycle = 15 - WHERE dev_FirstConnection = ? - AND UPPER(dev_Vendor) LIKE '%APPLE%' """, - (startTime,) ) + # print_log ('Update devices - 6 Cycle for Apple devices') + # sql.execute ("""UPDATE Devices SET dev_ScanCycle = 1 + # WHERE dev_FirstConnection = ? + # AND UPPER(dev_Vendor) LIKE '%APPLE%' """, + # (startTime,) ) print_log ('Update devices end') @@ -1192,7 +1198,6 @@ def skip_repeated_notifications (): def email_reporting (): global mail_text global mail_html - # Reporting section print ('\nReporting...') openDB() @@ -1239,7 +1244,7 @@ def email_reporting (): mail_section_Internet = False mail_text_Internet = '' mail_html_Internet = '' - text_line_template = ' {} \t{}\t{}\t{}\n' + text_line_template = '{}\t{}\n{}\t{}\n{}\t{}\n{}\t{}\n\n' html_line_template = '\n'+ \ ' {} \n {} \n'+ \ ' {} \n'+ \ @@ -1249,16 +1254,18 @@ def email_reporting (): WHERE eve_PendingAlertEmail = 1 AND eve_MAC = 'Internet' ORDER BY eve_DateTime""") + for eventAlert in sql : mail_section_Internet = True mail_text_Internet += text_line_template.format ( - eventAlert['eve_EventType'], eventAlert['eve_DateTime'], - eventAlert['eve_IP'], eventAlert['eve_AdditionalInfo']) + 'Event:', eventAlert['eve_EventType'], 'Time:', eventAlert['eve_DateTime'], + 'IP:', eventAlert['eve_IP'], 'More Info:', eventAlert['eve_AdditionalInfo']) mail_html_Internet += html_line_template.format ( REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_EventType'], eventAlert['eve_DateTime'], eventAlert['eve_IP'], eventAlert['eve_AdditionalInfo']) + format_report_section (mail_section_Internet, 'SECTION_INTERNET', 'TABLE_INTERNET', mail_text_Internet, mail_html_Internet) @@ -1266,7 +1273,7 @@ def email_reporting (): mail_section_new_devices = False mail_text_new_devices = '' mail_html_new_devices = '' - text_line_template = ' {}\t{}\t{}\t{}\t{}\n' + text_line_template = '{}\t{}\n\t{}\t{}\n\t{}\t{}\n\t{}\t{}\n\t{}\t{}\n\n' html_line_template = '\n'+ \ ' {} \n {} \n'+\ ' {} \n {} \n {} \n\n' @@ -1279,14 +1286,13 @@ def email_reporting (): for eventAlert in sql : mail_section_new_devices = True mail_text_new_devices += text_line_template.format ( - eventAlert['eve_MAC'], eventAlert['eve_DateTime'], - eventAlert['eve_IP'], eventAlert['dev_Name'], - eventAlert['eve_AdditionalInfo']) + 'Name:', eventAlert['dev_Name'], 'MAC:', eventAlert['eve_MAC'], 'IP:', eventAlert['eve_IP'], + 'Time:', eventAlert['eve_DateTime'], 'More Info:', eventAlert['eve_AdditionalInfo']) mail_html_new_devices += html_line_template.format ( REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'], eventAlert['eve_DateTime'], eventAlert['eve_IP'], eventAlert['dev_Name'], eventAlert['eve_AdditionalInfo']) - + format_report_section (mail_section_new_devices, 'SECTION_NEW_DEVICES', 'TABLE_NEW_DEVICES', mail_text_new_devices, mail_html_new_devices) @@ -1294,7 +1300,7 @@ def email_reporting (): mail_section_devices_down = False mail_text_devices_down = '' mail_html_devices_down = '' - text_line_template = ' {}\t{}\t{}\t{}\n' + text_line_template = '{}\t{}\n\t{}\t{}\n\t{}\t{}\n\t{}\t{}\n\n' html_line_template = '\n'+ \ ' {} \n {} \n'+ \ ' {} \n {} \n\n' @@ -1307,8 +1313,8 @@ def email_reporting (): for eventAlert in sql : mail_section_devices_down = True mail_text_devices_down += text_line_template.format ( - eventAlert['eve_MAC'], eventAlert['eve_DateTime'], - eventAlert['eve_IP'], eventAlert['dev_Name']) + 'Name:', eventAlert['dev_Name'], 'MAC:', eventAlert['eve_MAC'], + 'Time:', eventAlert['eve_DateTime'],'IP:', eventAlert['eve_IP']) mail_html_devices_down += html_line_template.format ( REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'], eventAlert['eve_DateTime'], eventAlert['eve_IP'], @@ -1321,7 +1327,7 @@ def email_reporting (): mail_section_events = False mail_text_events = '' mail_html_events = '' - text_line_template = ' {}\t{}\t{}\t{}\t{}\t{}\n' + text_line_template = '{}\t{}\n\t{}\t{}\n\t{}\t{}\n\t{}\t{}\n\t{}\t{}\n\t{}\t{}\n\n' html_line_template = '\n '+ \ ' {} \n {} \n'+ \ ' {} \n {} \n {} \n'+ \ @@ -1336,9 +1342,9 @@ def email_reporting (): for eventAlert in sql : mail_section_events = True mail_text_events += text_line_template.format ( - eventAlert['eve_MAC'], eventAlert['eve_DateTime'], - eventAlert['eve_IP'], eventAlert['eve_EventType'], - eventAlert['dev_Name'], eventAlert['eve_AdditionalInfo']) + 'Name:', eventAlert['dev_Name'],'Event:', eventAlert['eve_EventType'], + 'MAC:', eventAlert['eve_MAC'], 'IP:', eventAlert['eve_IP'], + 'Time:', eventAlert['eve_DateTime'],'More Info:', eventAlert['eve_AdditionalInfo']) mail_html_events += html_line_template.format ( REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'], eventAlert['eve_DateTime'], eventAlert['eve_IP'], @@ -1361,6 +1367,11 @@ def email_reporting (): send_email (mail_text, mail_html) else : print (' Skip mail...') + if REPORT_NTFY : + print (' Sending report by NTFY...') + send_ntfy (mail_text) + else : + print (' Skip NTFY...') else : print (' No changes to report...') @@ -1379,7 +1390,16 @@ def email_reporting (): # Commit changes sql_connection.commit() closeDB() - +#------------------------------------------------------------------------------- +def send_ntfy (_Text): + requests.post("https://ntfy.sh/{}".format(NTFY_TOPIC), + data=_Text, + headers={ + "Title": "Pi.Alert Notification", + "Click": REPORT_DASHBOARD_URL, + "Priority": "urgent", + "Tags": "warning" + }) #------------------------------------------------------------------------------- def format_report_section (pActive, pSection, pTable, pText, pHTML): global mail_text @@ -1478,6 +1498,7 @@ def upgradeDB (): "Online_Devices" INTEGER, "Down_Devices" INTEGER, "All_Devices" INTEGER, + "Archived_Devices" INTEGER, PRIMARY KEY("Index" AUTOINCREMENT) ); """) diff --git a/back/report_template.html b/back/report_template.html index 0bc0ecc0..e6b340ad 100644 --- a/back/report_template.html +++ b/back/report_template.html @@ -14,20 +14,19 @@ - +
- @@ -36,9 +35,9 @@
+ Pi.Alert Report
- - - - - +
Report Date: Scan Cycle: Server:
+ + +
Report Date: Scan Cycle:
-

Internet:

+

Internet:

- +
@@ -53,11 +52,11 @@ -

New Devices:

+

New Devices:

-
Event Type Datetime
+
- + @@ -71,9 +70,9 @@ -

Devices Down:

+

Devices Down:

-
MAC MAC Datetime IP Device Name
+
@@ -88,9 +87,9 @@ -

Events:

+

Events:

-
MAC Datetime
+
@@ -108,11 +107,10 @@ @@ -120,4 +118,4 @@
MAC Datetime
- +
- + -
© Puche Pi.Alert - Pi.Alert     () GNU GPLv3
- + \ No newline at end of file diff --git a/back/report_template.txt b/back/report_template.txt index 0d777f57..a2943c63 100644 --- a/back/report_template.txt +++ b/back/report_template.txt @@ -1,27 +1,21 @@ -======================================== - Pi.Alert Report -======================================== - - Report Date: - Scan Cycle: - Server: +Report Date: +Scan Cycle: +Server: Internet ----------------------------------------------------------------------- +--------------------- New Devices ----------------------------------------------------------------------- +--------------------- Devices Down ----------------------------------------------------------------------- +--------------------- Events ----------------------------------------------------------------------- +--------------------- ----------------------------------------------------------------------- -(?) Puche Pi.Alert () GNU GPLv3 diff --git a/config/pialert.conf b/config/pialert.conf index 65c0bf03..d5897392 100644 --- a/config/pialert.conf +++ b/config/pialert.conf @@ -23,6 +23,10 @@ REPORT_FROM = 'Pi.Alert <' + SMTP_USER +'>' REPORT_TO = 'user@gmail.com' REPORT_DEVICE_URL = 'http://pi.alert/deviceDetails.php?mac=' +REPORT_NTFY = False +REPORT_DASHBOARD_URL = 'http://pi.alert/' +NTFY_TOPIC = 'replace-my-secure-topicname-91h889f28' + # QUERY_MYIP_SERVER = 'https://diagnostic.opendns.com/myip' QUERY_MYIP_SERVER = 'http://ipv4.icanhazip.com' DDNS_ACTIVE = False diff --git a/config/version.conf b/config/version.conf index 60c442de..7110989f 100644 --- a/config/version.conf +++ b/config/version.conf @@ -1,3 +1,4 @@ VERSION = '3.5_leiweibau' VERSION_YEAR = '2022' VERSION_DATE = '2022-07-07' +TZ = 'Europe/London' \ No newline at end of file diff --git a/docs/img/1_devices_dark.jpg b/docs/img/1_devices_dark.jpg index 808dffe2..1b768f8f 100644 Binary files a/docs/img/1_devices_dark.jpg and b/docs/img/1_devices_dark.jpg differ diff --git a/front/css/dark-patch.css b/front/css/dark-patch.css index 2ea92e6c..7b0ec0cf 100644 --- a/front/css/dark-patch.css +++ b/front/css/dark-patch.css @@ -199,21 +199,6 @@ h4 { .box.box-danger { border-top-width: 3px; } -.box.box-info { - border-top-color: #00c0ef; -} -.box.box-primary { - border-top-color: #075383; -} -.box.box-success { - border-top-color: #00a65a; -} -.box.box-warning { - border-top-color: #ff851b; -} -.box.box-danger { - border-top-color: #dd4b39; -} .main-header .navbar { background-color: #272c30; } @@ -635,7 +620,7 @@ input[type="password"]::-webkit-caps-lock-indicator { } .pa-small-box-gray .inner { background-color: #777; - color: rgba(20,20,20,30%); + /* color: rgba(20,20,20,30%); */ border-top-left-radius: 10px; border-top-right-radius: 10px; } @@ -693,7 +678,7 @@ input[type="password"]::-webkit-caps-lock-indicator { border-bottom-right-radius: 10px; } -.small-box > .inner h3 { +.small-box > .inner h3, .small-box > .inner p { margin-bottom: 0px; margin-left: 0px; } diff --git a/front/css/pialert.css b/front/css/pialert.css index b79da8e4..9f329b8d 100644 --- a/front/css/pialert.css +++ b/front/css/pialert.css @@ -161,7 +161,7 @@ /* -------------------------------------------------------------------------- */ .pa-small-box-aqua { - border-top: 3px solid #00c0ef; + /* border-top: 3px solid #00c0ef; */ box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); } @@ -180,7 +180,7 @@ /* -------------------------------------------------------------------------- */ .pa-small-box-green { - border-top: 3px solid #00a65a; + /* border-top: 3px solid #00a65a; */ box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); } @@ -199,7 +199,7 @@ /* -------------------------------------------------------------------------- */ .pa-small-box-yellow { - border-top: 3px solid #f39c12; + /* border-top: 3px solid #f39c12; */ box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); } @@ -218,7 +218,7 @@ /* -------------------------------------------------------------------------- */ .pa-small-box-red { - border-top: 3px solid #dd4b39; + /* border-top: 3px solid #dd4b39; */ box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); } @@ -237,7 +237,7 @@ /* -------------------------------------------------------------------------- */ .pa-small-box-gray { - border-top: 3px solid #a0a0a0; + /* border-top: 3px solid #a0a0a0; */ box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); } @@ -257,7 +257,7 @@ /* ----------------------------------------------------------------------------- Customized Box Borders ----------------------------------------------------------------------------- */ -.box.box-aqua { +/* .box.box-aqua { border-top-color: #00c0ef; } @@ -271,7 +271,7 @@ .box.box-red { border-top-color: #dd4b39; -} +} */ /* ----------------------------------------------------------------------------- Custom Border @@ -459,7 +459,6 @@ white-space: normal; word-wrap: break-word; font-size: 16px; - border-radius: 10px; padding: 4px; } @@ -527,3 +526,19 @@ background-repeat: no-repeat; background-position: center; height: 50px; } + +.nav-tabs-custom .tab-content { + background-color: white; +} + +.top_small_box_gray_text { + color: white !important; +} + +.bg-gray { + background-color: #b2b6be !important; +} + +.infobox_label { + font-size: 16px !important; +} \ No newline at end of file diff --git a/front/deviceDetails.php b/front/deviceDetails.php index a2d6a500..b5b11762 100644 --- a/front/deviceDetails.php +++ b/front/deviceDetails.php @@ -42,10 +42,11 @@
- @@ -53,10 +54,11 @@
- @@ -64,10 +66,11 @@
- @@ -75,10 +78,11 @@
- @@ -95,7 +99,10 @@
diff --git a/front/devices.php b/front/devices.php index ec388348..3e8563d4 100644 --- a/front/devices.php +++ b/front/devices.php @@ -27,69 +27,74 @@
-
-
-
-
-
-
- @@ -118,7 +123,8 @@ var pia_js_online_history_time = []; var pia_js_online_history_ondev = []; var pia_js_online_history_dodev = []; - pia_draw_graph_online_history(pia_js_online_history_time, pia_js_online_history_ondev, pia_js_online_history_dodev); + var pia_js_online_history_ardev = []; + pia_draw_graph_online_history(pia_js_online_history_time, pia_js_online_history_ondev, pia_js_online_history_dodev, pia_js_online_history_ardev); @@ -223,6 +229,12 @@ function main () { // ----------------------------------------------------------------------------- function initializeDatatable () { + // If the device has a small width (mobile) only show name, ip, and status columns. + if (window.screen.width < 400) { + var tableColumnShow = [10,11,12,1,2,3,4,5,6,8]; + } else { + var tableColumnShow = [10, 11, 12]; + }; var table= $('#tableDevices').DataTable({ 'paging' : true, @@ -240,7 +252,7 @@ function initializeDatatable () { // 'order' : [[3,'desc'], [0,'asc']], 'columnDefs' : [ - {visible: false, targets: [10, 11, 12] }, + {visible: false, targets: tableColumnShow }, {className: 'text-center', targets: [3, 8, 9] }, {width: '80px', targets: [5, 6] }, {width: '0px', targets: 9 }, diff --git a/front/events.php b/front/events.php index feabbb3d..0655c08a 100644 --- a/front/events.php +++ b/front/events.php @@ -40,10 +40,11 @@
- @@ -51,10 +52,11 @@
- @@ -62,10 +64,11 @@
- @@ -73,10 +76,11 @@
- @@ -84,10 +88,11 @@
- @@ -95,10 +100,11 @@
- diff --git a/front/js/graph_online_history.js b/front/js/graph_online_history.js index 65d672bd..268acdc4 100644 --- a/front/js/graph_online_history.js +++ b/front/js/graph_online_history.js @@ -1,24 +1,30 @@ -function pia_draw_graph_online_history(pia_js_graph_online_history_time, pia_js_graph_online_history_ondev, pia_js_graph_online_history_dodev) { +function pia_draw_graph_online_history(pia_js_graph_online_history_time, pia_js_graph_online_history_ondev, pia_js_graph_online_history_dodev, pia_js_graph_online_history_ardev) { var xValues = pia_js_graph_online_history_time; new Chart("OnlineChart", { type: "bar", data: { labels: xValues, datasets: [{ - label: 'Online Devices', + label: 'Online', data: pia_js_graph_online_history_ondev, - borderColor: "#00a65a", + borderColor: "rgba(0, 166, 89)", fill: true, backgroundColor: "rgba(0, 166, 89, .6)", pointStyle: 'circle', pointRadius: 3, pointHoverRadius: 3 }, { - label: 'Offline/Down Devices', + label: 'Offline/Down', data: pia_js_graph_online_history_dodev, - borderColor: "#dd4b39", + borderColor: "rgba(222, 74, 56)", fill: true, backgroundColor: "rgba(222, 74, 56, .6)", + }, { + label: 'Archived', + data: pia_js_graph_online_history_ardev, + borderColor: "rgba(220,220,220)", + fill: true, + backgroundColor: "rgba(220,220,220, .6)", }] }, options: { diff --git a/front/maintenance.php b/front/maintenance.php index 3dbf210a..95761ad1 100644 --- a/front/maintenance.php +++ b/front/maintenance.php @@ -17,7 +17,8 @@ // then accepted. // $pia_installed_langs = array('en_us', - 'de_de'); + 'de_de', + 'es_es'); // // In addition to this, the language must also be added to the select tag in // line 235. Later, the whole thing may become dynamic. @@ -161,14 +162,13 @@ if (submit && isset($_POST['langselector_set'])) { } ?> -

Status

-
+
@@ -206,19 +206,40 @@ if (submit && isset($_POST['langselector_set'])) {
-
-
-
-
-

:

-
-
-
+ +
+
+
+
+ +
@@ -373,7 +349,6 @@ if (submit && isset($_POST['langselector_set'])) { diff --git a/install/pialert.cron b/install/pialert.cron index 9c479ee3..a01b5861 100644 --- a/install/pialert.cron +++ b/install/pialert.cron @@ -10,7 +10,6 @@ TZ=TIMEZONE 0 3 * * 1 python /home/pi/pialert/back/pialert.py update_vendors >/home/pi/pialert/log/pialert.vendors.log 2>&1 -*/1 * * * * python /home/pi/pialert/back/pialert.py internet_IP >/home/pi/pialert/log/pialert.IP.log 2>&1 +*/3 * * * * python /home/pi/pialert/back/pialert.py internet_IP >/home/pi/pialert/log/pialert.IP.log 2>&1 */5 * * * * python /home/pi/pialert/back/pialert.py 1 >/home/pi/pialert/log/pialert.1.log 2>&1 -*/15 * * * * python /home/pi/pialert/back/pialert.py 15 >/home/pi/pialert/log/pialert.15.log 2>&1 */30 * * * * cp /home/pi/pialert/db/pialert.db /home/pi/pialert/config/pialert.db_bak diff --git a/install/pialert_patch_DB.sh b/install/pialert_patch_DB.sh new file mode 100755 index 00000000..fd99ca26 --- /dev/null +++ b/install/pialert_patch_DB.sh @@ -0,0 +1,5 @@ +#!/bin/sh +echo "Create backup before insert new table" +cp ../db/pialert.db ../db/pialert.db.bak +echo "Insert new table 'Online_History' to pialert.db" +sqlite3 ../db/pialert.db "CREATE TABLE 'Online_History' ('Index' INTEGER, 'Scan_Date' TEXT, 'Online_Devices' INTEGER, 'Down_Devices' INTEGER, 'All_Devices' INTEGER, 'Archived_Devices' INTEGER, PRIMARY KEY('Index' AUTOINCREMENT));" diff --git a/tar/pialert_latest.tar b/tar/pialert_latest.tar new file mode 100644 index 00000000..5a86273c Binary files /dev/null and b/tar/pialert_latest.tar differ