#!/bin/bash

# With version 1.6c and above you may use an external configuration file.  Use [-h] to read the Help Section.
# Run the program with the [-config] to create a default configuration file in the directory this script is run from.

###### ZPool & SMART status report with FreeNAS/TrueNAS config backup
### Original script by joeschmuck, modified by Bidelu0hm, then by melp (me)

### Version: v1.3 TrueNAS Scale (Jeff Alperin 12-6-21)

### Version v1.4, v1.5, v1.6 FreeNAS/TrueNAS (joeschmuck)

### Changelog:
# v1.6d (11 September 2022)
#   - Updated gptid text and help text areas (clarifing inforamtion)
#   - Updated the -dump parameter to -dump [all] and included non-SMART attachments.
#   - Added Automatic UDMA_CRC, MultiZone, and Reallocated Sector Compensation to -config advanced option K.
#   - Fixed Warranty Date always showing as expired.
#   - Added He and Raw Read Error Rates to statistical data file.
#   - Added Raw Read Error Rates chart column.
#   - Added compensation for Seagate Seek Error Rates and Raw Read Error Rates.
#   --- Add -monitor function to test if a file is open or not.
#   --- Find other drive test files to test with.
#
# v1.6c (28 August 2022)
#   - Supports external configuration file (but not required).
#   - Completely Configurable by running the script -config parameter (this took a lot of work).
#   - Added HDD/SSDmaxtempovrd variables to combat some bogus SSD values.
#   - Added TLER (SCT) support.
#   - Added support for drives which do not support recording over 65536 hours for SMART Tests and rolls over to start at zero again.
#   - Added -dump parameter to create and email all of the drives smartctl outputs as text file email attachments.
#   - Added support for Helium drives.
#
#
# v1.6: (05 August 2022)
#   Thanks to Jeff, Simon, and Sean for providing me more test data than I could shake a stick at and friendly constructive opinions/advice.
#   - Complete rewrite of the script.  More organized and easier for future updates.
#   - Almost completely got rid of using AWK, earlier versions had way too much programming within the AWK structure.
#   - Reads the drives much less often (3 times each I believe).
#   - Added test input file to parse txt files of smartctl -a output. This will allow for a single drive entry and ability
#   -- for myself or any script writer to identify additional parameters for unrecognized drives.
#   -- Usage: program_name.sh [HDD|SSD|NVM] [inputfile.txt]
#   - Added better support for SAS drives.
#   - Fixed NVMe and SAS Power On Hours for statistical data recording, and other things.
#   - Added Critical and Warning Logs to email output with better descriptive data.
#   - Logs (stored in /tmp/) no longer deleted after execution to aid in troubleshooting, but deleted at the start of the script.
#   - Added HELP file, use program_name.sh [-h] [-help]
#   - Added SCT Error Recovery to the Text Report section.
#   - Added Zpool Size, Free Space, and Temp Min/Max.
#   - Added customizable temperature values and customizable Non-Value fields (use to be coded to "N/A").
#   - Added support for SandForce SSD.
#
# v1.5:
#   - Added NVMe support
#   - Added clearer error reporting for Warning and Critical errors.
#   - Known Problems: The NVMe Power On Time has a comma that I can't get rid of, yet. I want to remove the comma when the data is retrieved.
#   -- NVMe's are not all standardized so I expect tweaks as different drive data arrives.
#   -- onHours that includes a comma will not record correctly in the statistical data file.  This is related to the NVMe problem above.
#   -- Zpool Summary does not indicate Scrub Age warning, likely the entire summary has issues. 
#
#
# v1.4d:
#   - Fixed Scrub In Progress nuisance error when a scrub is in progress.
#   - Added offsetting Reallocated Sectors for four drives.  This should be for testing only. Any drives
#   -- with a significant number of bad sectors should be replaced, just my opinion.
#   - Added Drive Warranty Expiration warning messages and ability to disable the Email Subject line warning.
#   -- NOT TESTED ON OTHER THAN U.S. FORMATTED DATE YYYY-MM-DD.
#   - Added HDD and SSD individual temperature settings.
#   - Changed order of polling Temperature data from HDD/SSD.
#
# v1.4c:
#   - Rewrite to create functions and enable easier editing.
#   - Added Custom Reports.
#   - Added disabling the RAW 'smartctl -a' data appended to the end of the email.
#   - Added sorting drives alphabetically vice the default the OS reports them.
#   - Added RED warning in Device for any single failure in the summary (deviceRedFlag switch controlled).
#   - Added some additional SSD definitions.
#   - Fixed sorting last two SMART Tests, now reports them in proper order.
#   - Fixed detecting "SMART Support is: Enabled", for white spaces.
#   - Changed IGNORE DRIVES to a String Format to clean up and simplify programming.
#   - Added MultiZone_Errors support for up to eight drives.
#   - Added sectorWarn variable to complement the sectorCrit variable.
#   - Added ignoreSeekError variable to ignore some of those wild Seek Error Rate values.
#   - Added ignoreUDMA CRC Errors due to the "Known Problem"
#   - Fixed md5/sha256 error on TrueNAS Scale (only used during config backups).
#   - Added selectable config backup periodicity by day vice every run.
#   - Added Exporting statistical data for trend analysis.
#   -- Can be setup to email statistics weekly, monthly, or not at all.
#   -- The -s switch will run Data Collection Only, no email generated.  Note: Do Not run two instances at once, the temp files do not survive.
#   - Fixed the Capacity to remove the brackets "[]", thanks Jeff Alperin.
#   - Fixed Scrub Age failure due to 1 day or longer repair time, now shows anything >24 hours.
#
#   - Known Problem: One user reported UDMA_CRC_ERRORS is not subtracting correctly, have not been able to personnaly replicate it.
#   -- This error seems to occur around line #1027
#
# v1.4b:
#   - Added SMART test remaining percentage if Last Test has a SMART Test is in progress.
#   - Fix for empty SMART fields, typically for unsupported SSD's.
#   - Added IGNORE SMART Drive so you can ignore specific drives that may cause you weird readings.
#   --- Updated so blank SSD table header is removed when you ignore all the drives (just crazy talk).
# v1.4a:
#   - Fixed report errors for if a SCRUB is in progress, now shows estimated completion time.
#   - Fixed report error for a Canceled SCRUB.
#   - Fixed FreeBSD/Linux use for SCRUB report (minor oversight).
# v1.4:
#   - Run on CRON JOB using /path/multi_report_v1.4.sh
#   - Fixed for automatic running between FreeBSD and Linux Debian (aka SCALE) as of this date.
#   - All SMART Devices will report.
#   - Added conditional Subject Line (Good/Critical/Warning).
#   - Added Automatic SSD Support.
#   --- Some updates may need to be made to fit some of SSD's. Code in the area of about line 530 will
#   --- need to be adjusted to add new attributes for the desired SSD's fields.
#   - UDMA_CRC_ERROR Override because once a drive encounters this type of error, it cannot be cleared
#   --- so you can offset it now vice having an alarm condition for old UDMA_CRC_Errors.
#   - Added listing NON-SMART Supported Drives.  Use only if useful to you, some drives will
#   --- still output some relevant data, many will not.
# v1.3:
#   - Added scrub duration column
#   - Fixed for FreeNAS 11.1 (thanks reven!)
#   - Fixed fields parsed out of zpool status
#   - Buffered zpool status to reduce calls to script
# v1.2:
#   - Added switch for power-on time format
#   - Slimmed down table columns
#   - Fixed some shellcheck errors & other misc stuff
#   - Added .tar.gz to backup file attached to email
#   - (Still coming) Better SSD SMART support
# v1.1:
#   - Config backup now attached to report email
#   - Added option to turn off config backup
#   - Added option to save backup configs in a specified directory
#   - Power-on hours in SMART summary table now listed as YY-MM-DD-HH
#   - Changed filename of config backup to exclude timestamp (just uses datestamp now)
#   - Config backup and checksum files now zipped (was just .tar before; now .tar.gz)
#   - Fixed degrees symbol in SMART table (rendered weird for a lot of people); replaced with a *
#   - Added switch to enable or disable SSDs in SMART table (SSD reporting still needs work)
#   - Added most recent Extended & Short SMART tests in drive details section (only listed one before, whichever was more recent)
#   - Reformatted user-definable parameters section
#   - Added more general comments to code
# v1.0:
#   - Initial release

######### INSTRUCTIONS ON USE OF THIS SCRIPT
#
# This script will perform three main functions:
# 1: Generate a report and send an email on your drive(s) status.
# 2: Create a copy of your Config File and attach to the same email.
# 3: Create a statistical database and attach to the same email.
#
# In order to configure the script properly read over the User-definable Parameters before making any changes.
# Make changes as indicted by the section instructions.
#
# To run the program from the command line, use ./program_name.sh [-h][-s][HDD|SSD|NVM testfile.txt]
#   Normal use is no command line switches.
#   -h or -help = Display Help Information.
#   -s parameter = Just collect statistical data, do not send an email report.
#   HDD|SSD|NVM and testfile.txt = Use testfile.txt in the HDD or SSD or NVM code section to generate a report
#     using a text output file from the smartctl -a of a drive. This feature is for assisting in manual
#     reporgramming the script to recognize new drives.
#     EXAMPLE: multi_report.sh NVM nvm_smart_data.txt
#     NOTE: The input text file MUST be created using "smartctl -a /dev/xxx > output.txt", nothing less will not work properly.
#     -- Additionally, these test files are primarily for my use to help update the script to respond correctly to new drive SMART formats.
#
# Also you need to make the script executable using "chmod +x program_name.sh"

###### User-definable Parameters #######
# The sections below configure the script to your needs.  Please follow the instructions as it will matter, you cannot
# just "wing it".  Configurations are exact.  We use basically three different formats, Variables = TRUE/FALSE,
# Variables = NUMBER, and Variables = Comma Separated Variable (CSV) Strings.  Each variable will have a description
# associated with it, read it carefully.
#
# The default configuration will work right out of the box however one item must be changed, your email address.
# I highly recommend to try out the default setup first and then make changes as desired.  The only two changes
# I recommend is of course your email address, the second is the location of the statistical_data_file.cvs.
#
# Pay attention to any changes you make, accidentally deleting a quote will cause the entire script to fail.
# Do not continue editing the script after the User Definable Section unless you know what you are doing.
#
# This script will not harm your drives.  We are mostly only collecting drive data. All file writes are
# to /tmp space.  One exception: statistical_data_file.cvs is stored in /tmp by default however if you desire
# to maintain this data it must be stored in a dataset (user selected).

###### Email Address ######
# Enter your email address to send the report to.  The from address does not need to be changed.

email="YourEmail@Address.com"
from="TrueNAS@local.com"

###### Custom Hack ######
# Custom Hacks are for users with generally very unsupported drives and the data must be manually manipulated.
# The goal is to not have any script customized so I will look for fixes where I can.
#
# Allowable custom hacks are: mistermanko
custom_hack="none"

### Config File Name and Location ###
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
Config_File_Name="$SCRIPT_DIR/multi_report_config.txt"

###### Zpool Status Summary Table Settings
 
usedWarn=80               # Pool used percentage for CRITICAL color to be used.
scrubAgeWarn=37           # Maximum age (in days) of last pool scrub before CRITICAL color will be used (30 + 7 days for day of week). Default=37.
 
###### Temperature Settings
HDDtempWarn=45            # HDD Drive temp (in C) upper OK limit before a WARNING color/message will be used.
HDDtempCrit=50            # HDD Drive temp (in C) upper OK limit before a CRITICAL color/message will be used.
HDDmaxovrd="true"         # HDD Max Drive Temp Override. This value when "true" will not alarm on any Current Power Cycle Max Temperature Limit.
SSDtempWarn=45            # SSD Drive temp (in C) upper OK limit before a WARNING color/message will be used.
SSDtempCrit=50            # SSD Drive temp (in C) upper OK limit before a CRITICAL color/message will be used.
SSDmaxovrd="true"         # SSD Max Drive Temp Override. This value when "true" will not alarm on any Current Power Cycle Max Temperature Limit.
NVMtempWarn=50            # NVM Drive temp (in C) upper OK limit before a WARNING color/message will be used.
NVMtempCrit=60            # NVM Drive temp (in C) upper OK limit before a CRITICAL color/message will be used.
 
###### SSD/NVMe Specific Settings
 
wearLevelCrit=9           # Wear Level Alarm Setpoint lower OK limit before a WARNING color/message, 9% is the default.
 
###### General Settings
# Output Formats
powerTimeFormat="h"       # Format for power-on hours string, valid options are "ymdh", "ymd", "ym", "y", or "h" (year month day hour).
tempdisplay="*C"          # The format you desire the temperature to be displayed in. Common formats are: "*C", "^C", or "^c". Choose your own.
non_exist_value="---"     # How do you desire non existant data to be displayed.  The Default is "---", popular options are "N/A" or " ".
 
# Ignore or Activate Alarms
ignoreUDMA="false"        # Set to "true" to ignore all UltraDMA CRC Errors for the summary alarm (Email Header) only, errors will appear in the graphical chart.
ignoreSeekError="true"    # Set to "true" to ignore all Seek Error Rate/Health errors.  Default is true.
ignoreReadError="true"    # Set to "true" to ignore all Seek Error Rate/Health errors.  Default is true.
ignoreMultiZone="false"   # Set to "true" to ignore all MultiZone Errors. Default is false.
disableWarranty="true"    # Set to "true to disable email Subject line alerts for any expired warranty alert. The email body will still report the alert.
 
# Disable or Activate Input/Output File Settings
includeSSD="true"         # Set to "true" will engage SSD Automatic Detection and Reporting, false = Disable SSD Automatic Detection and Reporting.
includeNVM="true"         # Set to "true" will engage NVM Automatic Detection and Reporting, false = Disable NVM Automatic Detection and Reporting.
reportnonSMART="true"     # Will force even non-SMART devices to be reported, "true" = normal operation to report non-SMART devices.
disableRAWdata="false"    # Set to "true" to remove the smartctl -a data and non-smart data appended to the normal report.  Default is false.
 
# Media Alarms
sectorsWarn=1             # Number of sectors per drive to allow with errors before WARNING color/message will be used, this value should be less than sectorsCrit.
sectorsCrit=9             # Number of sectors per drive with errors before CRITICAL color/message will be used.
reAllocWarn=0             # Number of Reallocated sector events allowed.  Over this amount is an alarm condition.
multiZoneWarn=0           # Number of MultiZone Errors to allow before a Warning color/message will be used.  Default is 0.
multiZoneCrit=5           # Number of MultiZone Errors to allow before a Warning color/message will be used.  Default is 5.
deviceRedFlag="true"      # Set to "true" to have the Device Column indicate RED for ANY alarm condition.  Default is true.
heliumAlarm="true"        # Set to "true" to set for a critical alarm any He value below 100.  Default is true.
heliumMin=100             # Set to 100 for a zero leak helium result.  An alert will occur below this value.
rawReadWarn=5             # Number of read errors to allow before WARNING color/message will be used, this value should be less than rawReadCrit.
rawReadCrit=100           # Number of read errors to allow before CRITICAL color/message will be used.
seekErrorsWarn=5          # Number of seek errors to allow before WARNING color/message will be used, this value should be less than seekErrorsCrit.
seekErrorsCrit=100        # Number of seek errors to allow before CRITICAL color/message will be used.

# Time-Limited Error Recovery (TLER)
SCT_Drive_Enable="false"  # Set to "true" to send a command to enable SCT on your drives for user defined timeout.
SCT_Warning="TLER_No_Msg" # Set to "all" will generate a Warning Message for all devices not reporting SCT enabled. "TLER" reports only drive which support TLER.
                          # "TLER_No_Msg" will only report for TLER drives and not report a Warning Message if the drive can set TLER on.
SCT_Read_Timeout=70       # Set to the read threshold. Default = 70 = 7.0 seconds.
SCT_Write_Timeout=70      # Set to the write threshold. Default = 70 = 7.0 seconds.
 
# SMART Testing Alarm
testAgeWarn=2             # Maximum age (in days) of last SMART test before CRITICAL color/message will be used.
 
###### Statistical Data File
statistical_data_file="$SCRIPT_DIR/statisticalsmartdata.csv"    # Default location is where the script is located.
expDataEnable="true"      # Set to "true" will save all drive data into a CSV file defined by "statistical_data_file" below.
expDataEmail="true"       # Set to "true" to have an attachment of the file emailed to you. Default is true.
expDataPurge=730          # Set to the number of day you wish to keep in the data.  Older data will be purged. Default is 730 days (2 years). 0=Disable.
expDataEmailSend="Mon"    # Set to the day of the week the statistical report is emailed.  (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)
 
###### FreeNAS config backup settings
configBackup="true"      # Set to "true" to save config backup (which renders next two options operational); "false" to keep disable config backups.
configSendDay="Mon"      # Set to the day of the week the config is emailed.  (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)
saveBackup="false"       # Set to "false" to delete FreeNAS config backup after mail is sent; "true" to keep it in dir below.
backupLocation="/tmp/"   # Directory in which to store the backup FreeNAS config files.
 
########## REPORT CHART CONFIGURATION ##############
 
###### REPORT HEADER TITLE ######
HDDreportTitle="Spinning Rust Summary Report"     # This is the title of the HDD report, change as you desire.
SSDreportTitle="SSD Summary Report"               # This is the title of the SSD report, change as you desire.
NVMreportTitle="NVMe Summary Report"              # This is the title of the NVMe report, change as you desire.
 
### CUSTOM REPORT CONFIGURATION ###
# By default most items are selected. Change the item to false to have it not displayed in the graph, true to have it displayed.
# NOTE: Alarm setpoints are not affected by these settings, this is only what columns of data are to be displayed on the graph.
# I would recommend that you remove columns of data that you don't really care about to make the graph less busy.
 
# For Zpool Status Summary
Zpool_Pool_Name_Title="Pool Name"
Zpool_Status_Title="Status"
Zpool_Pool_Size_Title="Pool Size"
Zpool_Free_Space_Title="Free Space"
Zpool_Used_Space_Title="Space Used"
Zpool_Read_Errors_Title="Read Errors"
Zpool_Write_Errors_Title="Write Errors"
Zpool_Checksum_Errors_Title="Cksum Errors"
Zpool_Scrub_Repaired_Title="Scrub Repaired Bytes"
Zpool_Scrub_Errors_Title="Scrub Errors"
Zpool_Scrub_Age_Title="Last Scrub Age"
Zpool_Scrub_Duration_Title="Last Scrub Duration"
 
# For Hard Drive Section
HDD_Device_ID="true"
HDD_Device_ID_Title="Device ID"
HDD_Serial_Number="true"
HDD_Serial_Number_Title="Serial Number"
HDD_Model_Number="true"
HDD_Model_Number_Title="Model Number"
HDD_Capacity="true"
HDD_Capacity_Title="HDD Capacity"
HDD_Rotational_Rate="true"
HDD_Rotational_Rate_Title="RPM"
HDD_SMART_Status="true"
HDD_SMART_Status_Title="SMART Status"
HDD_Raw_Read_Error_Rate="true"
HDD_Raw_Read_Error_Rate_Title="Raw Error Rate"
HDD_Drive_Temp="true"
HDD_Drive_Temp_Title="Curr Temp"
HDD_Drive_Temp_Min="true"
HDD_Drive_Temp_Min_Title="Temp Min"
HDD_Drive_Temp_Max="true"
HDD_Drive_Temp_Max_Title="Temp Max"
HDD_Power_On_Hours="true"
HDD_Power_On_Hours_Title="Power On Time"
HDD_Start_Stop_Count="true"
HDD_Start_Stop_Count_Title="Start Stop Count"
HDD_Load_Cycle="true"
HDD_Load_Cycle_Title="Load Cycle Count"
HDD_Spin_Retry="true"
HDD_Spin_Retry_Title="Spin Retry Count"
HDD_Reallocated_Sectors="true"
HDD_Reallocated_Sectors_Title="Re-alloc Sects"
HDD_Reallocated_Events="true"
HDD_Reallocated_Events_Title="Re-alloc Evnt"
HDD_Pending_Sectors="true"
HDD_Pending_Sectors_Title="Curr Pend Sects"
HDD_Offline_Uncorrectable="true"
HDD_Offline_Uncorrectable_Title="Offl Unc Sects"
HDD_UDMA_CRC_Errors="true"
HDD_UDMA_CRC_Errors_Title="UDMA CRC Error"
HDD_Seek_Error_Rate="true"
HDD_Seek_Error_Rate_Title="Seek Error Rate"
HDD_MultiZone_Errors="true"
HDD_MultiZone_Errors_Title="Multi Zone Error"
HDD_Helium_Level="true"
HDD_Helium_Level_Title="He Level"
HDD_Last_Test_Age="true"
HDD_Last_Test_Age_Title="Last Test Age"
HDD_Last_Test_Type="true"
HDD_Last_Test_Type_Title="Last Test Type"
 
# For Solid State Drive Section
SSD_Device_ID="true"
SSD_Device_ID_Title="Device ID"
SSD_Serial_Number="true"
SSD_Serial_Number_Title="Serial Number"
SSD_Model_Number="true"
SSD_Model_Number_Title="Model Number"
SSD_Capacity="true"
SSD_Capacity_Title="HDD Capacity"
SSD_SMART_Status="true"
SSD_SMART_Status_Title="SMART Status"
SSD_Drive_Temp="true"
SSD_Drive_Temp_Title="Curr Temp"
SSD_Drive_Temp_Min="true"
SSD_Drive_Temp_Min_Title="Temp Min"
SSD_Drive_Temp_Max="true"
SSD_Drive_Temp_Max_Title="Temp Max"
SSD_Power_On_Hours="true"
SSD_Power_On_Hours_Title="Power On Time"
SSD_Wear_Level="true"
SSD_Wear_Level_Title="Wear Level"
SSD_Reallocated_Sectors="true"
SSD_Reallocated_Sectors_Title="Re-alloc Sects"
SSD_Reallocated_Events="true"
SSD_Reallocated_Events_Title="Re-alloc Evnt"
SSD_Pending_Sectors="true"
SSD_Pending_Sectors_Title="Curr Pend Sects"
SSD_Offline_Uncorrectable="true"
SSD_Offline_Uncorrectable_Title="Offl Unc Sects"
SSD_UDMA_CRC_Errors="true"
SSD_UDMA_CRC_Errors_Title="UDMA CRC Error"
SSD_Last_Test_Age="true"
SSD_Last_Test_Age_Title="Last Test Age"
SSD_Last_Test_Type="true"
SSD_Last_Test_Type_Title="Last Test Type"
 
# For NVMe Drive Section
NVM_Device_ID="true"
NVM_Device_ID_Title="Device ID"
NVM_Serial_Number="true"
NVM_Serial_Number_Title="Serial Number"
NVM_Model_Number="true"
NVM_Model_Number_Title="Model Number"
NVM_Capacity="true"
NVM_Capacity_Title="HDD Capacity"
NVM_SMART_Status="true"
NVM_SMART_Status_Title="SMART Status"
NVM_Critical_Warning="true"
NVM_Critical_Warning_Title="Critical Warning"
NVM_Drive_Temp="true"
NVM_Drive_Temp_Title="Curr Temp"
NVM_Drive_Temp_Min="false"               # I have not found this on an NVMe drive yet, so set to false
NVM_Drive_Temp_Min_Title="Temp Min"
NVM_Drive_Temp_Max="false"               # I have not found this on an NVMe drive yet, so set to false
NVM_Drive_Temp_Max_Title="Temp Max"
NVM_Power_On_Hours="true"
NVM_Power_On_Hours_Title="Power On Time"
NVM_Wear_Level="true"
NVM_Wear_Level_Title="Wear Level"
 
 
###### Drive Ignore List
# What does it do:
#  Use this to list any drives to ignore and remove from the report.  This is very useful for ignoring USB Flash Drives
#  or other drives for which good data is not able to be collected (non-standard).
#
# How to use it:
#  We are using a comma delimited file to identify the drive serial numbers.  You MUST use the exact and full serial
#  number smartctl reports, if there is no identical match then it will not match. Additionally you may list drives
#  from other systems and they will not have any effect on a system where the drive does not exist.  This is great
#  to have one configuration file that can be used on several systems.
#
# Live Example: Ignore_Drives="VMWare,1JUMLBD,21HNSAFC21410E"
 
Ignore_Drives="none"

 
###### Drive UDMA_CRC_Error_Count List
# What does it do:
#  If you have a drive which has an UDMA count other than 0 (zero), this setting will offset the
#  value back to zero for the concerns of monitoring future increases of this specific error. Any match will
#  subtract the given value to report a 0 (zero) value and highlight it in yellow to denote it was overridden.
#  The Warning Title will not be flagged if this is zero'd out in this manner.
#  NOTE: UDMA_CRC_Errors are typically permanently stored in the drive and cannot be reset to zero even though
#        they are frequently caused by a data cable communications error.
#
# How to use it:
#  List each drive by serial number and include the current UDMA_CRC_Error_Count value.
#  The format is very specific and will not work if you wing it, use the Live EXAMPLE.
#
#  Set the FLAG in the FLAGS Section ignoreUDMA to false (the default setting).
#
# If the error count exceeds the limit minus the offset then a warning message will be generated.
# On the Status Report the UDMA CRC Errors block will be YELLOW with a value of 0 for an overridden value.
#   -- NOTE: We are using the colon : as the separator between the drive serial number and the value to change.
#
# Format: variable=Drive_Serial_Number:Current_UDMA_Error_Count and add a comma if you have more than one drive.
#
# The below example shows drive WD-WMC4N2578099 has 1 UDMA_CRC_Error, drive S2X1J90CA48799 has 2 errors.
#
# Live Example: "WD-WMC4N2578099:1,S2X1J90CA48799:2,P02618119268:1"
 
CRC_ERRORS=""

 
###### Multi_Zone_Errors List
# What does it do:
#   This identifies drives with Multi_Zone_Errors which may be irritating people.
#   Multi_Zone_Errors for some drives, not all drives are pretty much meaningless.
#
# How to use it:
#   Use same format as CRC_Errors (see above).
 
MULTI_Zone=""
 
 
#######  Reallocated Sectors Exceptions
# What does it do:
#  This will offset any Reallocated Sectors count by the value provided.
#
#  I do not recommend using this feature as I'm a believer in if you have over 5 bad sectors, odds are the drive will get worse.
#  I'd recommend replacing the drive before complete failure.  But that is your decision.
#
#  Why is it even an option?
#  I use it for testing purposes only but you may want to use it.
#
# How to use it:
#   Use same format as CRC_Errors (see above).
 
BAD_SECTORS=""
 
####### Warranty Expiration Date
# What does it do:
# This section is used to add warranty expirations for designated drives and to create an alert when they expire.
# The date format is YYYY-MM-DD.
#
# Below is an example for the format using my own drives, which yes, are expired.
# As previously stated above, drive serial numbers must be an exact match to what smartctl reports to function.
#
# If the drive does not exist, for example my drives are not on your system, then nothing will happen.
#
# How to use it:
#   Use the format ="Drive_Serial_Number:YYYY-MM-DD" and add a comma if you have more than one drive.
 
DRIVE_WARRANTY="K1JUMLBD:2020-09-30,K1JRSWLD:2020-09-30,K1JUMW4D:2020-09-30,K1GVD84B:2020-10-12"
 

###### Global table of colors
# The colors selected you can change but you will need to look up the proper HEX code for a color.

okColor="#c9ffcc"       # Hex code for color to use in SMART Status column if drives pass (default is light green, #c9ffcc).
warnColor="#f765d0"     # Hex code for WARN color (default is purple, #f765d0).
critColor="#ff0000"     # Hex code for CRITICAL color (default is red, #ff0000).
altColor="#f4f4f4"      # Table background alternates row colors between white and this color (default is light gray, #f4f4f4).
whtColor="#ffffff"      # Hex for White background.
ovrdColor="#ffff66"     # Hex code for Override Yellow.
blueColor="#87ceeb"     # Hex code for Sky Blue, used for the SCRUB In Progress background.
yellowColor="#f1ffad"   # Hex code for pale yellow.

##########################
##########################
###                    ###
###  STOP EDITING THE  ###
###    SCRIPT HERE     ###
###                    ###
##########################
##########################

###### Auto-generated Parameters
softver=$(uname -s)
host=$(hostname -s)
truenas_ver=$(cat /etc/version)
logfile="/tmp/smart_report_body.tmp"
logfile_header="/tmp/smart_report_header.tmp"
logfile_warning="/tmp/smart_report_warning_flag.tmp"
logfile_critical="/tmp/smart_report_critical_flag.tmp"
logfile_warranty="/tmp/smart_report_warranty_flag.tmp"
logfile_messages="/tmp/smart_report_messages.tmp"
boundary="gc0p4Jq0M2Yt08jU534c0p"

if [[ $softver != "Linux" ]]; then
programver="Multi-Report v1.6d-beta dtd 11 September 2022 (TrueNAS Core "$(cat /etc/version | cut -d " " -f1 | sed 's/TrueNAS-//')")"
else
programver="Multi-Report v1.6d-beta dtd 11 September 2022 (TrueNAS Scale "$(cat /etc/version)")"
fi

##########################
##########################
###                    ###
###  PROGRAMING HACKS  ###
###                    ###
##########################
##########################

#Unique progeramming hacks to properly emulate other hardware that is not actually on the system.

VMWareNVME="on"            # Set to "off" normally, "on" to assist in incorrect VMWare reporting.
Silence="on"               # Set to "on" normally, "off" to provide Joe Schmuck troubleshooting feedback while running.

##########################
##########################
###                    ###
###  DEFINE FUNCTIONS  ###
###                    ###
##########################
##########################


##########################
##########################
###                    ###
###  LOAD CONFIG FILE  ###
###                    ###
##########################
##########################

load_config () {

if test -e "$Config_File_Name"; then
if [[ $Silence == "off" ]]; then echo "Loading Config File"; fi

# Arrays start with the letter "x" in their name within the config file and have special handling.

Config_File="$(cat "$Config_File_Name")"
email="$(echo "$Config_File" | grep "email=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"
from="$(echo "$Config_File" | grep "from=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"
HDDreportTitle="$(echo "$Config_File" | grep "HDDreportTitle=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"
SSDreportTitle="$(echo "$Config_File" | grep "SSDreportTitle=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"
NVMreportTitle="$(echo "$Config_File" | grep "NVMreportTitle=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"

# Convert local variables to table format

if [[ "$(echo "$Config_File" | grep "Zpool_Pool_Name_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Pool_Name_Title="$(echo "$Config_File" | grep "Zpool_Pool_Name_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Status_Title="$(echo "$Config_File" | grep "Zpool_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Pool_Size_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Pool_Size_Title="$(echo "$Config_File" | grep "Zpool_Pool_Size_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Free_Space_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Free_Space_Title="$(echo "$Config_File" | grep "Zpool_Free_Space_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Used_Space_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Used_Space_Title="$(echo "$Config_File" | grep "Zpool_Used_Space_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Read_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Read_Errors_Title="$(echo "$Config_File" | grep "Zpool_Read_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Write_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Write_Errors_Title="$(echo "$Config_File" | grep "Zpool_Write_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Checksum_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Checksum_Errors_Title="$(echo "$Config_File" | grep "Zpool_Checksum_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Scrub_Repaired_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Scrub_Repaired_Title="$(echo "$Config_File" | grep "Zpool_Scrub_Repaired_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Scrub_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Scrub_Errors_Title="$(echo "$Config_File" | grep "Zpool_Scrub_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Scrub_Age_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Scrub_Age_Title="$(echo "$Config_File" | grep "Zpool_Scrub_Age_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "Zpool_Scrub_Duration_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Zpool_Scrub_Duration_Title="$(echo "$Config_File" | grep "Zpool_Scrub_Duration_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "HDD_Device_ID=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Device_ID="$(echo "$Config_File" | grep "HDD_Device_ID=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Device_ID_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Device_ID_Title="$(echo "$Config_File" | grep "HDD_Device_ID_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Serial_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Serial_Number="$(echo "$Config_File" | grep "HDD_Serial_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Serial_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Serial_Number_Title="$(echo "$Config_File" | grep "HDD_Serial_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Model_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Model_Number="$(echo "$Config_File" | grep "HDD_Model_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Model_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Model_Number_Title="$(echo "$Config_File" | grep "HDD_Model_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Capacity=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Capacity="$(echo "$Config_File" | grep "HDD_Capacity=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Capacity_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Capacity_Title="$(echo "$Config_File" | grep "HDD_Capacity_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Rotational_Rate=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Rotational_Rate="$(echo "$Config_File" | grep "HDD_Rotational_Rate=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Rotational_Rate_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Rotational_Rate_Title="$(echo "$Config_File" | grep "HDD_Rotational_Rate_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_SMART_Status=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_SMART_Status="$(echo "$Config_File" | grep "HDD_SMART_Status=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_SMART_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_SMART_Status_Title="$(echo "$Config_File" | grep "HDD_SMART_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Drive_Temp=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Drive_Temp="$(echo "$Config_File" | grep "HDD_Drive_Temp=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Drive_Temp_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Drive_Temp_Title="$(echo "$Config_File" | grep "HDD_Drive_Temp_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Drive_Temp_Min=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Drive_Temp_Min="$(echo "$Config_File" | grep "HDD_Drive_Temp_Min=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Drive_Temp_Min_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Drive_Temp_Min_Title="$(echo "$Config_File" | grep "HDD_Drive_Temp_Min_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Drive_Temp_Max=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Drive_Temp_Max="$(echo "$Config_File" | grep "HDD_Drive_Temp_Max=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Drive_Temp_Max_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Drive_Temp_Max_Title="$(echo "$Config_File" | grep "HDD_Drive_Temp_Max_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Power_On_Hours=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Power_On_Hours="$(echo "$Config_File" | grep "HDD_Power_On_Hours=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Power_On_Hours_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Power_On_Hours_Title="$(echo "$Config_File" | grep "HDD_Power_On_Hours_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Start_Stop_Count=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Start_Stop_Count="$(echo "$Config_File" | grep "HDD_Start_Stop_Count=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Start_Stop_Count_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Start_Stop_Count_Title="$(echo "$Config_File" | grep "HDD_Start_Stop_Count_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Load_Cycle=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Load_Cycle="$(echo "$Config_File" | grep "HDD_Load_Cycle=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Load_Cycle_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Load_Cycle_Title="$(echo "$Config_File" | grep "HDD_Load_Cycle_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Spin_Retry=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Spin_Retry="$(echo "$Config_File" | grep "HDD_Spin_Retry=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Spin_Retry_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Spin_Retry_Title="$(echo "$Config_File" | grep "HDD_Spin_Retry_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Reallocated_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Reallocated_Sectors="$(echo "$Config_File" | grep "HDD_Reallocated_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Reallocated_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Reallocated_Sectors_Title="$(echo "$Config_File" | grep "HDD_Reallocated_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Reallocated_Events=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Reallocated_Events="$(echo "$Config_File" | grep "HDD_Reallocated_Events=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Reallocated_Events_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Reallocated_Events_Title="$(echo "$Config_File" | grep "HDD_Reallocated_Events_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Pending_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Pending_Sectors="$(echo "$Config_File" | grep "HDD_Pending_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Pending_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Pending_Sectors_Title="$(echo "$Config_File" | grep "HDD_Pending_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Offline_Uncorrectable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Offline_Uncorrectable="$(echo "$Config_File" | grep "HDD_Offline_Uncorrectable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Offline_Uncorrectable_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Offline_Uncorrectable_Title="$(echo "$Config_File" | grep "HDD_Offline_Uncorrectable_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_UDMA_CRC_Errors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_UDMA_CRC_Errors="$(echo "$Config_File" | grep "HDD_UDMA_CRC_Errors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_UDMA_CRC_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_UDMA_CRC_Errors_Title="$(echo "$Config_File" | grep "HDD_UDMA_CRC_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Seek_Error_Rate=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Seek_Error_Rate="$(echo "$Config_File" | grep "HDD_Seek_Error_Rate=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Seek_Error_Rate_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Seek_Error_Rate_Title="$(echo "$Config_File" | grep "HDD_Seek_Error_Rate_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "HDD_Raw_Read_Error_Rate=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Raw_Read_Error_Rate="$(echo "$Config_File" | grep "HDD_Raw_Read_Error_Rate=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Raw_Read_Error_Rate_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Raw_Read_Error_Rate_Title="$(echo "$Config_File" | grep "HDD_Raw_Read_Error_Rate_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "HDD_MultiZone_Errors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_MultiZone_Errors="$(echo "$Config_File" | grep "HDD_MultiZone_Errors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_MultiZone_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_MultiZone_Errors_Title="$(echo "$Config_File" | grep "HDD_MultiZone_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "HDD_Helium_Level=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Helium_Level="$(echo "$Config_File" | grep "HDD_Helium_Level=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Helium_Level_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Helium_Level_Title="$(echo "$Config_File" | grep "HDD_Helium_Level_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "HDD_Last_Test_Age=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Last_Test_Age="$(echo "$Config_File" | grep "HDD_Last_Test_Age=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Last_Test_Age_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Last_Test_Age_Title="$(echo "$Config_File" | grep "HDD_Last_Test_Age_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Last_Test_Type=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Last_Test_Type="$(echo "$Config_File" | grep "HDD_Last_Test_Type=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDD_Last_Test_Type_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDD_Last_Test_Type_Title="$(echo "$Config_File" | grep "HDD_Last_Test_Type_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "SSD_Device_ID=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Device_ID="$(echo "$Config_File" | grep "SSD_Device_ID=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Device_ID_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Device_ID_Title="$(echo "$Config_File" | grep "SSD_Device_ID_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Serial_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Serial_Number="$(echo "$Config_File" | grep "SSD_Serial_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Serial_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Serial_Number_Title="$(echo "$Config_File" | grep "SSD_Serial_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Model_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Model_Number="$(echo "$Config_File" | grep "SSD_Model_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Model_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Model_Number_Title="$(echo "$Config_File" | grep "SSD_Model_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Capacity=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Capacity="$(echo "$Config_File" | grep "SSD_Capacity=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Capacity_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Capacity_Title="$(echo "$Config_File" | grep "SSD_Capacity_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_SMART_Status=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_SMART_Status="$(echo "$Config_File" | grep "SSD_SMART_Status=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_SMART_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_SMART_Status_Title="$(echo "$Config_File" | grep "SSD_SMART_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Drive_Temp=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Drive_Temp="$(echo "$Config_File" | grep "SSD_Drive_Temp=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Drive_Temp_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Drive_Temp_Title="$(echo "$Config_File" | grep "SSD_Drive_Temp_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Drive_Temp_Min=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Drive_Temp_Min="$(echo "$Config_File" | grep "SSD_Drive_Temp_Min=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Drive_Temp_Min_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Drive_Temp_Min_Title="$(echo "$Config_File" | grep "SSD_Drive_Temp_Min_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Drive_Temp_Max=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Drive_Temp_Max="$(echo "$Config_File" | grep "SSD_Drive_Temp_Max=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Drive_Temp_Max_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Drive_Temp_Max_Title="$(echo "$Config_File" | grep "SSD_Drive_Temp_Max_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Power_On_Hours=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Power_On_Hours="$(echo "$Config_File" | grep "SSD_Power_On_Hours=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Power_On_Hours_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Power_On_Hours_Title="$(echo "$Config_File" | grep "SSD_Power_On_Hours_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Wear_Level=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Wear_Level="$(echo "$Config_File" | grep "SSD_Wear_Level=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Wear_Level_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Wear_Level_Title="$(echo "$Config_File" | grep "SSD_Wear_Level_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Reallocated_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Reallocated_Sectors="$(echo "$Config_File" | grep "SSD_Reallocated_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Reallocated_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Reallocated_Sectors_Title="$(echo "$Config_File" | grep "SSD_Reallocated_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Reallocated_Events=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Reallocated_Events="$(echo "$Config_File" | grep "SSD_Reallocated_Events=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Reallocated_Events_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Reallocated_Events_Title="$(echo "$Config_File" | grep "SSD_Reallocated_Events_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Pending_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Pending_Sectors="$(echo "$Config_File" | grep "SSD_Pending_Sectors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Pending_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Pending_Sectors_Title="$(echo "$Config_File" | grep "SSD_Pending_Sectors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Offline_Uncorrectable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Offline_Uncorrectable="$(echo "$Config_File" | grep "SSD_Offline_Uncorrectable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Offline_Uncorrectable_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Offline_Uncorrectable_Title="$(echo "$Config_File" | grep "SSD_Offline_Uncorrectable_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_UDMA_CRC_Errors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_UDMA_CRC_Errors="$(echo "$Config_File" | grep "SSD_UDMA_CRC_Errors=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_UDMA_CRC_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_UDMA_CRC_Errors_Title="$(echo "$Config_File" | grep "SSD_UDMA_CRC_Errors_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Last_Test_Age=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Last_Test_Age="$(echo "$Config_File" | grep "SSD_Last_Test_Age=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Last_Test_Age_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Last_Test_Age_Title="$(echo "$Config_File" | grep "SSD_Last_Test_Age_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Last_Test_Type=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Last_Test_Type="$(echo "$Config_File" | grep "SSD_Last_Test_Type=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSD_Last_Test_Type_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSD_Last_Test_Type_Title="$(echo "$Config_File" | grep "SSD_Last_Test_Type_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "NVM_Device_ID=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Device_ID="$(echo "$Config_File" | grep "NVM_Device_ID=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Device_ID_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Device_ID_Title="$(echo "$Config_File" | grep "NVM_Device_ID_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Serial_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Serial_Number="$(echo "$Config_File" | grep "NVM_Serial_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Serial_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Serial_Number_Title="$(echo "$Config_File" | grep "NVM_Serial_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Model_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Model_Number="$(echo "$Config_File" | grep "NVM_Model_Number=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Model_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Model_Number_Title="$(echo "$Config_File" | grep "NVM_Model_Number_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "NVM_Capacity=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Capacity="$(echo "$Config_File" | grep "NVM_Capacity=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "NVM_Capacity_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Capacity_Title="$(echo "$Config_File" | grep "NVM_Capacity_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "NVM_SMART_Status=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_SMART_Status="$(echo "$Config_File" | grep "NVM_SMART_Status=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_SMART_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_SMART_Status_Title="$(echo "$Config_File" | grep "NVM_SMART_Status_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Critical_Warning=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Critical_Warning="$(echo "$Config_File" | grep "NVM_Critical_Warning=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Critical_Warning_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Critical_Warning_Title="$(echo "$Config_File" | grep "NVM_Critical_Warning_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Drive_Temp=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Drive_Temp="$(echo "$Config_File" | grep "NVM_Drive_Temp=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Drive_Temp_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Drive_Temp_Title="$(echo "$Config_File" | grep "NVM_Drive_Temp_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Drive_Temp_Min=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Drive_Temp_Min="$(echo "$Config_File" | grep "NVM_Drive_Temp_Min=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Drive_Temp_Min_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Drive_Temp_Min_Title="$(echo "$Config_File" | grep "NVM_Drive_Temp_Min_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Drive_Temp_Max=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Drive_Temp_Max="$(echo "$Config_File" | grep "NVM_Drive_Temp_Max=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Drive_Temp_Max_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Drive_Temp_Max_Title="$(echo "$Config_File" | grep "NVM_Drive_Temp_Max_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Power_On_Hours=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Power_On_Hours="$(echo "$Config_File" | grep "NVM_Power_On_Hours=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Power_On_Hours_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Power_On_Hours_Title="$(echo "$Config_File" | grep "NVM_Power_On_Hours_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Wear_Level=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Wear_Level="$(echo "$Config_File" | grep "NVM_Wear_Level=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVM_Wear_Level_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
NVM_Wear_Level_Title="$(echo "$Config_File" | grep "NVM_Wear_Level_Title=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "Ignore_Drives=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
Ignore_Drives="$(echo "$Config_File" | grep "Ignore_Drives=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

if [[ "$(echo "$Config_File" | grep "CRC_ERRORS=" | cut -d '=' -f 2 | tr -d '"' )" ]]; then
CRC_Errors="$(echo "$Config_File" | grep "CRC_ERRORS=" | cut -d '=' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "MULTI_Zone=" | cut -d '=' -f 2 | tr -d '"' )" ]]; then
Multi_Zone="$(echo "$Config_File" | grep "MULTI_Zone=" | cut -d '=' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "BAD_SECTORS=" | cut -d '=' -f 2 | tr -d '"' )" ]]; then
Bad_Sectors="$(echo "$Config_File" | grep "BAD_SECTORS=" | cut -d '=' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "DRIVE_WARRANTY=" | cut -d '=' -f 2 | tr -d '"' )" ]]; then
Drive_Warranty="$(echo "$Config_File" | grep "DRIVE_WARRANTY=" | cut -d '=' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "usedWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
usedWarn="$(echo "$Config_File" | grep "usedWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "scrubAgeWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
scrubAgeWarn="$(echo "$Config_File" | grep "scrubAgeWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "includeSSD=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
includeSSD="$(echo "$Config_File" | grep "includeSSD=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "includeNVM=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
includeNVM="$(echo "$Config_File" | grep "includeNVM=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "reportnonSMART=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
reportnonSMART="$(echo "$Config_File" | grep "reportnonSMART=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "HDDtempWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
HDDtempWarn="$(echo "$Config_File" | grep "HDDtempWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "HDDtempCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
HDDtempCrit="$(echo "$Config_File" | grep "HDDtempCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "HDDmaxovrd=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
HDDmaxovrd="$(echo "$Config_File" | grep "HDDmaxovrd=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SSDtempWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
SSDtempWarn="$(echo "$Config_File" | grep "SSDtempWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "SSDtempCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
SSDtempCrit="$(echo "$Config_File" | grep "SSDtempCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "SSDmaxovrd=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SSDmaxovrd="$(echo "$Config_File" | grep "SSDmaxovrd=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "NVMtempWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
NVMtempWarn="$(echo "$Config_File" | grep "NVMtempWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "NVMtempCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
NVMtempCrit="$(echo "$Config_File" | grep "NVMtempCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "wearLevelCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
wearLevelCrit="$(echo "$Config_File" | grep "wearLevelCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "sectorsWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
sectorsWarn="$(echo "$Config_File" | grep "sectorsWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "sectorsCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
sectorsCrit="$(echo "$Config_File" | grep "sectorsCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "reAllocWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
reAllocWarn="$(echo "$Config_File" | grep "reAllocWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "multiZoneWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
multiZoneWarn="$(echo "$Config_File" | grep "multiZoneWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "multiZoneCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
multiZoneCrit="$(echo "$Config_File" | grep "multiZoneCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "testAgeWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
testAgeWarn="$(echo "$Config_File" | grep "testAgeWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "powerTimeFormat=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
powerTimeFormat="$(echo "$Config_File" | grep "powerTimeFormat=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "deviceRedFlag=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
deviceRedFlag="$(echo "$Config_File" | grep "deviceRedFlag=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "ignoreMultiZone=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
ignoreMultiZone="$(echo "$Config_File" | grep "ignoreMultiZone=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "ignoreSeekError=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
ignoreSeekError="$(echo "$Config_File" | grep "ignoreSeekError=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "ignoreUDMA=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
ignoreUDMA="$(echo "$Config_File" | grep "ignoreUDMA=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi   
if [[ "$(echo "$Config_File" | grep "expDataEnable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
expDataEnable="$(echo "$Config_File" | grep "expDataEnable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "expDataEmail=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
expDataEmail="$(echo "$Config_File" | grep "expDataEmail=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "expDataPurge=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
expDataPurge="$(echo "$Config_File" | grep "expDataPurge=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "expDataEmailSend=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
expDataEmailSend="$(echo "$Config_File" | grep "expDataEmailSend=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "disableRAWdata=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
disableRAWdata="$(echo "$Config_File" | grep "disableRAWdata=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "disableWarranty=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
disableWarranty="$(echo "$Config_File" | grep "disableWarranty=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "tempdisplay=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
tempdisplay="$(echo "$Config_File" | grep "tempdisplay=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "non_exist_value=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
non_exist_value="$(echo "$Config_File" | grep "non_exist_value=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "statistical_data_file=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
statistical_data_file="$(echo "$Config_File" | grep "statistical_data_file=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "configBackup=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
configBackup="$(echo "$Config_File" | grep "configBackup=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "configSendDay=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
configSendDay="$(echo "$Config_File" | grep "configSendDay=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "saveBackup=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
saveBackup="$(echo "$Config_File" | grep "saveBackup=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "backupLocation=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
backupLocation="$(echo "$Config_File" | grep "backupLocation=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "okColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
okColor="$(echo "$Config_File" | grep "okColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "warnColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
warnColor="$(echo "$Config_File" | grep "warnColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "critColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
critColor="$(echo "$Config_File" | grep "critColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "altColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
altColor="$(echo "$Config_File" | grep "altColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "whtColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
whtColor="$(echo "$Config_File" | grep "whtColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "ovrdColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
ovrdColor="$(echo "$Config_File" | grep "ovrdColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "blueColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
blueColor="$(echo "$Config_File" | grep "blueColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "yellowColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
yellowColor="$(echo "$Config_File" | grep "yellowColor=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SCT_Drive_Enable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SCT_Drive_Enable="$(echo "$Config_File" | grep "SCT_Drive_Enable=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SCT_Warning=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
SCT_Warning="$(echo "$Config_File" | grep "SCT_Warning=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "SCT_Read_Timeout=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
SCT_Read_Timeout="$(echo "$Config_File" | grep "SCT_Read_Timeout=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "SCT_Write_Timeout=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
SCT_Write_Timeout="$(echo "$Config_File" | grep "SCT_Write_Timeout=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "custom_hack=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
custom_hack="$(echo "$Config_File" | grep "custom_hack=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "heliumAlarm=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
heliumAlarm="$(echo "$Config_File" | grep "heliumAlarm=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi
if [[ "$(echo "$Config_File" | grep "heliumMin=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
heliumMin="$(echo "$Config_File" | grep "heliumMin=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "seekErrorsWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
seekErrorsWarn="$(echo "$Config_File" | grep "seekErrorsWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "seekErrorsCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
seekErrorsCrit="$(echo "$Config_File" | grep "seekErrorsCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "rawReadWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
rawReadWarn="$(echo "$Config_File" | grep "rawReadWarn=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "rawReadCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )" ]]; then
rawReadCrit="$(echo "$Config_File" | grep "rawReadCrit=" | cut -d '=' -f 2 | cut -d ' ' -f 1 )"; fi
if [[ "$(echo "$Config_File" | grep "ignoreReadError=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )" ]]; then
ignoreReadError="$(echo "$Config_File" | grep "ignoreReadError=" | cut -d '=' -f 2 | cut -d '"' -f 2 | tr -d '"' )"; fi

else
echo "No Config File Exists"
echo "Checking for a valid email within the script..."
if [[ $email == "YourEmail@Address.com" ]]; then
echo "No Valid Email Address... Recommend running script with the '-config' switch and selecting the N)ew Configuration option... Aborting"
echo " "
exit 1
else
echo "Valid email within the script = "$email", using script parameters..."
echo " "
External_Config="no"
return
fi
fi

}

#################### PURGE EXPORT DATA CSV FILE #######################

purge_exportdata () {
### This routine will purge the "statistical_data_file" of data older then "expDataPurge".

if [[ $Silence == "off" ]]; then echo "Running Purging Routine"; fi

# Delete temp file if it exists
if test -e "/tmp/temp_purge_file.csv"; then
rm "/tmp/temp_purge_file.csv"
# Create the header
  printf "Date,Time,Device ID,Drive Type,Serial Number,SMART Status,Temp,Power On Hours,Wear Level,Start Stop Count,Load Cycle,Spin Retry,Reallocated Sectors,\
ReAllocated Sector Events,Pending Sectors,Offline Uncorrectable,UDMA CRC Errors,Seek Error Rate,Multi Zone Errors,Read Error Rate,Helium Level\n" > "/tmp/temp_purge_file.csv"
fi

 {

input="$statistical_data_file"

if [ $softver != "Linux" ]; then
expireDate=$(date -v -"$expDataPurge"d +%Y/%m/%d)
else
expireDate=$(date -d "$expDataPurge days ago" +%Y/%m/%d) 
fi

awk -v expireDate="$expireDate" '
BEGIN {
  FS=OFS=","
  FPAT = "([^,]+)|(\"[^\"]+\")"
    count=0
 }

data=$1

     {
FS=OFS=" "

if (count !=0) if ($1 >= expireDate) {
  printf ("%s\n", data) >> "/tmp/temp_purge_file.csv"
  }
 ++count
     }

END {
    }
' $input >/dev/null

}
 
cp -R "/tmp/temp_purge_file.csv" "$statistical_data_file"

}


################## EMAIL EXPORT DATA CVS FILE #########################

email_datafile () {
if [[ $Silence == "off" ]]; then echo "Running email_datafile routine"; fi

if [ "$expDataEmail" == "true" ]; then
Now=$(date +"%a")
doit="false"
  case $expDataEmailSend in
    All)
      doit="true"
      ;;
    Mon|Tue|Wed|Thu|Fri|Sat|Sun)
      if [[ "$expDataEmailSend" == "$Now" ]]; then
         doit="true"
      fi
      ;;
    Month)
      if [[ $(date +"%d") == "01" ]]; then
         doit="true"
      fi
      ;;
    *)
      ;;
  esac

  if [[ "$doit" == "true" ]]; then
 (
  # Write MIME section header for file attachment (encoded with base64)
  echo "--${boundary}"
  echo "Content-Type: text/csv"
  echo "Content-Transfer-Encoding: base64"
  echo "Content-Disposition: attachment; filename=Statistical_Data.csv"
  base64 "$statistical_data_file"
  if [[ "$dump_all" == "1" || "$dump_all" == "2" ]]; then echo "--${boundary}"; else echo "--${boundary}--"; fi
 ) >> "$logfile"
  fi

fi

}

#################### GET SMART HARD DRIVES ############################

get_smartHDD_listings () {
### GET non-SSD listing - MUST support SMART
# smartdrives= All Drives that are SMART
# smartdrivesSSD = SSD all SMART
# nonsmartdrives = Any drive not supporting SMART
# nvmedrives = Any drive which contains "NVM"

# Get Hard Drive listing - MUST support SMART
# variable smartdrives
if [[ $Silence == "off" ]]; then echo "Running get_smartHDD_listings routine"; fi

if [[ "$testfile" != "" ]]; then
echo "HDD TEST FILE ROUTINE"
smartdrives="ada50"
return
fi

if [ $softver != "Linux" ]; then

    smartdrives=$(for drive in $(sysctl -n kern.disks); do
      if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && ! [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then

         targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";

### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
      fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
else
    smartdrives=$(for drive in $(fdisk -l | grep "Disk /dev/sd" | cut -c 11-13 | tr '\n' ' '); do
        if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && ! [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
            targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
       fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
fi
if [[ $Silence == "off" ]]; then echo "HDD List:" $smartdrives; fi
}


########################## GET SMART SOLID DISK DRIVES ################################

get_smartSSD_listings () {
if [[ $Silence == "off" ]]; then echo "Running get_smartSSD_listings routine"; fi

# Get SSD listing - MUST suport SMART
# variable smartdrivesSSD
NVME_Present="false"

if [[ "$testfile" != "" ]]; then
echo "SSD TEST FILE ROUTINE"
smartdrivesSSD="ada50"
return
fi

  if [ $softver != "Linux" ]; then
   smartdrivesSSD=$(for drive in $(sysctl -n kern.disks); do
        if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
            targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";

### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
        fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
  else
   smartdrivesSSD=$(for drive in $(fdisk -l | grep "Disk /dev/sd" | cut -c 11-13 | tr '\n' ' '); do
        if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
            targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
        fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
  fi
if [[ $Silence == "off" ]]; then echo "SSD List: " $smartdrivesSSD; fi
}

########################## GET NVMe DRIVES ################################

get_smartNVM_listings () {
if [[ $Silence == "off" ]]; then echo "Running get_smartNVM_listings routine"; fi

# Get NVM listing
# variable smartdrivesNVM

if [[ "$testfile" != "" ]]; then
echo "NVM TEST FILE ROUTINE"
smartdrivesNVM="nvme50"
echo "NVME List: " $smartdrivesNVM
return
fi

  if [ $softver != "Linux" ]; then
   smartdrivesNVM=$(for drive in $(sysctl -n kern.disks); do
        if [ "$(smartctl -i /dev/"${drive}" | grep "NVM")" ]; then
            targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";

### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
        fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
  else
smartdrivesNVM=$(for drive in $(fdisk -l | grep "Disk /dev/nvm" | cut -d ':' -f 1 | cut -d '/' -f 3 | tr '\n' ' '); do
         if [ "$(smartctl -i /dev/"${drive}" | grep "NVM")" ]; then
            targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
        fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
  fi

### Convert nvdx to nvmexx in smartdrivesNVM ###
smartdrivesNVM=$( echo "$smartdrivesNVM" | sed 's/nvd/nvme/g' )
if [[ $Silence == "off" ]]; then echo "NVME List: " $smartdrivesNVM; fi
}


########################## GET OTHER SMART DEVICES ##################################

get_smartOther_listings () {
### Get the non-SSD listing - MUST support SMART
# variable nonsmartdrives
if [[ $Silence == "off" ]]; then echo "Running get_smartOther_listings routine"; fi

if [[ "$testfile" != "" ]]; then
echo "TEST FILE ROUTINE"
nonsmartdrives="ada50"
return
fi


  if [ $softver != "Linux" ]; then
   nonsmartdrives=$(for drive in $(sysctl -n kern.disks); do
        if [ ! "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && [ ! "$(smartctl -i /dev/"${drive}" | grep "NVM")" ]; then
              targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
        fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
  else
   nonsmartdrives=$(for drive in $(fdisk -l | grep "Disk /dev/sd" | cut -c 11-13 | tr '\n' ' '); do
        if [ ! "$(smartctl -i /dev/"${drive}" | grep "SMART support is: Enabled")" ]; then
                  targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
         s="0"
         IFS=',' read -ra ADDR <<< "$Ignore_Drives"
           for i in "${ADDR[@]}"; do
             if [[ $i == $targument ]]; then
                s="1"
                continue
             fi
           done
         if [[ $s == "0" ]]; then
           printf "%s " "${drive}"
         fi
        fi
    done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
  fi
}

########################### FORMAT EMAILS STEP 1 ##########################

email_preformat () {
###### Email pre-formatting
### Set some of the email headers before conditional headers
if [[ $Silence == "off" ]]; then echo "Running email_preformat routine"; fi

(
    echo "MIME-Version: 1.0"
    echo "Content-Type: multipart/mixed; boundary=${boundary}"
) > "$logfile"
}


########################### CONFIGURATION BACKUP ##############################

config_backup () {
if [[ $Silence == "off" ]]; then echo "Running config_backup routine"; fi

###### Config backup (if enabled)
    tarfile="/tmp/config_backup.tar.gz"
    filename="$(date "+FreeNAS_Config_%Y-%m-%d")"
    filename2="Stat_Data"

if [ "$configBackup" == "true" ]; then
 Now=$(date +"%a")
 doit="false"
  case $configSendDay in
    All)
      doit="true"
      ;;
    Mon|Tue|Wed|Thu|Fri|Sat|Sun)
      if [[ "$configSendDay" == "$Now" ]]; then
         doit="true"
      fi
      ;;
    Month)
      if [[ $(date +"%d") == "01" ]]; then
         doit="true"
      fi
      ;;
    *)
      ;;
  esac

  if [[ "$doit" == "true" ]]; then

    # Set up file names, etc for later
    tarfile="/tmp/config_backup.tar.gz"
    filename="$(date "+FreeNAS_Config_%Y-%m-%d")"
    filename2="Stat_Data"
    ### Test config integrity

    if ! [ "$(sqlite3 /data/freenas-v1.db "pragma integrity_check;")" == "ok" ]; then
        # Config integrity check failed, set MIME content type to html and print warning
        (
            echo "--${boundary}"
            echo "Content-Type: text/html"
            echo "<b>Automatic backup of FreeNAS configuration has failed! The configuration file is corrupted!</b>"
            echo "<b>You should correct this problem as soon as possible!</b>"
            echo "<br>"
        ) >> "$logfile"

    else
        # Config integrity check passed; copy config db, generate checksums, make .tar.gz archive
        cp /data/freenas-v1.db "/tmp/${filename}.db"

                   if [ $softver != "Linux" ]; then
                      md5 "/tmp/${filename}.db" > /tmp/config_backup.md5
                      sha256 "/tmp/${filename}.db" > /tmp/config_backup.sha256
                   else
                      md5sum "/tmp/${filename}.db" > /tmp/config_backup.md5
                      sha256sum "/tmp/${filename}.db" > /tmp/config_backup.sha256
                   fi

        (
            cd "/tmp/" || exit;
            tar -czf "${tarfile}" "./${filename}.db" ./config_backup.md5 ./config_backup.sha256;
        )
        (
            # Write MIME section header for file attachment (encoded with base64)
            echo "--${boundary}"
            echo "Content-Type: application/tar+gzip"
            echo "Content-Transfer-Encoding: base64"
            echo "Content-Disposition: attachment; filename=${filename}.tar.gz"
            base64 "$tarfile"
            # Write MIME section header for html content to come below
            echo "--${boundary}"
            echo "Content-Type: text/html"
        ) >> "$logfile"
        # If logfile saving is enabled, copy .tar.gz file to specified location before it (and everything else) is removed below

                if [ "$saveBackup" == "true" ]; then
                  cp "${tarfile}" "${backupLocation}/${filename}.tar.gz"
                fi

        rm "/tmp/${filename}.db"
        rm /tmp/config_backup.md5
        rm /tmp/config_backup.sha256
        rm "${tarfile}"

    fi

else
    (
        echo "--${boundary}"
        echo "Content-Type: text/html"
    ) >> "$logfile"

  fi

else
  # configBackup = false so this is what to do
  # Config backup enabled; set up for html-type content
    (
        echo "--${boundary}"
        echo "Content-Type: text/html"
    ) >> "$logfile"

fi

}


################################## GENERATE ZPOOL REPORT ##################################

zpool_report () {
###### Report Summary Section (html tables)
### zpool status summary table
if [[ $Silence == "off" ]]; then echo "Running zpool_report routine"; fi
(
    # Write HTML table headers to log file; HTML in an email requires 100% in-line styling (no CSS or <style> section), hence the massive tags
echo $programver"<br>Report Run "$(date +%d-%b-%Y)" @ "$timestamp
    echo "<br><br>"
    echo "<table style=\"border: 1px solid black; border-collapse: collapse;\">"
    echo "<tr><th colspan=\"12\" style=\"text-align:center; font-size:20px; height:40px; font-family:courier;\"><span style='color:gray;'>*</span>ZPool Status Report Summary</th></tr>"
    echo "<tr>"
    echo "  <th style=\"text-align:center; width:130px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Pool_Name_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Status_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Pool_Size_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Free_Space_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Used_Space_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Read_Errors_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Write_Errors_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Checksum_Errors_Title"</th>"
    echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Scrub_Repaired_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Scrub_Errors_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Scrub_Age_Title"</th>"
    echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$Zpool_Scrub_Duration_Title"</th>"
    echo "</tr>"
) >> "$logfile"

pools=$(zpool list -H -o name)
poolNum=0
for pool in $pools; do
    # zpool health summary
    status="$(zpool list -H -o health "$pool")"
    # Total all read, write, and checksum errors per pool
    errors="$(zpool status "$pool" | grep -E "(ONLINE|DEGRADED|FAULTED|UNAVAIL|REMOVED)[ \\t]+[0-9]+")"
    readErrors=0
    for err in $(echo "$errors" | awk '{print $3}'); do
        if echo "$err" | grep -E -q "[^0-9]+"; then
            readErrors=1000
            break
        fi
        readErrors=$((readErrors + err))
    done
    writeErrors=0
    for err in $(echo "$errors" | awk '{print $4}'); do
        if echo "$err" | grep -E -q "[^0-9]+"; then
            writeErrors=1000
            break
        fi
        writeErrors=$((writeErrors + err))
    done
    cksumErrors=0
    for err in $(echo "$errors" | awk '{print $5}'); do
        if echo "$err" | grep -E -q "[^0-9]+"; then
            cksumErrors=1000
            break
        fi
        cksumErrors=$((cksumErrors + err))
    done
    # Not sure why this changes values larger than 1000 to ">1K", but I guess it works, so I'm leaving it
    # Answer to question above: Because it formats the value to = ">1K" vice stating very large values to
    # fit into the formatted table.  All we care about is it's way too high.
    if [ "$readErrors" -gt 999 ]; then readErrors=">1K"; fi
    if [ "$writeErrors" -gt 999 ]; then writeErrors=">1K"; fi
    if [ "$cksumErrors" -gt 999 ]; then cksumErrors=">1K"; fi


    # Get used capacity percentage of the zpool
    used="$(zpool list -H -p -o capacity "$pool")"
    pool_size="$(zpool list -H -o size "$pool")"
    pool_free="$(zpool list -H -o free "$pool")"

    # Gather info from most recent scrub; values set to "$non_exist_value" initially and overwritten when (and if) it gathers scrub info
    scrubRepBytes="$non_exist_value"
    scrubErrors="$non_exist_value"
    scrubAge="$non_exist_value"
    scrubTime="$non_exist_value"
    statusOutput="$(zpool status "$pool")"


### Fix for SCRUB lasting longer than 24 hours.
scrubDays="$(echo "$statusOutput" | grep "scan" | awk '{print $7}')"

if [[ $scrubDays == "days" ]]; then
   scrubextra="$(echo "$statusOutput" | grep "scan" | awk '{print $6}')"


### Fix for SCRUB Cancelled and In-Progress

#Check if scrub in progress
if [ "$(echo "$statusOutput" | grep -w "scan" | awk '{print $4}')" = "progress" ]; then
        scrubAge="In Progress"
        scrubTime="$(echo "Est Comp: ")$(echo "$statusOutput" | grep "done, " | awk '{print $5}')"

# Check if the SCRUB is completed or canceled.

elif [ "$(echo "$statusOutput" | grep "scan" | awk '{print $2}')" = "scrub" ] && [ "$(echo "$statusOutput" | grep "scan" | awk '{print $3}')" = "canceled" ]; then
          scrubAge="Canceled"
       elif [ "$(echo "$statusOutput" | grep "scan" | awk '{print $2}')" = "scrub" ]; then
        scrubRepBytes="$(echo "$statusOutput" | grep "scan" | awk '{print $4}')"
        scrubRepBytes="$(echo "$scrubRepBytes" | rev | cut -c2- | rev)"
        scrubErrors="$(echo "$statusOutput" | grep "scan" | awk '{print $10}')"
        # Convert time/datestamp format presented by zpool status, compare to current date, calculate scrub age

# For FreeBSD
   if [ $softver != "Linux" ]; then
        scrubDate="$(echo "$statusOutput" | grep "scan" | awk '{print $17"-"$14"-"$15"_"$16}')"
        scrubTS="$(date -j -f "%Y-%b-%e_%H:%M:%S" "$scrubDate" "+%s")"
   else
# For Linux
        scrubDate="$(echo "$statusOutput" | grep "scan" | awk '{print $14" "$15" "$17" "$16}')"
        scrubTS="$(date --date="$scrubDate" "+%s")"
   fi
        currentTS="$(date "+%s")"
        scrubAge=$((((currentTS - scrubTS) + 43200) / 86400))

        scrubTimetemp="$(echo "$statusOutput" | grep "scan" | awk '{print $8}')"
        scrubTime="$scrubextra days $scrubTimetemp"

        else
        #No scrub previously performed
        scrubAge="Never Scrubbed"
fi

else

#Check if scrub in progress
if [ "$(echo "$statusOutput" | grep -w "scan" | awk '{print $4}')" = "progress" ]; then
        scrubAge="In Progress"
        scrubTime="$(echo "Est Comp: ")$(echo "$statusOutput" | grep "done, " | awk '{print $5}')"

# Check if the SCRUB is completed or canceled.

elif [ "$(echo "$statusOutput" | grep "scan" | awk '{print $2}')" = "scrub" ] && [ "$(echo "$statusOutput" | grep "scan" | awk '{print $3}')" = "canceled" ]; then
          scrubAge="Canceled"
       elif [ "$(echo "$statusOutput" | grep "scan" | awk '{print $2}')" = "scrub" ]; then
        scrubRepBytes="$(echo "$statusOutput" | grep "scan" | awk '{print $4}')"
        scrubRepBytes="$(echo "$scrubRepBytes" | rev | cut -c2- | rev)"
        scrubErrors="$(echo "$statusOutput" | grep "scan" | awk '{print $8}')"
        # Convert time/datestamp format presented by zpool status, compare to current date, calculate scrub age

# For FreeBSD
   if [ $softver != "Linux" ]; then
        scrubDate="$(echo "$statusOutput" | grep "scan" | awk '{print $15"-"$12"-"$13"_"$14}')"
        scrubTS="$(date -j -f "%Y-%b-%e_%H:%M:%S" "$scrubDate" "+%s")"
   else
# For Linux
        scrubDate="$(echo "$statusOutput" | grep "scan" | awk '{print $12" "$13" "$15" "$14}')"
        scrubTS="$(date --date="$scrubDate" "+%s")"
   fi
        currentTS="$(date "+%s")"
        scrubAge=$((((currentTS - scrubTS) + 43200) / 86400))
        scrubTime="$(echo "$statusOutput" | grep "scan" | awk '{print $6}')"
       else
        #No scrub previously performed
        scrubAge="Never Scrubbed"
fi

fi

    # Set row's background color; alternates between white and $altColor (light gray)
    if [ $((poolNum % 2)) == 1 ]; then bgColor="#ffffff"; else bgColor="$altColor"; fi
    poolNum=$((poolNum + 1))
    # Set up conditions for warning or critical colors to be used in place of standard background colors
    if [ "$status" != "ONLINE" ]; then statusColor="$warnColor"; echo "$pool - Scrub Offline Error<br>" >> "$logfile_critical"; else statusColor="$bgColor"; fi
    if [ "$readErrors" != "0" ]; then readErrorsColor="$warnColor"; echo "$pool - Scrub Read Errors<br>" >> "$logfile_warning"; else readErrorsColor="$bgColor"; fi
    if [ "$writeErrors" != "0" ]; then writeErrorsColor="$warnColor"; echo "$pool - Scrub Write Errors<br>" >> "$logfile_warning"; else writeErrorsColor="$bgColor"; fi
    if [ "$cksumErrors" != "0" ]; then cksumErrorsColor="$warnColor"; echo "$pool - Scrub Cksum Errors<br>" >> "$logfile_warning"; else cksumErrorsColor="$bgColor"; fi
    if [ "$used" -gt "$usedWarn" ]; then usedColor="$warnColor"; echo "$pool - Scrub Used<br>" >> "$logfile_warning"; else usedColor="$bgColor"; fi
    if [ "$scrubRepBytes" != "$non_exist_value" ] && [ "$scrubRepBytes" != "0" ]; then scrubRepBytesColor="$warnColor"; echo "$pool - Scrub Rep Bytes<br>" >> "$logfile_warning"; else scrubRepBytesColor="$bgColor"; fi
    if [ "$scrubErrors" != "$non_exist_value" ] && [ "$scrubErrors" != "0" ]; then scrubErrorsColor="$warnColor"; echo "$pool - Scrub Errors<br>" >> "$logfile_critical"; else scrubErrorsColor="$bgColor"; fi
    if [ "$(echo "$scrubAge" | awk '{print int($1)}')" -gt "$scrubAgeWarn" ]; then scrubAgeColor="$warnColor"; echo "$pool - Scrub Age" >> "$logfile_warning"; else scrubAgeColor="$bgColor"; fi
    if [ "$scrubAge" == "In Progress" ]; then scrubAgeColor="$blueColor"; fi

    (
        # Use the information gathered above to write the date to the current table row
        printf "<tr style=\"background-color:%s;\">
            <td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s%%</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
            <td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>
        </tr>\\n" "$bgColor" "$pool" "$statusColor" "$status" "$pool_size" "$pool_free" "$usedColor" "$used" "$readErrorsColor" "$readErrors" "$writeErrorsColor" "$writeErrors" "$cksumErrorsColor" \
        "$cksumErrors" "$scrubRepBytesColor" "$scrubRepBytes" "$scrubErrorsColor" "$scrubErrors" "$scrubAgeColor" "$scrubAge" "$scrubTime"
    ) >> "$logfile"

done
# End of zpool status table
echo "</table>" >> "$logfile"
echo "<br><span style='color:gray;'>*Data obtained from zpool command</span>" >> "$logfile"
}

######################### GET DRIVE DATA #############################
get_drive_data () {
if [[ $Silence == "off" ]]; then echo "Running get_drive_data routine"; fi

if [[ "$drive" == "nvme50" || "$drive" == "ada50" ]]; then
smartdata="$(cat "$testfile")"
echo "Modified smartdata="
cat "$testfile"
else
smartdata="$(smartctl -a /dev/"$drive")"
  if [[ "$dump_all" == "1" || "$dump_all" == "2" ]]; then
     "$(echo "$smartdata" > /tmp/drive_${drive}_a.txt)" 2> /dev/null
     "$(smartctl -x /dev/"$drive" > /tmp/drive_${drive}_x.txt)" 2> /dev/null


     if [[ ! -f "/tmp/drive_${drive}_a.txt" ]]; then echo "sleeping"; sleep 5; fi
  fi
fi

if [[ "$1" == "NON" ]]; then return; fi

re='^[0-9]+$'
### For Min/Max Drive Temps
if [[ "$(smartctl -x /dev/"$drive" | grep "Power Cycle Min/Max Temperature:" | awk '{print $5}' | cut -d '/' -f1)" != "?" ]]; then
temp_min=$(smartctl -x /dev/"$drive" | grep "Power Cycle Min/Max Temperature:" | awk '{print $5}' | cut -d '/' -f1); else temp_min=0; fi
if ! [[ $temp_min =~ $re ]]; then temp_min=0; fi

if [[ "$(smartctl -x /dev/"$drive" | grep "Power Cycle Min/Max Temperature:" | awk '{print $5}' | cut -d '/' -f2)" != "?" ]]; then
temp_max=$(smartctl -x /dev/"$drive" | grep "Power Cycle Min/Max Temperature:" | awk '{print $5}' | cut -d '/' -f2); else temp_max=0; fi
if ! [[ $temp_max =~ $re ]]; then temp_max=0; fi

sas=0
if [[ "$(echo "$smartdata" | grep "SAS")" ]]; then sas=1; fi

if [[ "$(echo "$smartdata" | grep "remaining" | awk '{print $1}')" ]]; then
smarttesting="$(echo "$smartdata" | grep "remaining" | awk '{print $1}' | tr -d '[%]')"; fi

if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $5}')" ]]; then
chkreadfailure="$(echo "$smartdata" | grep "# 1" | awk '{print $5}')"; fi

if [[ "$sas" == 0 ]]; then
if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $9}')" =~ [%]+$ ]]; then
lastTestHours="$((10#$(echo "$smartdata" | grep "# 1" | awk '{print $10}' )))"
else
if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $9}')" ]]; then
lastTestHours="$((10#$(echo "$smartdata" | grep "# 1" | awk '{print $9}' )))"
fi
fi
fi

if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $3}')" ]]; then
lastTestType="$(echo "$smartdata" | grep "# 1" | awk '{print $3}')"; fi

if [[ "$(echo "$smartdata" | grep "SMART overall-health" | awk '{print $6}')" ]]; then
smartStatus="$(echo "$smartdata" | grep "SMART overall-health" | awk '{print $6}')"; fi

if [[ "$(echo "$smartdata" | grep "SMART Health Status" | awk '{print $4}')" ]]; then
smartStatus="$(echo "$smartdata" | grep "SMART Health Status" | awk '{print $4}' | tr -d '[:space:]')";
fi

if [[ "$(echo "$smartdata" | grep "Serial number:" | awk '{print $3}')" ]]; then
serial="$(echo "$smartdata" | grep "Serial number:" | awk '{print $3}')"; fi

if [[ "$(echo "$smartdata" | grep "Serial Number" | awk '{print $3}')" ]]; then
serial="$(echo "$smartdata" | grep "Serial Number" | awk '{print $3}')"; fi

if [[ "$(echo "$smartdata" | grep "Airflow" | awk '{print $10}')" ]]; then
temp="$((10#$(echo "$smartdata" | grep "Airflow" | awk '{print $10 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Temperature_Case" | awk '{print $10}')" ]]; then
temp="$((10#$(echo "$smartdata" | grep "Temperature_Case" | awk '{print $10 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Temperature_Celsius" | awk '{print $10}')" ]]; then
temp="$((10#$(echo "$smartdata" | grep "Temperature_Celsius" | awk '{print $10 + 0}')))"; fi

if [[ "$sas" == 0 ]]; then
if [[ "$(echo "$smartdata" | grep "Temperature:" | awk '{print $2}')" ]]; then
temp="$((10#$(echo "$smartdata" | grep "Temperature:" | awk '{print $2 + 0}')))"; fi
fi

if [[ "$(echo "$smartdata" | grep "Power_On_Hours" | awk '{print $10}')" ]]; then
onHours="$((10#$(echo "$smartdata" | grep "Power_On_Hours" | awk '{print $10}' | cut -d 'h' -f1)))"; fi

if [[ "$(echo "$smartdata" | grep "Power On Hours" | awk '{print $4}')" ]]; then
onHours="$(echo "$smartdata" | grep "Power On Hours" | awk '{print $4}')"
fi

if [[ "$(echo "$smartdata" | grep "Start_Stop_Count" | awk '{print $10}')" ]]; then
startStop="$((10#$(echo "$smartdata" | grep "Start_Stop_Count" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Spin_Retry_Count" | awk '{print $10}')" ]]; then
spinRetry="$((10#$(echo "$smartdata" | grep "Spin_Retry_Count" | awk '{print $10 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Reallocated_Sector" | awk '{print $10}')" ]]; then
reAlloc="$((10#$(echo "$smartdata" | grep "Reallocated_Sector" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Reallocated_Event_Count" | awk '{print $10}')" ]]; then
reAllocEvent="$((10#$(echo "$smartdata" | grep "Reallocated_Event_Count" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Current_Pending_Sector" | awk '{print $10}')" ]]; then
pending="$((10#$(echo "$smartdata" | grep "Current_Pending_Sector" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Offline_Uncorrectable" | awk '{print $10}')" ]]; then
offlineUnc="$((10#$(echo "$smartdata" | grep "Offline_Uncorrectable" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Uncorrectable_Error_Cnt" | awk '{print $10}')" ]]; then
offlineUnc="$((10#$(echo "$smartdata" | grep "Uncorrectable_Error_Cnt" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "UDMA_CRC_Error_Count" | awk '{print $10}')" ]]; then
crcErrors="$((10#$(echo "$smartdata" | grep "UDMA_CRC_Error_Count" | awk '{print $10 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "CRC_Error_Count" | awk '{print $10}')" ]]; then
crcErrors="$((10#$(echo "$smartdata" | grep "CRC_Error_Count" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Seek_Error_Rate" | awk '{print $4}')" ]]; then
seekErrorHealth2="$((10#$(echo "$smartdata" | grep "Seek_Error_Rate" | awk '{print $4}')))"; fi

if [[ "$(echo "$smartdata" | grep "Seek_Error_Rate" | awk '{print $10}')" ]]; then
seekErrorHealth="$((10#$(echo "$smartdata" | grep "Seek_Error_Rate" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Raw_Read_Error_Rate" | awk '{print $4}')" ]]; then
rawReadErrorRate2="$((10#$(echo "$smartdata" | grep "Raw_Read_Error_Rate" | awk '{print $4}')))"; fi

if [[ "$(echo "$smartdata" | grep "Raw_Read_Error_Rate" | awk '{print $10}')" ]]; then
rawReadErrorRate="$((10#$(echo "$smartdata" | grep "Raw_Read_Error_Rate" | awk '{print $10}')))"; fi

### Add search for Seagate and mark seagate=1
if [[ "$(echo "$smartdata" | grep -i "Seagate" )" ]]; then seagate=1; else seagate=""; fi

if [[ "$(echo "$smartdata" | grep "Load_Cycle_Count" | awk '{print $10}')" ]]; then
loadCycle="$((10#$(echo "$smartdata" | grep "Load_Cycle_Count" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Multi_Zone_Error_Rate" | awk '{print $10}')" ]]; then
multiZone="$((10#$(echo "$smartdata" | grep "Multi_Zone_Error_Rate" | awk '{print $10 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "SSD_Life_Left" | awk '{print $4}')" ]]; then
wearLevel="$((10#$(echo "$smartdata" | grep "SSD_Life_Left" | awk '{print $4 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Wear_Leveling_Count" | awk '{print $4}')" ]]; then
wearLevel="$((10#$(echo "$smartdata" | grep "Wear_Leveling_Count" | awk '{print $4 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Percent_Lifetime_Remain" | awk '{print $4}')" ]]; then
wearLevel="$((10#$(echo "$smartdata" | grep "Percent_Lifetime_Remain" | awk '{print $4 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Media_Wearout_Indicator" | awk '{print $4}')" ]]; then
wearLevel="$((10#$(echo "$smartdata" | grep "Media_Wearout_Indicator" | awk '{print $4 + 0}')))"; fi

# Changed from Available Spare: for NVME.txt
if [[ "$(echo "$smartdata" | grep "Percentage Used:" | awk '{print $3}')" ]]; then
wearLevel="$((10#$(echo "$smartdata" | grep "Percentage Used:" | awk '{print $3 + 0}')))"
wearLevel=100-$wearLevel
fi

if [[ "$(echo "$smartdata" | grep "Percentage used endurance indicator:" | awk '{print $5}')" ]]; then
wearLevel="$((10#$(echo "$smartdata" | grep "Percentage used endurance indicator:" | awk '{print $5}' | cut -d '%' -f1)))"
# Adjusting Wear Level for amount used vice amount remaining #
wearLevel=100-$wearLevel
fi

if [[ "$(echo "$smartdata" | grep "Reallocated_NAND_Blk_Cnt" | awk '{print $10}')" ]]; then
reAlloc="$((10#$(echo "$smartdata" | grep "Reallocated_NAND_Blk_Cnt" | awk '{print $10}')))"; fi

if [[ "$(echo "$smartdata" | grep "Current Drive Temperature:" | awk '{print $4}')" ]]; then
temp="$((10#$(echo "$smartdata" | grep "Current Drive Temperature:" | awk '{print $4 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Accumulated start-stop cycles:" | awk '{print $4}')" ]]; then
startStop="$((10#$(echo "$smartdata" | grep "Accumulated start-stop cycles:" | awk '{print $4 + 0}')))"; fi

if [[ "$(echo "$smartdata" | grep "Accumulated load-unload cycles:" | awk '{print $4}')" ]]; then
loadCycle="$((10#$(echo "$smartdata" | grep "Accumulated load-unload cycles:" | awk '{print $4}')))"; fi

if [[ "$(echo "$smartdata" | grep "Elements in grown defect list:" | awk '{print $6}')" == '^[0-9]+$' ]]; then
reAlloc="$((10#$(echo "$smartdata" | grep "Elements in grown defect list:" | awk '{print $6}')))"; fi

if [[ "$(echo "$smartdata" | grep "Accumulated power on time" | awk '{print $6}' | cut -d ":" -f1)" ]]; then
onHours="$((10#$(echo "$smartdata" | grep "Accumulated power on time" | awk '{print $6}' | cut -d ":" -f1)))"
fi

if [[ "$(echo "$smartdata" | grep "Rotation" | awk '{print $3}')" ]]; then
rotation="$(echo "$smartdata" | grep "Rotation" | awk '{print $3}')"; fi

if [[ "$(echo "$smartdata" | grep "Device Model" | awk '{print $3 " " $4 " " $5 " " $6 " " $7}')" ]]; then
modelnumber="$(echo "$smartdata" | grep "Device Model" | awk '{print $3 " " $4 " " $5 " " $6 " " $7}')"; fi

if [[ "$(echo "$smartdata" | grep "Model Number:" | awk '{print $3 " " $4 " " $5 " " $6 " " $7}')" ]]; then
modelnumber="$(echo "$smartdata" | grep "Model Number:" | awk '{print $3 " " $4 " " $5 " " $6 " " $7}')"; fi

if [[ "$(echo "$smartdata" | grep "Product:" | awk '{print $2}')" ]]; then
modelnumber="$(echo "$smartdata" | grep "Product:" | awk '{print $2}')"; fi

if [[ "$(echo "$smartdata" | grep "User Capacity" | awk '{print $5 $6}')" ]]; then
capacity="$(echo "$smartdata" | grep "User Capacity" | awk '{print $5 $6}')"; fi

if [[ "$(echo "$smartdata" | grep "Namespace 1 Size" | awk '{print $5 $6}')" ]]; then
capacity="$(echo "$smartdata" | grep "Namespace 1 Size" | awk '{print $5 $6}')"; fi

if [[ "$(echo "$smartdata" | grep "Critical Warning:" | awk '{print $3}')" ]]; then
NVMcriticalWarning="$(echo "$smartdata" | grep "Critical Warning:" | awk '{print $3}')"; fi

if [[ "$(echo "$smartdata" | grep "Helium_Level" | awk '{print $10}')" ]]; then
Helium="$(echo "$smartdata" | grep "Helium_Level" | awk '{print $10}')"; fi

if [[ "$(echo "$smartdata" | grep "22 Unknown_Attribute" | awk '{print $10}')" ]]; then
if [[ "$Helium" == "" ]]; then Helium="$(echo "$smartdata" | grep "22 Unknown_Attribute" | awk '{print $10}')"; fi; fi

if [[ "$(echo "$smartdata" | grep "Background" | awk '{print $10}')" ]]; then
lastTestHours="$(echo "$smartdata" | grep "Background" | awk '{print $10}')"; fi

if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $7}')" ]]; then
altlastTestHours="$(echo "$smartdata" | grep "# 1" | awk '{print $7}')"; fi

if [[ "$sas" == 1 ]]; then
lastTestHours="$(echo "$smartdata" | grep "# 1" | awk '{print $7}')"
fi

if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $4}')" ]]; then
altlastTestType="$(echo "$smartdata" | grep "# 1" | awk '{print $4}')"; fi

if [[ "$sas" == 1 ]]; then
if [[ "$(echo "$smartdata" | grep "# 1" | awk '{print $4}')" ]]; then
lastTestType="$(echo "$smartdata" | grep "# 1" | awk '{print $4}')"; fi
fi

# Some drives do not report test age after 65536 hours.
if [[ $onHours -gt "65536" ]] && [[ $lastTestHours -gt "0" && $lastTestHours -lt "65536" ]]; then lastTestHours=$(($lastTestHours + 65536)); fi

######## VMWare Hack to fix NVMe bad variables #####
if [[ "$VMWareNVME" == "on" ]]; then
if [[ "$serial" == "VMWare" ]]; then
onHours="17,200"
wearLevel="98"
temp="38"
temp_min="20"
temp_max="43"
fi
fi

}

########################## GET TIMESTAMP ######################
get_timestamp () {
if [[ $Silence == "off" ]]; then echo "Running get_timestamp routine"; fi
# I Want Milliseconds Resolution represented for timestamp, FreeBSD deos not support it ################################

if [[ $softver != "Linux" ]]; then 
  timestamp=$(date +%T)
else
  timestamp=$(date +"%T.%2N")
fi

datestamp=$(date +%Y/%m/%d)

}

################################## GENERATE TABLE ########################################################
# Call function with generate_table "HDD|SSD|NVM"

generate_table () {
if [[ $Silence == "off" ]]; then echo "Running generate_table routine"; fi

detail_level="$1"

# Lets add up how many columns we will need.

Columns=0;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Device_ID" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Serial_Number" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Model_Number" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Capacity" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Rotational_Rate" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_SMART_Status" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp_Min" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp_Max" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Power_On_Hours" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Start_Stop_Count" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Load_Cycle" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Spin_Retry" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Reallocated_Sectors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Reallocated_Events" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Pending_Sectors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Offline_Uncorrectable" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_UDMA_CRC_Errors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Raw_Read_Error_Rate" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Seek_Error_Rate" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_MultiZone_Errors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Helium_Level" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Last_Test_Age" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Last_Test_Type" == "true" ]]; then ((Columns=Columns+1)); fi;

# Count for SSD
if [[ "$1" == "SSD" ]] && [[ "$SSD_Device_ID" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Serial_Number" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Model_Number" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Capacity" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_SMART_Status" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp_Min" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp_Max" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Power_On_Hours" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Wear_Level" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Reallocated_Sectors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Reallocated_Events" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Pending_Sectors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Offline_Uncorrectable" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_UDMA_CRC_Errors" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Last_Test_Age" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "SSD" ]] && [[ "$SSD_Last_Test_Type" == "true" ]]; then ((Columns=Columns+1)); fi;

# Count for NVMe
if [[ "$1" == "NVM" ]] && [[ "$NVM_Device_ID" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Serial_Number" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Model_Number" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Capacity" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_SMART_Status" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Critical_Warning" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp_Min" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp_Max" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Power_On_Hours" == "true" ]]; then ((Columns=Columns+1)); fi;
if [[ "$1" == "NVM" ]] && [[ "$NVM_Wear_Level" == "true" ]]; then ((Columns=Columns+1)); fi;

#echo "Columns="$Columns

(
    # Write HTML table headers to log file
    echo "<br><br>"
    echo "<table style=\"border: 1px solid black; border-collapse: collapse;\">"
    if [[ "$1" == "HDD" ]]; then echo "<tr><th colspan=\"$Columns\" style=\"text-align:center; font-size:20px; height:40px; font-family:courier;\">"$HDDreportTitle"</th></tr>"; fi
    if [[ "$1" == "SSD" ]]; then echo "<tr><th colspan=\"$Columns\" style=\"text-align:center; font-size:20px; height:40px; font-family:courier;\">"$SSDreportTitle"</th></tr>"; fi
    if [[ "$1" == "NVM" ]]; then echo "<tr><th colspan=\"$Columns\" style=\"text-align:center; font-size:20px; height:40px; font-family:courier;\">"$NVMreportTitle"</th></tr>"; fi
    echo "<tr>"

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Device_ID" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Device_ID_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Device_ID" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Device_ID_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Device_ID" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Device_ID_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Serial_Number" == "true" ]]; then echo "  <th style=\"text-align:center; width:130px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Serial_Number_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Serial_Number" == "true" ]]; then echo "  <th style=\"text-align:center; width:130px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Serial_Number_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Serial_Number" == "true" ]]; then echo "  <th style=\"text-align:center; width:130px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Serial_Number_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Model_Number" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Model_Number_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Model_Number" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Model_Number_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Model_Number" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Model_Number_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Capacity" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Capacity_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Capacity" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Capacity_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Capacity" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Capacity_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Rotational_Rate" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Rotational_Rate_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_SMART_Status" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_SMART_Status_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_SMART_Status" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_SMART_Status_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_SMART_Status" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_SMART_Status_Title"</th>"; fi

    if [[ "$1" == "NVM" ]] && [[ "$NVM_Critical_Warning" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Critical_Warning_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Drive_Temp_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Drive_Temp_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Drive_Temp_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp_Min" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Drive_Temp_Min_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp_Min" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Drive_Temp_Min_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp_Min" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Drive_Temp_Min_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp_Max" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Drive_Temp_Max_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp_Max" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Drive_Temp_Max_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp_Max" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Drive_Temp_Max_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Power_On_Hours" == "true" ]]; then echo "  <th style=\"text-align:center; width:120px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Power_On_Hours_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Power_On_Hours" == "true" ]]; then echo "  <th style=\"text-align:center; width:120px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Power_On_Hours_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Power_On_Hours" == "true" ]]; then echo "  <th style=\"text-align:center; width:120px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Power_On_Hours_Title"</th>"; fi

    if [[ "$1" == "SSD" ]] && [[ "$SSD_Wear_Level" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Wear_Level_Title"</th>"; fi
    if [[ "$1" == "NVM" ]] && [[ "$NVM_Wear_Level" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$NVM_Wear_Level_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Start_Stop_Count" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Start_Stop_Count_Title"</th>"; fi
    if [[ "$1" == "HDD" ]] && [[ "$HDD_Load_Cycle" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Load_Cycle_Title"</th>"; fi
    if [[ "$1" == "HDD" ]] && [[ "$HDD_Spin_Retry" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Spin_Retry_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Reallocated_Sectors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Reallocated_Sectors_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Reallocated_Sectors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Reallocated_Sectors_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Reallocated_Events" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Reallocated_Events_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Reallocated_Events" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Reallocated_Events_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Pending_Sectors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Pending_Sectors_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Pending_Sectors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Pending_Sectors_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Offline_Uncorrectable" == "true" ]]; then echo "  <th style=\"text-align:center; width:120px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Offline_Uncorrectable_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Offline_Uncorrectable" == "true" ]]; then echo "  <th style=\"text-align:center; width:120px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Offline_Uncorrectable_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_UDMA_CRC_Errors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_UDMA_CRC_Errors_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_UDMA_CRC_Errors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_UDMA_CRC_Errors_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Raw_Read_Error_Rate" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Raw_Read_Error_Rate_Title"</th>"; fi
    if [[ "$1" == "HDD" ]] && [[ "$HDD_Seek_Error_Rate" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Seek_Error_Rate_Title"</th>"; fi
    if [[ "$1" == "HDD" ]] && [[ "$HDD_MultiZone_Errors" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_MultiZone_Errors_Title"</th>"; fi
    if [[ "$1" == "HDD" ]] && [[ "$HDD_Helium_Level" == "true" ]]; then echo "  <th style=\"text-align:center; width:80px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Helium_Level_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Last_Test_Age" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Last_Test_Age_Title"</th>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Last_Test_Age" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Last_Test_Age_Title"</th>"; fi

    if [[ "$1" == "HDD" ]] && [[ "$HDD_Last_Test_Type" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$HDD_Last_Test_Type_Title"</th></tr>"; fi
    if [[ "$1" == "SSD" ]] && [[ "$SSD_Last_Test_Type" == "true" ]]; then echo "  <th style=\"text-align:center; width:100px; height:60px; border:1px solid black; border-collapse:collapse; font-family:courier;\">"$SSD_Last_Test_Type_Title"</th></tr>"; fi
    echo "</tr>"

) >> "$logfile"
}

################################## WRITE TABLE #############################################################
# Call function with end_table "HDD|SSD|NVM"

write_table () {
if [[ $Silence == "off" ]]; then echo "Running write_table routine"; fi

(
printf "<tr style=\"background-color:%s;\">\n" $bgColor;
if [[ "$1" == "HDD" ]] && [[ "$HDD_Device_ID" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">/dev/%s</td>\n" "$deviceStatusColor" "$drive"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Device_ID" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">/dev/%s</td>\n" "$deviceStatusColor" "$drive"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Device_ID" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">/dev/%s</td>\n" "$deviceStatusColor" "$drive"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Serial_Number" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$bgColor" "$serial"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Serial_Number" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$bgColor" "$serial"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Serial_Number" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$bgColor" "$serial"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Model_Number" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$modelnumber"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Model_Number" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$modelnumber"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Model_Number" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$modelnumber"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Capacity" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$capacity"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Capacity" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$capacity"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Capacity" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$capacity"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Rotational_Rate" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$rotation"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_SMART_Status" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$smartStatusColor" "$smartStatus"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_SMART_Status" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$smartStatusColor" "$smartStatus"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_SMART_Status" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$smartStatusColor" "$smartStatus"; fi

if [[ "$1" == "NVM" ]] && [[ "$NVM_Critical_Warning" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$NVMcriticalWarningColor" "$NVMcriticalWarning"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$tempColor" "$temp"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$tempColor" "$temp"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$tempColor" "$temp"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp_Min" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$temp_min"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp_Min" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$temp_min"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp_Min" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$temp_min"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Drive_Temp_Max" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$temp_maxColor" "$temp_max"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Drive_Temp_Max" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$temp_maxColor" "$temp_max"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Drive_Temp_Max" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%d$tempdisplay</td>\n" "$temp_maxColor" "$temp_max"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Power_On_Hours" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$onTimeColor" "$onTime"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Power_On_Hours" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$onTimeColor" "$onTime"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Power_On_Hours" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$onTimeColor" "$onTime"; fi

if [[ "$1" == "SSD" ]] && [[ "$SSD_Wear_Level" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$wearLevelColor" "$wearLevel"; fi
if [[ "$1" == "NVM" ]] && [[ "$NVM_Wear_Level" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$wearLevelColor" "$wearLevel"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Start_Stop_Count" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$startStop"; fi
if [[ "$1" == "HDD" ]] && [[ "$HDD_Load_Cycle" == "true" ]]; then printf "<td style=\"text-align:center; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$loadCycle"; fi
if [[ "$1" == "HDD" ]] && [[ "$HDD_Spin_Retry" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$spinRetryColor" "$spinRetry"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Reallocated_Sectors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$reAllocColor" "$reAlloc"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Reallocated_Sectors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$reAllocColor" "$reAlloc"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Reallocated_Events" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$reAllocEventColor" "$reAllocEvent"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Reallocated_Events" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$reAllocEventColor" "$reAllocEvent"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Pending_Sectors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$pendingColor" "$pending"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Pending_Sectors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$pendingColor" "$pending"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Offline_Uncorrectable" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$offlineUncColor" "$offlineUnc"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Offline_Uncorrectable" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$offlineUncColor" "$offlineUnc"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_UDMA_CRC_Errors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$crcErrorsColor" "$crcErrors"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_UDMA_CRC_Errors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$crcErrorsColor" "$crcErrors"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Raw_Read_Error_Rate" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">$SER%s</td>\n" "$rawReadErrorRateColor" "$rawReadErrorRate"; fi
if [[ "$1" == "HDD" ]] && [[ "$HDD_Seek_Error_Rate" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">$SER%s</td>\n" "$seekErrorHealthColor" "$seekErrorHealth"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_MultiZone_Errors" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$multiZoneColor" "$multiZone"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Helium_Level" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$HeliumColor" "$Helium"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Last_Test_Age" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$testAgeColor" "$testAge"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Last_Test_Age" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$testAgeColor" "$testAge"; fi

if [[ "$1" == "HDD" ]] && [[ "$HDD_Last_Test_Type" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$lastTestTypeColor" "$lastTestType"; fi
if [[ "$1" == "SSD" ]] && [[ "$SSD_Last_Test_Type" == "true" ]]; then printf "<td style=\"text-align:center; background-color:%s; height:25px; border:1px solid black; border-collapse:collapse; font-family:courier;\">%s</td>\n" "$lastTestTypeColor" "$lastTestType"; fi

    echo "</tr>"
) | tr -d "[]" >> "$logfile"
}

#############################  END THE TABLE ###########################

end_table () {
if [[ $Silence == "off" ]]; then echo "Running end_table routine"; fi
(
    echo "</tr>"
 echo "</table>"
if [[ "$SER1" == "1" ]]; then echo "<span style='color:gray;'>* = Seek Error Rate is Normalized.  Higher is better.</span>"; fi
    echo "<br>"
) >> "$logfile"
}

################################## COMPILE DETAILED REPORT ###############################################

detailed_report () {
if [[ $Silence == "off" ]]; then echo "Running detailed_report routine"; fi

###### Detailed Report Section (monospace text)
testfile=$1

(

echo "<pre style=\"font-size:20px\">"
echo "<b>Multi-Report Text Section</b>"
echo "<pre style=\"font-size:14px\">"
) >> "$logfile"

if test -e "$Config_File_Name"; then
echo "<b>External Configuration File in Use</b><br>" >> "$logfile"
else
echo "<b>No External Configuration File Exists</b><br>" >> "$logfile"
fi

if [[ $expDataEnable == "true" ]]; then
if [[ "$(echo $statistical_data_file | grep "/tmp/")" ]]; then
 echo "<b><span style='color:darkred;'>The Statistical Data File is located in the /tmp directory and is not permanent.<br>Recommend changing to a proper dataset.</span></b><br>" >> "$logfile"; fi
if [[ $statistical_data_file_created == "1" ]]; then echo "Statistical Data File Created.<br>" >> "$logfile"; fi

   if [[ $expDataEmail == "true" ]]; then
      echo "<b>Statistical Export Log Located:<br></b>$statistical_data_file<br><b>Emailed every:</b> $expDataEmailSend<br>" >> "$logfile"
   else
      echo "<b>Statistical Export Log Located at:<br>$statistical_data_file</b><br>" >> "$logfile"
   fi
fi

### Lets write out the error messages if there are any, Critical first followed by Warning
(

if test -e "$logfile_messages"; then
echo "<b>MESSAGES LOG FILE"
cat $logfile_messages
echo "<br>END<br></b>"
fi

if test -e "$logfile_critical"; then
echo "<b>CRITICAL LOG FILE"
cat $logfile_critical
echo "<br>END<br></b>"
fi

if test -e "$logfile_warning"; then
echo "<b>WARNING LOG FILE"
cat $logfile_warning
echo "<br>END<br></b>"
fi

if [[ ! $Ignore_Drives == "none" ]]; then
echo "Ignored Drives = "$Ignore_Drives
echo "<br>END<br>"
fi



if [[ $Fun == "1" ]]; then echo "Have a Happy April Fools Day!"; fi
if test -e "$logfile_warranty"; then
  cat $logfile_warranty
  echo "</b><br>"
fi
) >> "$logfile"

if [[ $disableRAWdata != "true" ]]; then

### zpool status for each pool
for pool in $pools; do
if [ $softver != "Linux" ]; then
drives_in_zpool=$(zpool status "$pool" | grep "gptid" | awk '{print $1}')
else
drives_in_zpool=$(zpool status -P "$pool" | grep "/dev/disk" | awk -F '[/]' '{print $5}' | cut -d " " -f1)
fi
driveit=0
    (
      # Create a simple header and drop the output of zpool status -v
        echo "<b>########## ZPool status report for ${pool} ##########</b>"
       # echo "<br>"
        zpool status -v "$pool"
        for longpool in $drives_in_zpool; do
          if [ $softver != "Linux" ]; then
             drive_ident=$(glabel status | tail -n +2 | grep "$longpool" | awk '{print $3}' | cut -d 'p' -f1)
          else
             drive_ident=$(/sbin/blkid | grep "$longpool" | cut -d ":" -f1 | cut -d "/" -f3)
          fi
          if [[ $drive_ident != "" ]]; then
          if [[ $driveit == "0" ]]; then echo "<br>Drives for this pool listed below are in order as listed above:"; driveit="1"; fi
          echo $drive_ident
          fi
        done
        echo "<br>"

    ) >> "$logfile"
done

  if [[ $includeSSD == "true" ]] && [[ $includeNVM == "true" ]]; then
  drives="${smartdrives} ${smartdrivesSSD} ${smartdrivesNVM}"
  elif [[ $includeSSD == "true" ]]; then
  drives="${smartdrives} ${smartdrivesSSD}"
  else
  drives="${smartdrives}"
  fi
### SMART status for each drive - SMART Enabled
 for drive in $drives; do

if [[ $drive == "ada50" || $drive == "nvme50"  ]] ; then
    brand="$(cat "$testfile" | grep "Model Family" | awk '{print $3, $4, $5}')"
    serial="$(cat "$testfile" | grep "Serial Number" | awk '{print $3}')"
    (
    echo "<br><b>########## FULL TESTFILE -- SMART status report for ${drive} drive (${brand}: ${serial}) ##########</b>" 
    cat "$testfile"
    ) >> "$logfile"
else
    # Gather brand and serial number of each drive
    brand="$(smartctl -i /dev/"$drive" | grep "Model Family" | awk '{print $3, $4, $5}')"
    serial="$(smartctl -i /dev/"$drive" | grep "Serial Number" | awk '{print $3}')"

    (
     # Create a simple header and drop the output of some basic smartctl commands
        echo "<b>########## SMART status report for ${drive} drive (${brand}: ${serial}) ##########</b>"
        smartctl -H -A -l error /dev/"$drive"

     # Create Recent Tests Report
        echo "Num Test_Description  (Most recent Short & Extended Tests - Listed by test number)"
        lasttest1="$(smartctl -x /dev/"$drive" | egrep "# 1")"
        echo $lasttest1
        if [[ $lasttest1 == *"Short offline"* ]]; then lastfind="Extended offline"; fi;
        if [[ $lasttest1 == *"Extended offline"* ]]; then lastfind="Short offline"; fi;
        lasttest2="$(smartctl -x /dev/"$drive" | egrep "$lastfind" | head -1)"
        echo $lasttest2
        echo "<br>"
    ) >> "$logfile"

      
 # SCT Error Recovery Control Report
       scterc="$(smartctl -l scterc /dev/"$drive" | tail -3 | head -2)"
    (
      echo "SCT Error Recovery Control: "$scterc
      echo "<br>"
     ) >> "$logfile"
fi
 done
fi
}

################################ COMPILE NON-SMART REPORT ##################################

non_smart_report () {
if [[ $Silence == "off" ]]; then echo "Running non_smart_report routine"; fi

### NON-SMART status report section
# I don't particularly use this but some folks might find it useful.
# To activate it, in the variables set reportnonSMART=true.
# It will list all drives where Non-SMART is true and remove devices starting with "cd", for example "cd0"

drives=$nonsmartdrives
if [ $reportnonSMART == "true" ]; then 
for drive in $drives; do
  if [ ! "$(echo "$drive" | grep "cd")" ]; then
   if [ $softver != "Linux" ]; then
    # Gather brand and serial number of each drive
    brand="$(smartctl -i /dev/"$drive" | grep "Model Family" | awk '{print $3, $4, $5}')"
    serial="$(smartctl -i /dev/"$drive" | grep "Serial Number" | awk '{print $3}')"
   else
    brand="$(fdisk -l /dev/"$drive" | grep "Disk model" | awk '{print $3, $4, $5}')"
    serial="$(fdisk -l /dev/"$drive" | grep "Serial Number" | awk '{print $3}')"
   fi
    (
        echo "<br>"
        echo "<b>########## NON-SMART status report for ${drive} drive (${brand}: ${serial}) ##########</b>"
    # And we will dump everything since it's not a standard SMART device.
        echo "<b>SMARTCTL DATA</b>"
        smartctl -a /dev/"$drive"
        echo "<br>"
      if [ $softver == "Linux" ]; then
        echo "<b>FDISK DATA</b>"
        fdisk -l /dev/"$drive"
      fi

    ) >> "$logfile"
  fi
done
fi
}

############################## REMOVE UN-NEEDED JUNK AND FINALIZE EMAIL MESSAGE END #####################

remove_junk_report () {
if [[ $Silence == "off" ]]; then echo "Running remove_junk_report routine"; fi

### Remove some un-needed junk from the output
sed -i -e '/smartctl/d' "$logfile"
sed -i -e '/Copyright/d' "$logfile"
sed -i -e '/=== START OF READ/d' "$logfile"
sed -i -e '/SMART Attributes Data/d' "$logfile"
sed -i -e '/Vendor Specific SMART/d' "$logfile"
sed -i -e '/SMART Error Log Version/d' "$logfile"

# Attach dump files
if [[ "$dump_all" == "1" || "$dump_all" == "2" ]]; then
for drive in $smartdrives; do
  dump_drive_data
done
for drive in $smartdrivesSSD; do
  dump_drive_data
done
for drive in $smartdrivesNVM; do
  dump_drive_data
done
for drive in $nonsmartdrives; do
  dump_drive_data
done
(
  # Write MIME section header for file attachment (encoded with base64)
  echo "--${boundary}"
  echo "Content-Type: text/html"
  echo "Content-Transfer-Encoding: base64"
  echo "Content-Disposition: attachment; filename=config_file.txt"
  base64 $Config_File_Name

#  echo "--${boundary}"
#  echo "Content-Type: text/html"
#  echo "Content-Transfer-Encoding: base64"
#  echo "Content-Disposition: attachment; filename=drive_${drive}_x.txt"
#  base64 "/tmp/drive_${drive}_x.txt"

 # echo "--${boundary}"
 # echo "Content-Type: text/html"

 ) >> "$logfile"

fi

### End details section, close MIME section
(
    echo "</pre>"
    echo "--${boundary}--"
)  >> "$logfile"
}

############################# COMBINE ALL DATA INTO A FORMAL EMAIL MESSAGE AND SEND IT ############################

create_email () {
### Create New Email Header - Set Subject Line
if [[ $Silence == "off" ]]; then echo "Running create_email routine"; fi

## Test if there is a Warning Message and Setup Subject Line
if test -e "$logfile_critical"; then
 subject="*CRITICAL ERROR*  SMART Testing Results for ${host}  *CRITICAL ERROR*"
elif test -e "$logfile_warning"; then
 subject="*WARNING*  SMART Testing Results for ${host}  *WARNING*"
elif [[ $disableWarranty == "false" ]]; then
	if test -e "$logfile_warranty"; then
	subject="*Drive Warranty Expired* - SMART Testing Results for ${host}"
	else
	subject="SMART Testing Results for ${host} - All is Good"
	fi
else
 subject="SMART Testing Results for ${host} - All is Good"
fi

### Set email headers ###
(
echo "From: ${from}"
echo "To: ${email}"
echo "Subject: ${subject}"
) > ${logfile_header}

cat $logfile >> $logfile_header

### Send report
sendmail -t -oi < "$logfile_header"
}

############################# CRUNCH THE NUMBERS and FORMAT MESSAGES and COLORS ####################################
##### Call with HDD|SSD|NVM ##############
crunch_numbers () {
if [[ $Silence == "off" ]]; then echo "Running crunch_numbers routine"; fi

detail_level=$1

### Remove Leading Zeros from all variables
# This is important because double square brackets interpret a leading zero as Octal number
# This only works for positive numbers, not negative.  Thankfully I should not have negative
# numbers in this script.

# Make onHours a base 10 number and remove an commas
onHours=${onHours#0}
onHours="${onHours//,}"

if [[ $Silence == "off" ]]; then
echo "---"
echo "Drive="$drive
echo "lastTestHours="$lastTestHours
echo "onHours="$onHours
fi

### Convert onHours to onTime
if [[ $onHours -gt "1000000" ]]; then onHours=0; fi
if [[ $lastTestHours != "" ]]; then let testAge=$(((($onHours - $lastTestHours) / 24))); fi

if [[ $Silence == "off" ]]; then
echo "testAge="$testAge
fi

let yrs=$((($onHours / 8760)))
let mos=$(((($onHours % 8760) / 730)))
let dys=$((((($onHours % 8760) % 730) / 24)))
let hrs=$(((($onHours % 8760) % 730) % 24))

if [[ $powerTimeFormat == "ymdh" ]]; then onTime="${yrs}y ${mos}m ${dys}d ${hrs}h";
 elif [[ $powerTimeFormat == "ymd" ]]; then onTime="${yrs}y ${mos}m ${dys}d";
 elif [[ $powerTimeFormat == "ym" ]]; then onTime="${yrs}y ${mos}m";
 elif [[ $powerTimeFormat == "y" ]]; then onTime="${yrs}y";
 elif [[ $powerTimeFormat == "h" ]]; then onTime=$onHours;
 else onTime=$onHours;
fi

##### CUSTOM DRIVE HACK Section #####
if [[ $custom_hack == "mistermanko" ]]; then
    if [[ $serial == "1603F0161945" ]]; then testAge=1; fi
fi

### WARRANTY DATE
# Use Format: DriveWarranty="DriveSerialNumber YYYY-MM-DD,"

s="0"
IFS=',' read -ra ADDR <<< "$Drive_Warranty"
 for i in "${ADDR[@]}"; do
   drivesn1="$(echo $i | cut -d':' -f 1)"
   drivedt1="$(echo $i | cut -d':' -f 2)"
   if [[ $drivesn1 == $serial ]]; then
     if [[ "$datestamp2" > "$drivedt1" ]]; then
        s="1"
        drivesn2=$drivesn1
        drivedt2=$drivedt1
        continue
     fi
   fi
   done
 if [[ $s != "0" ]]; then
onTimeColor=$yellowColor
printf "Drive "$drivesn2" Warranty Expired on "$drivedt2"<br>" >> "$logfile_warranty"
 fi

### SMART STATUS

if [[ $smartStatus == "" || $smartStatus == "PASSED" || $smartStatus == "OK" ]]; then smartStatusColor=$okColor; else smartStatusColor=$critColor; fi
if [[ $smartStatus == "" || $smartStatus == "PASSED" || $smartStatus == "OK" ]]; then a=1; else printf "Drive "$device " - Check Smart Status<br>" >> "$logfile_critical"; fi
if [[ $smartStatus == "" ]]; then smartStatus = "$non_exist_value"; fi

### BAD SECTORS

s="0"
IFS=',' read -ra ADDR <<< "$Bad_Sectors"
 for i in "${ADDR[@]}"; do
   badsectsn1="$(echo $i | cut -d':' -f 1)"
   badsectdt1="$(echo $i | cut -d':' -f 2)"
   if [[ $badsectsn1 == $serial ]]; then
    s="1"
    badsectsn2=$badsectsn1
    badsectdt2=$badsectdt1
    continue
   fi
   done
 if [[ $s != "0" ]]; then
reAllocColor=$ovrdColor
reAlloc=$(($reAlloc-$badsectdt2))
 fi

####################  TEMPERATURE SECTION ###################
# LETS ZERO OUT BOGUS HIGH TEMPS and LOW TEMPS
if [[ $temp == "" ]]; then temp="0"; fi
if [[ $temp -gt 150 ]]; then temp="0"; fi
if [[ $temp -lt -60 ]]; then temp="0"; fi

### TEMP for HDD
if [[ $detail_level == "HDD" ]]; then
if [[ $temp != "" ]]; then if [[ $temp -gt $HDDtempCrit ]]; then tempColor=$critColor; else if [[ $temp -gt $HDDtempWarn ]]; then tempColor=$warnColor; fi; fi; fi
if [[ $temp != "" ]]; then if [[ $temp -gt $HDDtempCrit ]]; then printf "Drive "$serial" Critical Drive Temp "$temp" - Threshold = "$HDDtempCrit"<br>" >> "$logfile_critical";
else if [[ $temp -gt $HDDtempWarn ]]; then printf "Drive "$serial" High Drive Temp "$temp" - Threshold set at "$HDDtempWarn"<br>" >> "$logfile_warning"; fi; fi; fi

if [[ $HDDmaxovrd != "true" ]]; then
if [[ $temp_max != "" ]]; then if [[ $temp_max -gt $HDDtempCrit ]]; then temp_maxColor=$critColor; else if [[ $temp_max -gt $HDDtempWarn ]]; then temp_maxColor=$warnColor; fi; fi; fi
if [[ $temp_max != "" ]]; then if [[ $temp_max -gt $HDDtempCrit ]]; then printf "Drive "$serial" Critical Drive Temp "$temp_max" - Temp Max Threshold = "$HDDtempCrit"<br>" >> "$logfile_critical";
else if [[ $temp_max -gt $HDDtempWarn ]]; then printf "Drive "$serial" High Drive Temp "$temp_max" - Temp Max Threshold set at "$HDDtempWarn"<br>" >> "$logfile_warning"; fi; fi; fi
fi
fi

### TEMP for SSD
if [[ $detail_level == "SSD" ]]; then
if [[ $temp != "" ]]; then if [[ $temp -gt $SSDtempCrit ]]; then tempColor=$critColor; else if [[ $temp -gt $SSDtempWarn ]]; then tempColor=$warnColor; fi; fi; fi
if [[ $temp != "" ]]; then if [[ $temp -gt $SSDtempCrit ]]; then printf "Drive "$serial" Critical Drive Temp "$temp" - Threshold = "$SSDtempCrit"<br>" >> "$logfile_critical";
else if [[ $temp -gt $SSDtempWarn ]]; then printf "Drive "$serial" High Drive Temp "$temp" - Threshold set at "$SSDtempWarn"<br>" >> "$logfile_warning"; fi; fi; fi

if [[ $SSDmaxovrd != "true" ]]; then
if [[ $temp_max != "" ]]; then if [[ $temp_max -gt $SSDtempCrit ]]; then temp_maxColor=$critColor; else if [[ $temp_max -gt $SSDtempWarn ]]; then temp_maxColor=$warnColor; fi; fi; fi
if [[ $temp_max != "" ]]; then if [[ $temp_max -gt $SSDtempCrit ]]; then printf "Drive "$serial" Critical Drive Temp "$temp_max" - Threshold = "$SSDtempCrit"<br>" >> "$logfile_critical";
else if [[ $temp_max -gt $SSDtempWarn ]]; then printf "Drive "$serial" High Drive Temp "$temp_max" - Temp Max Threshold set at "$SSDtempWarn"<br>" >> "$logfile_warning"; fi; fi; fi
fi
fi

### TEMP for NVM
if [[ $detail_level == "NVM" ]]; then
if [[ $temp != "" ]]; then if [[ $temp -gt $NVMtempCrit ]]; then tempColor=$critColor; else if [[ $temp -gt $NVMtempWarn ]]; then tempColor=$warnColor; fi; fi; fi
if [[ $temp != "" ]]; then if [[ $temp -gt $NVMtempCrit ]]; then printf "Drive "$serial" Critical Drive Temp "$temp" - Threshold = "$NVMtempCrit"<br>" >> "$logfile_critical";
else if [[ $temp -gt $NVMtempWarn ]]; then printf "Drive "$serial" High Drive Temp "$temp" - Threshold set at "$NVMtempWarn"<br>" >> "$logfile_warning"; fi; fi; fi

if [[ $temp_max != "" ]]; then if [[ $temp_max -gt $NVMtempCrit ]]; then temp_maxColor=$critColor; else if [[ $temp_max -gt $NVMtempWarn ]]; then temp_maxColor=$warnColor; fi; fi; fi
if [[ $temp_max != "" ]]; then if [[ $temp_max -gt $NVMtempCrit ]]; then printf "Drive "$serial" Critical Drive Temp "$temp_max" - Threshold = "$NVMtempCrit"<br>" >> "$logfile_critical";
else if [[ $temp_max -gt $NVMtempWarn ]]; then printf "Drive "$serial" High Drive Temp "$temp_max" - Threshold set at "$NVMtempWarn"<br>" >> "$logfile_warning"; fi; fi; fi

fi

# NVM CRITICAL WARNING
if [[ $detail_level == "NVM" ]]; then
NVMcriticalWarningColor="$okColor"
if [[ $NVMcriticalWarning != "" ]]; then if [[ $NVMcriticalWarning != "0x00" ]]; then printf "Drive "$serial" NVM Critical Warning "$NVMcriticalWarning"<br>" >> "$logfile_critical"; fi; fi
if [[ $NVMcriticalWarning != "" ]]; then if [[ $NVMcriticalWarning != "0x00" ]]; then NVMcriticalWarningColor=$critColor; fi; fi
if [[ $NVMcriticalWarning != "" ]]; then if [[ $NVMcriticalWarning != "0x00" ]]; then NVMcriticalWarning="CRITICAL FAILURE"; fi; fi
if [[ $NVMcriticalWarning == "0x00" ]]; then NVMcriticalWarning="GOOD"; fi
if [[ $NVMcriticalWarning == "" ]]; then NVMcriticalWarning="$non_exist_value"; fi
fi

if [[ $detail_level == "HDD" ]]; then

#Helium=99
# Helium Critical Warning
if [[ $Helium == "" ]]; then Helium="$non_exist_value"; HeliumColor="$bgColor"; fi
if [[ $Helium == "$heliumMin" || $Helium == "$non_exist_value" ]]; then
 HeliumColor="$bgColor"
 else
 if [[ $heliumAlarm == "true" ]]; then
   HeliumColor="$critColor"
   printf "Drive "$serial" Helium Critical Warning - Value "$Helium"<br>" >> "$logfile_critical"
 fi
fi
fi
########### PROCESSING THAT AFFECTS EVERYTHING ##########################################################
### SPINRETRY

if [[ $spinRetry != "" ]]; then if [[ $spinRetry != "0" ]]; then spinRetryColor=$critColor; fi; fi
if [[ $spinRetry != "" ]]; then if [[ $spinRetry != "0" ]]; then printf "Drive "$serial" Spin Retry "$spinRetry" - Threshold = 0 <br>" >> "$logfile_critical"; fi; fi
if [[ $spinRetry == "" ]]; then spinRetry="$non_exist_value"; fi

### REALLOC and REALLOCEVENT
if [[ $reAlloc != "" ]]; then if [[ $(($reAlloc + 0)) -gt $sectorsCrit ]]; then reAllocColor=$critColor; else if [[ $(($reAlloc + 0)) -gt $sectorsWarn ]]; then reAllocColor=$warnColor; fi; fi; fi
if [[ $reAlloc != "" ]]; then if [[ $(($reAlloc + 0)) -gt $sectorsCrit ]]; then printf "Drive "$serial" Critical Sectors "$reAlloc" - Threshold = "$sectorsCrit"<br>" >> "$logfile_critical";
else if [[ $(($reAlloc + 0)) -gt $sectorsWarn ]]; then printf "Drive "$serial" Warning Sectors "$reAlloc" - Threshold = "$sectorsWarn"<br>" >> "$logfile_warning"; fi; fi; fi
if [[ $reAlloc == "" ]]; then reAlloc="$non_exist_value"; fi

if [[ $reAllocEvent != "" ]]; then if [[ $reAllocEvent -gt $reAllocWarn ]]; then reAllocEventColor=$warnColor; fi; fi
if [[ $reAllocEvent != "" ]]; then if [[ $reAllocEvent -gt $reAllocWarn ]]; then printf "Drive "$serial" Reallocating Sectors "$reAllocEvent" - Threshold = "$reAllocWarn"<br>" >> "$logfile_warning"; fi; fi
if [[ $reAllocEvent == "" ]]; then reAllocEvent="$non_exist_value"; fi

### PENDING SECTORS
if [[ $pending != "" ]]; then if [[ $(($pending + 0)) -gt $sectorsCrit ]]; then pendingColor=$critColor; else if [[ $(($pending + 0)) -gt $sectorsWarn ]]; then pendingColor=$warnColor; fi; fi; fi
if [[ $pending != "" ]]; then if [[ $(($pending + 0)) -gt $sectorsCrit ]]; then printf "Drive "$serial" Sector Errors "$pending" - Threshold = "$sectorsCrit"<br>" >> "$logfile_critical";
else if [[ $(($pending + 0)) -gt $sectorsWarn ]]; then printf "Drive "$serial" Sector Errors "$pending" - Threshold = "$sectorsWarn"<br>" >> "$logfile_warning"; fi; fi; fi
if [[ $pending == "" ]]; then pending="$non_exist_value"; fi

### OFFLINE UNCORRECTABLE SECTORS
if [[ $offlineUnc != "" ]]; then if [[ $(($offlineUnc + 0)) > $sectorsCrit ]]; then offlineUncColor=$critColor; else if [[ $offlineUnc != 0 ]]; then offlineUncColor=$warnColor; fi; fi; fi
if [[ $offlineUnc != "" ]]; then if [[ $(($offlineUnc + 0)) > $sectorsCrit ]]; then printf "Drive "$serial" Uncorrectable Errors "$offlineUnc"<br>" >> "$logfile_critical";
else if [[ $offlineUnc -gt $sectorsWarn ]]; then printf "Drive "$serial" Uncorrectable Errors "$offlineUnc" - Threshold = "$sectorsWarn"<br>" >> "$logfile_warning";fi; fi; fi
if [[ $offlineUnc == "" ]]; then offlineUnc="$non_exist_value"; fi

### CRC ERRORS
if [[ $crcErrors != "" ]]; then if [[ $crcErrors != "0" ]]; then crcErrorsColor=$critColor; fi; fi
if [[ $crcErrors == "" ]]; then crcErrors="$non_exist_value"; fi

### SMARTTESTING
if [[ $smarttesting -gt 0 ]]; then lastTestType="$smarttesting% Remaining"; fi

### CHKREADFAILURE
if [[ $chkreadfailure == "Completed:" ]]; then lastTestType="Read Failure"; lastTestTypeColor=$critColor; printf "Drive "$serial" Read Failure "$chkreadfailure"<br>" >> "$logfile_critical"; else lastTestTypeColor=$bgColor; fi 
#if [[ $chkreadfailure == "Completed:" ]]; then printf "Drive "$serial" Read Failure "$chkreadfailure"<br>" >> "$logfile_critical"; fi

### SEEK ERRORS
# If seekErrorHealth RAW_VALUE is some crazy number, use the VALUE column data.
# Seek Error Rate fix for Seagate Drives
# We use seekErrorHealth for the Seagate Rate, and seekErrorHealth2 for the Normalized Rate if we must.

if [[ $seekErrorHealth -gt 0 ]]; then

# Lets see if this is a NORMAL drive, not reporting crazy ass numbers.
if [[ $seekErrorHealth -lt $seekErrorsWarn ]] && [[ $seekErrorHealth -le 4294967295 ]]; then seek="done"; fi

if [[ $seekErrorHealth -gt $seekErrorsWarn ]] && [[ $seekErrorHealth -lt $seekErrorsCrit ]]; then
   seekErrorHealthColor=$warnColor
   seek="done"
fi
if [[ $seekErrorHealth -gt $seekErrorsCrit ]] && [[ $seekErrorHealth -le 500 ]]; then
   seekErrorHealthColor=$critColor
   seek="done"
fi

# If the count is above the Seagate FFFFFFFF value, subtract it out or if below FFFFFFFF then make value zero

  if [[ $seekErrorHealth -lt 4294967295 ]] && [[ $seek != "done" ]]; then seekErrorHealth=0; fi
  if [[ $seekErrorHealth -ge 4294967295 ]]; then seekErrorHealth=$(($seekErrorHealth - 4294967295)); fi

  if [[ $ignoreSeekError != "true" ]]; then
   if [[ $(($seekErrorHealth + 0)) -gt $seekErrorsCrit ]]; then
     seekErrorHealthColor=$critColor
     printf "Drive "$serial" Seek Errors "$seekErrorHealth" - Threshold = "$seekErrorsCrit"<br>" >> "$logfile_critical"
   else
     if [[ $(($seekErrorHealth + 0)) -gt $seekErrorsWarn ]]; then
       seekErrorHealthColor=$warnColor
       printf "Drive "$serial" Seek Errors "$seekErrorHealth" - Threshold = "$seekErrorsWarn"<br>" >> "$logfile_warning"
     fi
   fi
  fi
fi
seek=""

### Raw Read Error Rate
# If seekErrorHealth RAW_VALUE is some crazy number, use the VALUE column data.
# Raw Read Error Rate fix for Seagate Drives
# We use rawReadErrorRate for the Seagate Rate, and rawReadErrorRate2 for the Normalized Rate if we must.

if [[ $rawReadErrorRate -gt 0 ]]; then

# Lets see if this is a NORMAL drive, not reporting crazy ass numbers.
if [[ $rawReadErrorRate -lt $rawReadWarn ]] && [[ $rawReadErrorRate -le 4294967295 ]]; then seek="done"; fi

if [[ $rawReadErrorRate -gt $rawReadWarn ]] && [[ $rawReadErrorRate -lt $rawReadCrit ]]; then
   rawReadErrorRateColor=$warnColor
   seek="done"
fi
if [[ $rawReadErrorRate -gt $rawReadCrit ]] && [[ $rawReadErrorRate -le 500 ]]; then
   rawReadErrorRateColor=$critColor
   seek="done"
fi

# If the count is above the Seagate FFFFFFFF value, subtract it out or if below FFFFFFFF then make value zero

  if [[ $rawReadErrorRate -lt 4294967295 ]] && [[ $seek != "done" ]]; then rawReadErrorRate=0; fi
  if [[ $rawReadErrorRate -ge 4294967295 ]]; then rawReadErrorRate=$(($rawReadErrorRate - 4294967295)); fi

  if [[ $ignoreReadError != "true" ]]; then
   if [[ $(($rawReadErrorRate + 0)) -gt $rawReadCrit ]]; then
     rawReadErrorRateColor=$critColor
     printf "Drive "$serial" Raw Read Error Rate "$rawReadErrorRate" - Threshold = "$rawReadCrit"<br>" >> "$logfile_critical"
   else
     if [[ $(($rawReadErrorRate + 0)) -gt $rawReadWarn ]]; then
       rawReadErrorRateColor=$warnColor
       printf "Drive "$serial" Raw Read Error Rate "$rawReadErrorRate" - Threshold = "$rawReadWarn"<br>" >> "$logfile_warning"
     fi
   fi
  fi
fi
seek=""

wearLevelColor=$bgColor
if [[ $multiZone == "" ]]; then multiZone="$non_exist_value"; fi
if [[ $wearLevel == "" || $wearLevel == "0" ]]; then wearLevel="$non_exist_value"; else wearLevel=$(($wearLevel + 0)); fi
if [[ $wearLevel != "$non_exist_value" ]]; then if [[ $wearLevel -lt $wearLevelCrit ]]; then wearLevelColor=$warnColor; printf "Drive: "$serial" - Wear Level = "$wearLevel"%%<br>" >> "$logfile_warning"; fi; fi
if [[ $modelnumber == "" ]]; then modelnumber="$non_exist_value"; fi
if [[ $startStop == "" ]]; then startStop="$non_exist_value"; fi
if [[ $loadCycle == "" ]]; then loadCycle="$non_exist_value"; fi
if [[ $seekErrorHealth == "" ]]; then seekErrorHealth="$non_exist_value"; fi
if [[ $rawReadErrorRate == "" ]]; then rawReadErrorRate="$non_exist_value"; fi
if [[ $Helium == "" ]]; then Helium="$non_exist_value"; fi

################################## WRITE STATISTICAL DATA #########################################
### Save Statistical Data before we make any changes to it.

if [[ $expDataEnable == "true" && $writing_data != "1" ]]; then
   writing_data=1
   if [[ $Silence == "off" ]]; then echo "Writing Statistical Data"; fi
fi

if [[ $expDataEnable == "true" ]]; then printf $datestamp","$timestamp","$drive","$detail_level","$serial","$smartStatus","$temp","$onHours","$wearLevel","$startStop","$loadCycle","$spinRetry","$reAlloc","$reAllocEvent","$pending","$offlineUnc","$crcErrors","$seekErrorHealth","$multiZone","$rawReadErrorRate","$Helium",\n" >> "$statistical_data_file";fi

### Routine to zero out the UDMA CRC Error Count and Highlights it Yellow.

if [[ $External_Config == "no" ]]; then CRC_Errors=$CRC_ERRORS; Multi_Zone=$MULTI_Zone; Bad_Sectors=$BAD_SECTORS; Drive_Warranty=$DRIVE_WARRANTY; fi

s="0"
IFS=',' read -ra ADDR <<< "$CRC_Errors"
 for i in "${ADDR[@]}"; do
   crc_errsn1="$(echo $i | cut -d':' -f 1)"
   crc_errst1="$(echo $i | cut -d':' -f 2)"
   if [[ $crc_errsn1 == $serial ]]; then
    s="1"
    crc_errsn2=$crc_errsn1
    crc_errst2=$crc_errst1
    continue
   fi
   done
 if [[ $s != "0" ]]; then
crcErrorsColor=$ovrdColor
crcErrors=$(($crcErrors-$crc_errst2))
 fi

s="0"
IFS=',' read -ra ADDR <<< "$Multi_Zone"
 for i in "${ADDR[@]}"; do
   badsectsn1="$(echo $i | cut -d':' -f 1)"
   badsectdt1="$(echo $i | cut -d':' -f 2)"
   if [[ $badsectsn1 == $serial ]]; then
    s="1"
    badsectsn2=$badsectsn1
    badsectdt2=$badsectdt1
    continue
   fi
   done
 if [[ $s != "0" ]]; then
multiZoneColor=$ovrdColor
multiZone=$(($multiZone-$badsectdt2))
 fi

if [[ $Fun == "1" ]]; then deviceStatusColor=$critColor; printf "Drive "$serial" Data Bit Breakdown Occuring - Bits are flying off the media.<br>"  >> "$logfile_warning"; fi
if [[ $ignoreMultiZone != "true" ]]; then if [[ $multiZone != "$non_exist_value" ]]; then if [[ $multiZone -gt $multiZoneWarn ]]; then multiZoneColor=$warnColor; printf "Drive: "$serial" - MultiZone Errors = "$multiZone"<br>" >> "$logfile_warning"; fi; fi; fi
if [[ $ignoreMultiZone != "true" ]]; then if [[ $multiZone != "$non_exist_value" ]]; then if [[ $multiZone -gt $multiZoneCrit ]]; then multiZoneColor=$critColor; printf "Drive: "$serial" - MultiZone Errors = "$multiZone"<br>" >> "$logfile_critical";fi ;fi ;fi
if [[ $ignoreUDMA != "true" ]]; then if [[ $crcErrors != "$non_exist_value" ]]; then if [[ $crcErrors != "0" ]]; then printf "Drive "$serial" CRC Errors "$crcErrors"<br>" >> "$logfile_critical";fi; fi; fi
if [[ $testAge -gt $testAgeWarn ]]; then testAgeColor=$warnColor; else testAgeColor=$bgColor; fi
if [[ $testAge -gt $testAgeWarn ]]; then printf "Drive: "$serial" - Test Age = "$testAge" Days<br>" >> "$logfile_warning"; fi
if [[ $smartStatusColor != $okColor ]]; then if [[ $smartStatusColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi; fi; fi
if [[ $tempColor != $bgColor ]]; then if [[ $tempColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi; fi; fi
if [[ $temp_maxColor != $bgColor ]]; then if [[ $temp_maxColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi; fi; fi
if [[ $spinRetryColor != $bgColor ]]; then if [[ $spinRetryColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor; fi; fi; fi
if [[ $reAllocColor != $bgColor ]]; then if [[ $reAllocColor != $altColor ]]; then if [[ $reAllocColor != $ovrdColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi ;fi ;fi
if [[ $reAllocEventColor != $bgColor ]]; then if [[ $reAllocEventColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor; fi; fi; fi
if [[ $pendingColor != $bgColor ]]; then if [[ $pendingColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi; fi
if [[ $offlineUncColor != $bgColor ]]; then if [[ $offlineUncColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi; fi
if [[ $crcErrorsColor != $bgColor ]]; then if [[ $crcColor != $altColor ]]; then if [[ $crcErrorsColor != $ovrdColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi ;fi ;fi
if [[ $seekErrorHealthColor != $bgColor ]]; then if [[ $seekErrorHealthColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi; fi; fi
if [[ $rawReadErrorRateColor != $bgColor ]]; then if [[ $rawReadErrorRateColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi; fi; fi
if [[ $testAgeColor != $bgColor ]]; then if [[ $testAgeColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi ;fi
if [[ $lastTestTypeColor != $bgColor ]]; then if [[ $lastTestTypeColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi ;fi
if [[ $multiZoneColor != $bgColor ]]; then if [[ $multiZoneColor != $altColor ]]; then if [[ $multiZoneColor != $ovrdColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi ;fi ;fi
if [[ $wearLevelColor != $bgColor ]]; then if [[ $wearLevelColor != $altColor ]]; then if [[ $deviceRedFlag == "true" ]]; then deviceStatusColor=$critColor;fi ;fi ;fi

# SCT Error Recovery Control Report

  scterc="$(smartctl -l scterc /dev/"$drive" | tail -3 | head -2)"

if [[ $SCT_Warning == "TLER" ]]; then
   # Warning Level TLER = Ignore Drives that do not report "seconds" or "Disable"
   # Warning Level TLER_No_Msg = same as above but will not report TLER disabled message until after trying to set TLER fails.
    if [[ $scterc =~ "Disabled" ]]; then printf "Drive "$serial" TLER is Disabled<br>" >> "$logfile_warning"; fi
fi

if [[ $SCT_Warning == "TLER_No_Msg" && $SCT_Drive_Enable == "true" ]]; then
     if [[ $scterc =~ "Disabled" ]]; then
     # Now we set the TLER ONLY for Disabled Drives because we do not know how it will affect other drives.
     smartctl -l scterc,"$SCT_Read_Timeout","$SCT_Write_Timeout" /dev/"$drive" > /dev/null 2>&1
     scterc="$(smartctl -l scterc /dev/"$drive" | tail -3 | head -2)"
      if [[ $scterc =~ "seconds" ]]; then printf "<b><span style='color:green;'>Drive "$serial" TLER is NOW ENABLED !</span></b><br>" >> "$logfile_messages"; fi
      if [[ $scterc =~ "Disabled" ]]; then printf "<b><span style='color:darkred;'>Drive "$serial" TLER is Disabled and failed to set.</span></b><br>" >> "$logfile_warning"; fi
     fi
fi

if [[ $SCT_Warning == "all" ]]; then 
   if [[ $scterc =~ "Disabled" ]]; then
      printf "Drive "$serial" TLER is Disabled<br>" >> "$logfile_warning"
   else
      if [[ ! $scterc =~ "seconds" ]]; then printf "Drive "$serial" TLER is Unsupported<br>" >> "$logfile_warning"; fi
   fi
fi

  if [[ $SCT_Drive_Enable == "true" ]]; then
     if [[ $scterc =~ "Disabled" ]]; then
     # Now we set the TLER ONLY for Disabled Drives because we do not know how it will affect other drives.
     smartctl -l scterc,"$SCT_Read_Timeout","$SCT_Write_Timeout" /dev/"$drive" > /dev/null 2>&1
     scterc="$(smartctl -l scterc /dev/"$drive" | tail -3 | head -2)"
      if [[ $SCT_Warning == "all" || $SCT_Warning == "TLER" ]]; then printf "<b><span style='color:green;'>Drive "$serial" TLER is NOW ENABLED !</span></b><br>" >> "$logfile_warning"; fi
        if [[ $scterc =~ "Disabled" ]]; then
         if [[ $SCT_Warning == "all" || SCT_Warning == "TLER" ]]; then printf "<b><span style='color:darkred;'>Drive "$serial" TLER is Disabled and failed to set.</span></b><br>" >> "$logfile_warning"; fi
        fi
     fi
 fi

}

################################## UPDATE CONFIG FILE #############################################
update_config_file () {
if [[ $Silence == "off" ]]; then echo "Running update_config_file routine"; fi
(
echo $programver
echo "This file is used exclusively to configure the multi_report version 1.6c or later."
echo " "
echo "NOTE: The configuration file will be created in the same directory as the script."
echo " "
echo "This configuration file only overrides the default values hardcoded into the script.  If you do not want to change"
echo "certain values within the script, you can delete those lines from this configuration file to make it more palatable."
echo " "
echo "###### Email Address ######"
echo "# Enter your email address to send the report to.  The from address does not need to be changed."
echo " "
echo 'email="'$email'"'
echo 'from="'$from'"'
echo " "
echo "###### Custom Hack ######"
echo "# Custom Hacks are for users with generally very unsupported drives and the data must be manually manipulated."
echo "# The goal is to not have any script customized so I will look for fixes where I can."
echo "#"
echo "# Allowable custom hacks are: mistermanko"
echo 'custom_hack="'$custom_hack'"'
echo " "
echo "###### New Updates Go Here"
echo "# v 1.6d - Added Raw Read Error Rate and Seek Error Rate "
echo " "
echo "###### Zpool Status Summary Table Settings"
echo " "
echo "usedWarn=$usedWarn             # Pool used percentage for CRITICAL color to be used."
echo "scrubAgeWarn=$scrubAgeWarn           # Maximum age (in days) of last pool scrub before CRITICAL color will be used (30 + 7 days for day of week). Default=37."
echo " "
echo "###### Temperature Settings"
echo "HDDtempWarn=$HDDtempWarn            # HDD Drive temp (in C) upper OK limit before a WARNING color/message will be used."
echo "HDDtempCrit=$HDDtempCrit            # HDD Drive temp (in C) upper OK limit before a CRITICAL color/message will be used."
echo 'HDDmaxovrd="'$HDDmaxovrd'"         # HDD Max Drive Temp Override. This value when "true" will not alarm on any Current Power Cycle Max Temperature Limit.'
echo "SSDtempWarn=$SSDtempWarn            # SSD Drive temp (in C) upper OK limit before a WARNING color/message will be used."
echo "SSDtempCrit=$SSDtempCrit            # SSD Drive temp (in C) upper OK limit before a CRITICAL color/message will be used."
echo 'SSDmaxovrd="'$SSDmaxovrd'"         # SSD Max Drive Temp Override. This value when "true" will not alarm on any Current Power Cycle Max Temperature Limit.'
echo "NVMtempWarn=$NVMtempWarn            # NVM Drive temp (in C) upper OK limit before a WARNING color/message will be used."
echo "NVMtempCrit=$NVMtempCrit            # NVM Drive temp (in C) upper OK limit before a CRITICAL color/message will be used."
echo " "
echo "###### SSD/NVMe Specific Settings"
echo " "
echo "wearLevelCrit=$wearLevelCrit           # Wear Level Alarm Setpoint lower OK limit before a WARNING color/message, 9% is the default."
echo " "
echo "###### General Settings"
echo "# Output Formats"
echo 'powerTimeFormat="'$powerTimeFormat'"       # Format for power-on hours string, valid options are "ymdh", "ymd", "ym", "y", or "h" (year month day hour).'
echo 'tempdisplay="'$tempdisplay'"          # The format you desire the temperature to be displayed in. Common formats are: "*C", "^C", or "^c". Choose your own.'
echo 'non_exist_value="'$non_exist_value'"     # How do you desire non existent data to be displayed.  The Default is "---", popular options are "N/A" or " ".'
echo " "
echo "# Ignore or Activate Alarms"
echo 'ignoreUDMA="'$ignoreUDMA'"        # Set to "true" to ignore all UltraDMA CRC Errors for the summary alarm (Email Header) only, errors will appear in the graphical chart.'
echo 'ignoreSeekError="'$ignoreSeekError'"    # Set to "true" to ignore all Seek Error Rate/Health errors.  Default is true.'
echo 'ignoreReadError="'$ignoreReadError'"    # Set to "true" to ignore all Raw Read Error Rate/Health errors.  Default is true.'
echo 'ignoreMultiZone="'$ignoreMultiZone'"   # Set to "true" to ignore all MultiZone Errors. Default is false.'
echo 'disableWarranty="'$disableWarranty'"    # Set to "true to disable email Subject line alerts for any expired warranty alert. The email body will still report the alert.'
echo " "
echo "# Disable or Activate Input/Output File Settings"
echo 'includeSSD="'$includeSSD'"         # Set to "true" will engage SSD Automatic Detection and Reporting, false = Disable SSD Automatic Detection and Reporting.'
echo 'includeNVM="'$includeNVM'"         # Set to "true" will engage NVM Automatic Detection and Reporting, false = Disable NVM Automatic Detection and Reporting.'
echo 'reportnonSMART="'$reportnonSMART'"     # Will force even non-SMART devices to be reported, "true" = normal operation to report non-SMART devices.'
echo 'disableRAWdata="'$disableRAWdata'"    # Set to "true" to remove the 'smartctl -a' data and non-smart data appended to the normal report.  Default is false.'
echo " "
echo "# Media Alarms"
echo "sectorsWarn=$sectorsWarn             # Number of sectors per drive to allow with errors before WARNING color/message will be used, this value should be less than sectorsCrit."
echo "sectorsCrit=$sectorsCrit             # Number of sectors per drive with errors before CRITICAL color/message will be used."
echo "reAllocWarn=$reAllocWarn             # Number of Reallocated sector events allowed.  Over this amount is an alarm condition."
echo "multiZoneWarn=$multiZoneWarn           # Number of MultiZone Errors to allow before a Warning color/message will be used.  Default is 0."
echo "multiZoneCrit=$multiZoneCrit           # Number of MultiZone Errors to allow before a Warning color/message will be used.  Default is 5."
echo 'deviceRedFlag="'$deviceRedFlag'"      # Set to "true" to have the Device Column indicate RED for ANY alarm condition.  Default is true.'
echo 'heliumAlarm="'$heliumAlarm'"        # Set to "true" to set for a critical alarm any He value below 100.  Default is true.'
echo "heliumMin=$heliumMin             # Set to 100 for a zero leak helium result.  An alert will occur below this value."
echo "rawReadWarn=$rawReadWarn             # Number of read errors to allow before WARNING color/message will be used, this value should be less than rawReadCrit."
echo "rawReadCrit=$rawReadCrit           # Number of read errors to allow before CRITICAL color/message will be used."
echo "seekErrorsWarn=$seekErrorsWarn          # Number of seek errors to allow before WARNING color/message will be used, this value should be less than seekErrorsCrit."
echo "seekErrorsCrit=$seekErrorsCrit        # Number of seek errors to allow before CRITICAL color/message will be used."
echo " "
echo "# Time-Limited Error Recovery (TLER)"
echo 'SCT_Drive_Enable="'$SCT_Drive_Enable'"  # Set to "true" to send a command to enable SCT on your drives for user defined timeout if the TLER state is Disabled.'
echo 'SCT_Warning="'$SCT_Warning'" # Set to "all" will generate a Warning Message for all devices not reporting SCT enabled. "TLER" reports only drive which support TLER.'
echo '                          # "TLER_No_Msg" will only report for TLER drives and not report a Warning Message if the drive can set TLER on.'
echo "SCT_Read_Timeout=$SCT_Read_Timeout       # Set to the read threshold. Default = 70 = 7.0 seconds."
echo "SCT_Write_Timeout=$SCT_Write_Timeout      # Set to the write threshold. Default = 70 = 7.0 seconds."
echo " "
echo "# SMART Testing Alarm"
echo "testAgeWarn=$testAgeWarn             # Maximum age (in days) of last SMART test before CRITICAL color/message will be used."
echo " "
echo "###### Statistical Data File"
echo 'statistical_data_file="'$statistical_data_file'"    # Default location is where the script is located.'
echo 'expDataEnable="'$expDataEnable'"      # Set to "true" will save all drive data into a CSV file defined by "statistical_data_file" below.'
echo 'expDataEmail="'$expDataEmail'"       # Set to "true" to have an attachment of the file emailed to you. Default is true.'
echo "expDataPurge=$expDataPurge          # Set to the number of day you wish to keep in the data.  Older data will be purged. Default is 730 days (2 years). 0=Disable."
echo 'expDataEmailSend="'$expDataEmailSend'"    # Set to the day of the week the statistical report is emailed.  (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)'
echo " "
echo "###### FreeNAS config backup settings"
echo 'configBackup="'$configBackup'"      # Set to "true" to save config backup (which renders next two options operational); "false" to keep disable config backups.'
echo 'configSendDay="'$configSendDay'"      # Set to the day of the week the config is emailed.  (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)'
echo 'saveBackup="'$saveBackup'"       # Set to "false" to delete FreeNAS config backup after mail is sent; "true" to keep it in dir below.'
echo 'backupLocation="'$backupLocation'"   # Directory in which to store the backup FreeNAS config files.'
echo " "
echo "########## REPORT CHART CONFIGURATION ##############"
echo " "
echo "###### REPORT HEADER TITLE ######"
echo 'HDDreportTitle="'$HDDreportTitle'"     # This is the title of the HDD report, change as you desire.'
echo 'SSDreportTitle="'$SSDreportTitle'"               # This is the title of the SSD report, change as you desire.'
echo 'NVMreportTitle="'$NVMreportTitle'"              # This is the title of the NVMe report, change as you desire.'
echo " "
echo "### CUSTOM REPORT CONFIGURATION ###"
echo "# By default most items are selected. Change the item to "false" to have it not displayed in the graph, "true" to have it displayed."
echo "# NOTE: Alarm setpoints are not affected by these settings, this is only what columns of data are to be displayed on the graph."
echo "# I would recommend that you remove columns of data that you don't really care about to make the graph less busy."
echo " "
echo "# For Zpool Status Summary"
echo 'Zpool_Pool_Name_Title="'$Zpool_Pool_Name_Title'"'
echo 'Zpool_Status_Title="'$Zpool_Status_Title'"'
echo 'Zpool_Pool_Size_Title="'$Zpool_Pool_Size_Title'"'
echo 'Zpool_Free_Space_Title="'$Zpool_Free_Space_Title'"'
echo 'Zpool_Used_Space_Title="'$Zpool_Used_Space_Title'"'
echo 'Zpool_Read_Errors_Title="'$Zpool_Read_Errors_Title'"'
echo 'Zpool_Write_Errors_Title="'$Zpool_Write_Errors_Title'"'
echo 'Zpool_Checksum_Errors_Title="'$Zpool_Checksum_Errors_Title'"'
echo 'Zpool_Scrub_Repaired_Title="'$Zpool_Scrub_Repaired_Title'"'
echo 'Zpool_Scrub_Errors_Title="'$Zpool_Scrub_Errors_Title'"'
echo 'Zpool_Scrub_Age_Title="'$Zpool_Scrub_Age_Title'"'
echo 'Zpool_Scrub_Duration_Title="'$Zpool_Scrub_Duration_Title'"'
echo " "
echo "# For Hard Drive Section"
echo 'HDD_Device_ID="'$HDD_Device_ID'"'
echo 'HDD_Device_ID_Title="'$HDD_Device_ID_Title'"'
echo 'HDD_Serial_Number="'$HDD_Serial_Number'"'
echo 'HDD_Serial_Number_Title="'$HDD_Serial_Number_Title'"'
echo 'HDD_Model_Number="'$HDD_Model_Number'"'
echo 'HDD_Model_Number_Title="'$HDD_Model_Number_Title'"'
echo 'HDD_Capacity="'$HDD_Capacity'"'
echo 'HDD_Capacity_Title="'$HDD_Capacity_Title'"'
echo 'HDD_Rotational_Rate="'$HDD_Rotational_Rate'"'
echo 'HDD_Rotational_Rate_Title="'$HDD_Rotational_Rate_Title'"'
echo 'HDD_SMART_Status="'$HDD_SMART_Status'"'
echo 'HDD_SMART_Status_Title="'$HDD_SMART_Status_Title'"'
echo 'HDD_Raw_Read_Error_Rate="'$HDD_Raw_Read_Error_Rate'"'
echo 'HDD_Raw_Read_Error_Rate_Title="'$HDD_Raw_Read_Error_Rate_Title'"'
echo 'HDD_Drive_Temp="'$HDD_Drive_Temp'"'
echo 'HDD_Drive_Temp_Title="'$HDD_Drive_Temp_Title'"'
echo 'HDD_Drive_Temp_Min="'$HDD_Drive_Temp_Min'"'
echo 'HDD_Drive_Temp_Min_Title="'$HDD_Drive_Temp_Min_Title'"'
echo 'HDD_Drive_Temp_Max="'$HDD_Drive_Temp_Max'"'
echo 'HDD_Drive_Temp_Max_Title="'$HDD_Drive_Temp_Max_Title'"'
echo 'HDD_Power_On_Hours="'$HDD_Power_On_Hours'"'
echo 'HDD_Power_On_Hours_Title="'$HDD_Power_On_Hours_Title'"'
echo 'HDD_Start_Stop_Count="'$HDD_Start_Stop_Count'"'
echo 'HDD_Start_Stop_Count_Title="'$HDD_Start_Stop_Count_Title'"'
echo 'HDD_Load_Cycle="'$HDD_Load_Cycle'"'
echo 'HDD_Load_Cycle_Title="'$HDD_Load_Cycle_Title'"'
echo 'HDD_Spin_Retry="'$HDD_Spin_Retry'"'
echo 'HDD_Spin_Retry_Title="'$HDD_Spin_Retry_Title'"'
echo 'HDD_Reallocated_Sectors="'$HDD_Reallocated_Sectors'"'
echo 'HDD_Reallocated_Sectors_Title="'$HDD_Reallocated_Sectors_Title'"'
echo 'HDD_Reallocated_Events="'$HDD_Reallocated_Events'"'
echo 'HDD_Reallocated_Events_Title="'$HDD_Reallocated_Events_Title'"'
echo 'HDD_Pending_Sectors="'$HDD_Pending_Sectors'"'
echo 'HDD_Pending_Sectors_Title="'$HDD_Pending_Sectors_Title'"'
echo 'HDD_Offline_Uncorrectable="'$HDD_Offline_Uncorrectable'"'
echo 'HDD_Offline_Uncorrectable_Title="'$HDD_Offline_Uncorrectable_Title'"'
echo 'HDD_UDMA_CRC_Errors="'$HDD_UDMA_CRC_Errors'"'
echo 'HDD_UDMA_CRC_Errors_Title="'$HDD_UDMA_CRC_Errors_Title'"'
echo 'HDD_Seek_Error_Rate="'$HDD_Seek_Error_Rate'"'
echo 'HDD_Seek_Error_Rate_Title="'$HDD_Seek_Error_Rate_Title'"'
echo 'HDD_MultiZone_Errors="'$HDD_MultiZone_Errors'"'
echo 'HDD_MultiZone_Errors_Title="'$HDD_MultiZone_Errors_Title'"'
echo 'HDD_Helium_Level="'$HDD_Helium_Level'"'
echo 'HDD_Helium_Level_Title="'$HDD_Helium_Level_Title'"'
echo 'HDD_Last_Test_Age="'$HDD_Last_Test_Age'"'
echo 'HDD_Last_Test_Age_Title="'$HDD_Last_Test_Age_Title'"'
echo 'HDD_Last_Test_Type="'$HDD_Last_Test_Type'"'
echo 'HDD_Last_Test_Type_Title="'$HDD_Last_Test_Type_Title'"'
echo " "
echo "# For Solid State Drive Section"
echo 'SSD_Device_ID="'$SSD_Device_ID'"'
echo 'SSD_Device_ID_Title="'$SSD_Device_ID_Title'"'
echo 'SSD_Serial_Number="'$SSD_Serial_Number'"'
echo 'SSD_Serial_Number_Title="'$SSD_Serial_Number_Title'"'
echo 'SSD_Model_Number="'$SSD_Model_Number'"'
echo 'SSD_Model_Number_Title="'$SSD_Model_Number_Title'"'
echo 'SSD_Capacity="'$SSD_Capacity'"'
echo 'SSD_Capacity_Title="'$SSD_Capacity_Title'"'
echo 'SSD_SMART_Status="'$SSD_SMART_Status'"'
echo 'SSD_SMART_Status_Title="'$SSD_SMART_Status_Title'"'
echo 'SSD_Drive_Temp="'$SSD_Drive_Temp'"'
echo 'SSD_Drive_Temp_Title="'$SSD_Drive_Temp_Title'"'
echo 'SSD_Drive_Temp_Min="'$SSD_Drive_Temp_Min'"'
echo 'SSD_Drive_Temp_Min_Title="'$SSD_Drive_Temp_Min_Title'"'
echo 'SSD_Drive_Temp_Max="'$SSD_Drive_Temp_Max'"'
echo 'SSD_Drive_Temp_Max_Title="'$SSD_Drive_Temp_Max_Title'"'
echo 'SSD_Power_On_Hours="'$SSD_Power_On_Hours'"'
echo 'SSD_Power_On_Hours_Title="'$SSD_Power_On_Hours_Title'"'
echo 'SSD_Wear_Level="'$SSD_Wear_Level'"'
echo 'SSD_Wear_Level_Title="'$SSD_Wear_Level_Title'"'
echo 'SSD_Reallocated_Sectors="'$SSD_Reallocated_Sectors'"'
echo 'SSD_Reallocated_Sectors_Title="'$SSD_Reallocated_Sectors_Title'"'
echo 'SSD_Reallocated_Events="'$SSD_Reallocated_Events'"'
echo 'SSD_Reallocated_Events_Title="'$SSD_Reallocated_Events_Title'"'
echo 'SSD_Pending_Sectors="'$SSD_Pending_Sectors'"'
echo 'SSD_Pending_Sectors_Title="'$SSD_Pending_Sectors_Title'"'
echo 'SSD_Offline_Uncorrectable="'$SSD_Offline_Uncorrectable'"'
echo 'SSD_Offline_Uncorrectable_Title="'$SSD_Offline_Uncorrectable_Title'"'
echo 'SSD_UDMA_CRC_Errors="'$SSD_UDMA_CRC_Errors'"'
echo 'SSD_UDMA_CRC_Errors_Title="'$SSD_UDMA_CRC_Errors_Title'"'
echo 'SSD_Last_Test_Age="'$SSD_Last_Test_Age'"'
echo 'SSD_Last_Test_Age_Title="'$SSD_Last_Test_Age_Title'"'
echo 'SSD_Last_Test_Type="'$SSD_Last_Test_Type'"'
echo 'SSD_Last_Test_Type_Title="'$SSD_Last_Test_Type_Title'"'
echo " "
echo "# For NVMe Drive Section"
echo 'NVM_Device_ID="'$NVM_Device_ID'"'
echo 'NVM_Device_ID_Title="'$NVM_Device_ID_Title'"'
echo 'NVM_Serial_Number="'$NVM_Serial_Number'"'
echo 'NVM_Serial_Number_Title="'$NVM_Serial_Number_Title'"'
echo 'NVM_Model_Number="'$NVM_Model_Number'"'
echo 'NVM_Model_Number_Title="'$NVM_Model_Number_Title'"'
echo 'NVM_Capacity="'$NVM_Capacity'"'
echo 'NVM_Capacity_Title="'$NVM_Capacity_Title'"'
echo 'NVM_SMART_Status="'$NVM_SMART_Status'"'
echo 'NVM_SMART_Status_Title="'$NVM_SMART_Status_Title'"'
echo 'NVM_Critical_Warning="'$NVM_Critical_Warning'"'
echo 'NVM_Critical_Warning_Title="'$NVM_Critical_Warning_Title'"'
echo 'NVM_Drive_Temp="'$NVM_Drive_Temp'"'
echo 'NVM_Drive_Temp_Title="'$NVM_Drive_Temp_Title'"'
echo 'NVM_Drive_Temp_Min="'$NVM_Drive_Temp_Min'"               # I have not found this on an NVMe drive yet, so set to false'
echo 'NVM_Drive_Temp_Min_Title="'$NVM_Drive_Temp_Min_Title'"'
echo 'NVM_Drive_Temp_Max="'$NVM_Drive_Temp_Max'"               # I have not found this on an NVMe drive yet, so set to false'
echo 'NVM_Drive_Temp_Max_Title="'$NVM_Drive_Temp_Max_Title'"'
echo 'NVM_Power_On_Hours="'$NVM_Power_On_Hours'"'
echo 'NVM_Power_On_Hours_Title="'$NVM_Power_On_Hours_Title'"'
echo 'NVM_Wear_Level="'$NVM_Wear_Level'"'
echo 'NVM_Wear_Level_Title="'$NVM_Wear_Level_Title'"'
echo " "
echo " "
echo "###### Drive Ignore List"
echo "# What does it do:"
echo "#  Use this to list any drives to ignore and remove from the report.  This is very useful for ignoring USB Flash Drives"
echo '#  or other drives for which good data is not able to be collected (non-standard).'
echo "#"
echo "# How to use it:"
echo "#  We are using a comma delimited file to identify the drive serial numbers.  You MUST use the exact and full serial"
echo "#  number smartctl reports, if there is no identical match then it will not match. Additionally you may list drives"
echo "#  from other systems and they will not have any effect on a system where the drive does not exist.  This is great"
echo "#  to have one configuration file that can be used on several systems."
echo "#"
echo '# Example: "VMWare,1JUMLBD,21HNSAFC21410E"'
echo " "
echo 'Ignore_Drives="'$Ignore_Drives'"'
echo " "
echo "###### Drive UDMA_CRC_Error_Count List"
echo "# What does it do:"
echo '#  If you have a drive which has an UDMA count other than 0 (zero), this setting will offset the'
echo "#  value back to zero for the concerns of monitoring future increases of this specific error. Any match will"
echo '#  subtract the given value to report a 0 (zero) value and highlight it in yellow to denote it was overridden.'
echo "#  The Warning Title will not be flagged if this is zero'd out in this manner."
echo "#  NOTE: UDMA_CRC_Errors are typically permanently stored in the drive and cannot be reset to zero even though"
echo "#        they are frequently caused by a data cable communications error."
echo "#"
echo "# How to use it:"
echo "#  List each drive by serial number and include the current UDMA_CRC_Error_Count value."
echo "#  The format is very specific and will not work if you "wing it", use the Live EXAMPLE."
echo "#"
echo "#  Set the FLAG in the FLAGS Section ignoreUDMA to false."
echo "#"
echo "# If the error count exceeds the limit minus the offset then a warning message will be generated."
echo "# On the Status Report the UDMA CRC Errors block will be YELLOW with a value of "0" for an overridden value."
echo "#   -- NOTE: We are using the colon : as the separator between the drive serial number and the value to change."
echo "#"
echo "# Format: variable="Drive_Serial_Number:Current_UDMA_Error_Count" and add a comma if you have more than one drive."
echo "#"
echo "# The below example shows drive WD-WMC4N2578099 has 1 UDMA_CRC_Error, drive S2X1J90CA48799 has 2 errors."
echo "#"
echo '# Live Example: "WD-WMC4N2578099:1,S2X1J90CA48799:2,P02618119268:1"'
echo " "
echo 'CRC_ERRORS="'$CRC_ERRORS'"'
echo " "
echo "###### Multi_Zone_Errors List"
echo "# What does it do:"
echo "#   This identifies drives with Multi_Zone_Errors which may be irritating people."
echo "#   Multi_Zone_Errors "for some drives, not all drives" are pretty much meaningless."
echo "#"
echo "# How to use it:"
echo '#   Use same format as CRC_Errors.'
echo " "
echo 'MULTI_Zone="'$MULTI_Zone'"'
echo " "
echo "#######  Reallocated Sectors Exceptions"
echo "# What does it do:"
echo "#  This will offset any Reallocated Sectors count by the value provided."
echo "#"
echo "#  I do not recommend using this feature as I'm a believer in if you have over 5 bad sectors, odds are the drive will get worse."
echo "#  I'd recommend replacing the drive before complete failure.  But that is your decision."
echo "#"
echo "#  Why is it even an option?"
echo "#  I use it for testing purposes only but you may want to use it."
echo "#"
echo "# How to use it:"
echo '#   Use same format as CRC_Errors.'
echo " "
echo 'BAD_SECTORS="'$BAD_SECTORS'"'
echo " "
echo "####### Warranty Expiration Date"
echo "# What does it do:"
echo "# This section is used to add warranty expirations for designated drives and to create an alert when they expire."
echo "# The date format is YYYY-MM-DD."
echo "#"
echo "# Below is an example for the format using my own drives, which yes, are expired."
echo "# As previously stated above, drive serial numbers must be an exact match to what smartctl reports to function."
echo "#"
echo "# If the drive does not exist, for example my drives are not on your system, then nothing will happen."
echo "#"
echo "# How to use it:"
echo '#   Use the format ="Drive_Serial_Number:YYYY-MM-DD" and add a comma if you have more than one drive.'
echo " "
echo 'DRIVE_WARRANTY="'$DRIVE_WARRANTY'"'
echo " "
echo "###### Global table of colors"
echo "# The colors selected you can change but you will need to look up the proper HEX code for a color."
echo " "
echo 'okColor="'$okColor'"       # Hex code for color to use in SMART Status column if drives pass (default is light green, #c9ffcc).'
echo 'warnColor="'$warnColor'"     # Hex code for WARN color (default is purple, #f765d0).'
echo 'critColor="'$critColor'"     # Hex code for CRITICAL color (default is red, #ff0000).'
echo 'altColor="'$altColor'"      # Table background alternates row colors between white and this color (default is light gray, #f4f4f4).'
echo 'whtColor="'$whtColor'"      # Hex for White background.'
echo 'ovrdColor="'$ovrdColor'"     # Hex code for Override Yellow.'
echo 'blueColor="'$blueColor'"     # Hex code for Sky Blue, used for the SCRUB In Progress background.'
echo 'yellowColor="'$yellowColor'"   # Hex code for pale yellow.'

) > "$Config_File_Name"

}
################################## CLEAN UP TEMPORARY FILES #######################################

cleanup_files () {
### Clean up our temporary files
if test -e "$logfile"; then rm "$logfile"; fi
if test -e "$logfile_header"; then rm "$logfile_header"; fi
if test -e "$logfile_critical"; then rm "$logfile_critical"; fi
if test -e "$logfile_warning"; then rm "$logfile_warning"; fi
if test -e "$logfile_warranty"; then rm "$logfile_warranty"; fi
if test -e "$logfile_messages"; then rm "$logfile_messages"; fi
f=(/tmp/drive_*.txt)
if [[ -f "${f[0]}" ]]; then rm /tmp/drive_*.txt; fi

}

################################# CLEAR VARIABLES ###############################################

clear_variables () {
if [[ $Silence == "off" ]]; then echo "Running clear_variables routine"; fi

### Null out variables for get_drive_data function before using them again

altlastTestHours=""
altlastTestType=""
capacity=""
chkreadfailure=""
crcErrors=""
lastTestHours=""
lastTestType=""
loadCycle=""
modelnumber=""
multiZone=""
NVMcriticalWarning=""
offlineUnc=""
onHours=""
pending=""
reAlloc=""
reAllocEvent=""
rotation=""
seekErrorHealth=""
seekErrorHealth2=""
serial=""
smartStatus=""
smarttesting=""
startStop=""
spinRetry=""
temp=""
temp_max=""
wearLevel=""
onTime=""
testAge=""
SER=""
Helium=""
seagate=""
seekErrorRate=""
rawReadErrorRate=""
seek=""

# And Reset bgColors
if [[ "$bgColor" == "$altColor" ]]; then bgColor="#ffffff"; else bgColor="$altColor"; fi
deviceStatusColor=$bgColor
smartStatusColor=$bgColor
tempColor=$bgColor
temp_maxColor=$bgColor
onTimeColor=$bgColor
spinRetryColor=$bgColor
reAllocColor=$bgColor
reAllocEventColor=$bgColor
pendingColor=$bgColor
offlineUncColor=$bgColor
crcErrorsColor=$bgColor
seekErrorHealthColor=$bgColor
rawReadErrorRateColor=$bgColor
multiZoneColor=$bgColor
testAgeColor=$bgColor
lastTestTypeColor=$bgColor
wearLevelColor=$bgColor
NVMcriticalWarningColor=$bgColor
HeliumColor=$bgColor

}

################# GENERATE CONFIG FILE ##############

generate_config_file () {
if [[ $Silence == "off" ]]; then echo "Running generate_config_file routine"; fi

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
Config_File_Name="$SCRIPT_DIR/multi_report_config.txt"
for (( z=1; z<=50; z++ ))
do
clear
echo $programver
echo " "
echo "         Configuration File Management"
echo " "
if test -e "$Config_File_Name"; then
echo " *** WARNING - A CONFIGURATION CURRENTLY FILE EXISTS ***"
fi
echo " "
echo " "
echo "  Select an option and press Enter/Return:"
echo " "
echo "       N)ew configuration file  (creates a new clean configuration external file)"
echo " "
echo "       A)dvanced configuration (must have a configuration file alredy present)"
echo " "
echo "       U)pdate configuration file to current version (Future Feature)"
echo " "
echo "       H)ow to use this configuration tool"
echo " "
echo "       X) Exit"
echo " "
echo " "
echo "NOTE: In using this configuration script when the value is:"
echo "  Number or Text: the current value will be displayed. You have the option to just"
echo "press Enter/Return to accept the current value or you may enter a different value."
echo " "
echo "  true or false: the current value will be displayed. You have the option to just"
echo "press Enter/Return to accept the current value or you may press 't' for true or"
echo "'f' for false."
echo " "
echo " "
echo -n "   Make your selection: "
read -n 1 Keyboard_var
shopt -s nocasematch
case $Keyboard_var in
# First Level Start
    A)
    clear
    echo " "
    echo "            Advanced Configuration Settings"
    echo " "
    echo " Loading Configuration File Data..."
    echo " "
       if [[ ! -f "$Config_File_Name" ]]; then
       echo "You do not have an external configuration file yet. Please create a New configuration file first."
       echo " "   
       exit 1
       fi
    load_config

    echo "This is not a complete configuration setup, it is just the most common settings"
    echo "that a user would expectedly require for a normal setup.  You may directly"
    echo "edit the config text file with any text editor to take full advantage of the options."
    echo " "
    echo "The config text file is located here: "$Config_File_Name
    echo " "
     for (( x=1; x<=50; x++ ))
     do
    clear
    echo "            Advanced Configuration Settings"
    echo " "
    echo " "
    echo "   A) Alarm Setpoints (Temp, Zpool, Media, Activate In/Out, Ignore)" 
    echo " "
    echo "   B) Config-Backup"
    echo " "
    echo "   C) Email Address" 
    echo " "
    echo "   D) HDD Column Selection"
    echo " "
    echo "   E) SSD Column Selection"
    echo " "
    echo "   F) NVMe Column Selection"
    echo " "
    echo "   G) Output Formats (Hours, Temp, Non-Existant)"
    echo " "
    echo "   H) Report Header Titles" 
    echo " "
    echo "   I) Statistical Data File Setup"
    echo " "
    echo "   J) TLER / SCT"
    echo " "
    echo "   K) Drive Errors and Custom Builds (Ignore Drives, UDMA CRC, MultiZone,"
    echo "            Reallocated Sectors, Warranty Expiration, Person Specific Custom)"
    echo " "
    echo "   W) Write Configuration File"
    echo " "
    echo "   X) Exit - Will not automatically save changes"
    echo " "
    echo -n "   Make your selection: "
    read -n 1 Keyboard_var2
    echo " " 
    shopt -s nocasematch
    case $Keyboard_var2 in
# Second Level Start
         A)

         for (( y=1; y<=50; y++ ))
         do
         clear
         echo "            Alarm Configuration Settings"
         echo " "
         echo " "
         echo "   A) Temperature Settings" 
         echo " "
         echo "   B) Zpool Settings"
         echo " "
         echo "   C) Media Alarm Settings"
         echo " "
         echo "   D) Activate Input/Output Settings" 
         echo " "
         echo "   E) Ignore Alarms"
         echo " "
         echo "   X) Exit - Return to previous menu"
         echo " "
         echo -n "   Make your selection: "
         read -n 1 Keyboard_var3
         echo " " 
         shopt -s nocasematch
         case $Keyboard_var3 in

               A)
               clear 
               echo "Temperature Settings"
               echo " "
               echo -n "HDD Warning Temperature ("$HDDtempWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then HDDtempWarn=$Keyboard_yn; fi
               echo "Set Value: ("$HDDtempWarn")"
               echo " "
               echo -n "HDD Critical Temperature ("$HDDtempCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then HDDtempCrit=$Keyboard_yn; fi
               echo "Set Value: ("$HDDtempCrit")"
               echo " "
               echo -n "HDD Max Temperature Override for Power Cycle Enabled ("$HDDmaxovrd") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then HDDmaxovrd="true"; else HDDmaxovrd="false"; fi
               fi
               echo "Set Value: ("$HDDmaxovrd")"
               echo " "
               echo -n "SSD Warning Temperature ("$SSDtempWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then SSDtempWarn=$Keyboard_yn; fi
               echo "Set Value: ("$SSDtempWarn")"
               echo " "
               echo -n "SSD Critical Temperature ("$SSDtempCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then SSDtempCrit=$Keyboard_yn; fi
               echo "Set Value: ("$SSDtempCrit")"
               echo " "
               echo -n "SSD Max Temperature Override for Power Cycle Enabled ("$SSDmaxovrd") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then SSDmaxovrd="true"; else SSDmaxovrd="false"; fi
               fi
               echo "Set Value: ("$SSDmaxovrd")"
               echo " "
               echo -n "NVMe Warning Temperature ("$NVMtempWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then NVMtempWarn=$Keyboard_yn; fi
               echo "Set Value: ("$NVMtempWarn")"
               echo " "
               echo -n "NVMe Critical Temperature ("$NVMtempCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then NVMtempCrit=$Keyboard_yn; fi
               echo "Set Value: ("$NVMtempCrit")"
               echo " "
               echo "returning..."
               sleep 2
               ;;

               B)
               clear
               echo "Zpool Settings"
               echo " "
               echo -n "Scrub maximum days since last completion ("$scrubAgeWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then scrubAgeWarn=$Keyboard_yn; fi
               echo "Set Value: ("$scrubAgeWarn")"
               echo " "
               echo -n "Pool Space Used Alert ("$usedWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then usedWarn=$Keyboard_yn; fi
               echo "Set Value: ("$usedWarn")"
               echo " "
               echo "returning..."
               sleep 2
               ;;

               C)
               clear
               echo "Media Alarm Settings"
               echo " "
               echo -n "SSD/NVMe Wear Level lower limit ("$wearLevelCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then wearLevelCrit=$Keyboard_yn; fi
               echo "Set Value: ("$wearLevelCrit")"
               echo " "
               echo -n "Sector Errors Warning ("$sectorsWarn") "
               read Keyboard_yn 
               if [[ ! $Keyboard_yn == "" ]]; then sectorsWarn=$Keyboard_yn; fi
               echo "Set Value: ("$sectorsWarn")"
               echo " "
               echo -n "Sector Errors Critical ("$sectorsCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then sectorsCrit=$Keyboard_yn; fi
               echo "Set Value: ("$sectorsCrit")"
               echo " "
               echo -n "Reallocated Sectors Warning ("$reAllocWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then reAllocWarn=$Keyboard_yn; fi
               echo "Set Value: ("$reAllocWarn")"
               echo " "
               echo -n "Raw Read Errors Warning ("$rawReadWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then rawReadWarn=$Keyboard_yn; fi
               echo "Set Value: ("$rawReadWarn")"
               echo " "
               echo -n "Raw Read Errors Critical ("$rawReadCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then rawReadCrit=$Keyboard_yn; fi
               echo "Set Value: ("$rawReadCrit")"
               echo " "
               echo -n "Seek Errors Warning ("$seekErrorsWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then seekErrorsWarn=$Keyboard_yn; fi
               echo "Set Value: ("$seekErrorsWarn")"
               echo " "
               echo -n "Seek Errors Critical ("$seekErrorsCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then seekErrorsCrit=$Keyboard_yn; fi
               echo "Set Value: ("$seekErrorsCrit")"
               echo " "
               echo -n "MultiZone Errors Warning ("$multiZoneWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then multiZoneWarn=$Keyboard_yn; fi
               echo "Set Value: ("$multiZoneWarn")"
               echo " "
               echo -n "MultiZone Errors Critical ("$multiZoneCrit") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then multiZoneCrit=$Keyboard_yn; fi
               echo "Set Value: ("$multiZoneCrit")"
               echo " "
               echo -n "Helium Minimum Level ("$heliumMin") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then heliumMin=$Keyboard_yn; fi
               echo "Set Value: ("$heliumMin")"
               echo " "
               echo -n "Helium Critical Alert Message ("$heliumAlarm") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then heliumAlarm="true"; else heliumAlarm="false"; fi
               fi
               echo "Set Value: ("$heliumAlarm")"
               echo " "
               echo -n "S.M.A.R.T. Test Age Warning ("$testAgeWarn") "
               read Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then testAgeWarn=$Keyboard_yn; fi
               echo "Set Value: ("$testAgeWarn")"
               echo " "
               echo -n "Flag Device ID RED on Error ("$deviceRedFlag") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then deviceRedFlag="true"; else deviceRedFlag="false"; fi
               fi
               echo "Set Value: ("$deviceRedFlag")"
               echo " "
               echo "returning..."
               sleep 2      
               ;;

               D)
               clear
               echo "Activate/Disable Input/Output Settings"
               echo " "
               echo -n "Include SSD's in report ("$includeSSD") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then includeSSD="true"; else includeSSD="false"; fi
               fi
               echo "Set Value: ("$includeSSD")"
               echo " "     
               echo -n "Include NVMe's in report ("$includeNVM") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then includeNVM="true"; else includeNVM="false"; fi
               fi
               echo "Set Value: ("$includeNVM")"
               echo " "
               echo -n "Report Non-SMART Devices ("$reportnonSMART") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then reportnonSMART="true"; else reportnonSMART="false"; fi
               fi
               echo "Set Value: ("$reportnonSMART")"
               echo " "
               echo -n "Remove Non-SMART Data from report ("$disableRAWdata") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then disableRAWdata="true"; else disableRAWdata="false"; fi
               fi
               echo "Set Value: ("$disableRAWdata")"
               echo " "
               echo "returning..."
               sleep 2
               ;;

               E)
               clear
               echo "Ignore Alarm Settings"
               echo " "
               echo -n "Ignore UDMA CRC Errors ("$ignoreUDMA") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then ignoreUDMA="true"; else ignoreUDMA="false"; fi
               fi
               echo "Set Value: ("$ignoreUDMA")"
               echo " "
               echo -n "Ignore Raw Read Errors ("$ignoreReadError") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then ignoreReadError="true"; else ignoreReadError="false"; fi
               fi
               echo "Set Value: ("$ignoreReadError")"
               echo " "
               echo -n "Ignore Seek Errors ("$ignoreSeekError") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then ignoreSeekError="true"; else ignoreSeekError="false"; fi
               fi
               echo "Set Value: ("$ignoreSeekError")"
               echo " "
               echo -n "Ignore MultiZone Errors ("$ignoreMultiZone") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then ignoreMultiZone="true"; else ignoreMultiZone="false"; fi
               fi
               echo "Set Value: ("$ignoreMultiZone")"
               echo " "
               echo -n "Disable Warranty Email Header Warning ("$disableWarranty") "
               read -n 1 Keyboard_yn
               if [[ ! $Keyboard_yn == "" ]]; then
                  if [[ $Keyboard_yn == "t" ]]; then disableWarranty="true"; else disableWarranty="false"; fi
               fi
               echo "Set Value: ("$disableWarranty")"
               echo " "
               echo "returning..."
               sleep 2
               ;;

               X)
              clear
              echo "Returning to the previous menu..."
              sleep 2
              y=100
              ;;


              *)
              echo "Invalid Option"
              sleep 2
              ;;
         esac
         done
         ;;


         B)
         clear
         echo "TrueNAS Configuration Backup Setup"
         echo " "
         echo -n "Save a local copy of the config-backup file ("$saveBackup") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then saveBackup="true"; else saveBackup="false"; fi
         fi
         echo "Set Value: ("$saveBackup")"
         echo " "
         echo "TrueNAS Backup Configuration file location ("$backupLocation")"
         echo -n "Enter new location or press Enter/Return to accecpt current value:"
         read Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then backupLocation=$Keyboard_yn; fi
         echo "Set Value: ("$backupLocation")"
         echo " "
         echo -n "Configuration Backup Enabled ("$configBackup") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then configBackup="true"; else configBackup="false"; fi
         fi
         echo "Set Value: ("$configBackup")"
         echo " "
         echo "What day of the week would you like the file attached?"
         echo "Current Value: "$configSendDay
         echo "(All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)"
         echo -n "Enter: "
         read Keyboard_HDD
         if [[ ! $Keyboard_HDD == "" ]]; then configSendDay=$Keyboard_HDD; fi
         echo "Set Value: ("$configSendDay")"
         echo " "
         echo "returning..."
         sleep 2
         ;;


         C)
         clear
         echo "Email Settings"
         echo " "
         echo "Current email address: "$email" "
         read Keyboard_email
         if [[ ! $Keyboard_email == "" ]]; then email=$Keyboard_email; fi
         echo "Set Value: "$email
         echo " "
         echo " "
         echo "Current from address: "$from" "
         read Keyboard_email
         if [[ ! $Keyboard_email == "" ]]; then from=$Keyboard_email; fi
         echo "Set Value: "$from
         echo " "
         echo "returning..."
         sleep 2
         ;;


         D)
         clear
         echo "HDD Column Selection"
         echo " "
         echo -n "Device ID ("$HDD_Device_ID") "  
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Device_ID="true"; else HDD_Device_ID="false"; fi
         fi
         echo "Set Value: ("$HDD_Device_ID")"
         echo " "
         echo -n "Serial Number ("$HDD_Serial_Number") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Serial_Number="true"; else HDD_Serial_Number="false"; fi
         fi
         echo "Set Value: ("$HDD_Serial_Number")"
         echo " "
         echo -n "Model Number ("$HDD_Model_Number") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Model_Number="true"; else HDD_Model_Number="false"; fi
         fi
         echo "Set Value: ("$HDD_Model_Number")"
         echo " "
         echo -n "Capacity ("$HDD_Capacity") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Capacity="true"; else HDD_Capacity="false"; fi
         fi
         echo "Set Value: ("$HDD_Capacity")"
         echo " "
         echo -n "Rotational Rate ("$HDD_Rotational_Rate") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Rotational_Rate="true"; else HDD_Rotational_Rate="false"; fi
         fi
         echo "Set Value: ("$HDD_Rotational_Rate")"
         echo " "
         echo -n "SMART Status ("$HDD_SMART_Status") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_SMART_Statusy="true"; else HDD_SMART_Status="false"; fi
         fi
         echo "Set Value: ("$HDD_SMART_Status")"
         echo " "
         echo -n "Drive Temp ("$HDD_Drive_Temp") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Drive_Temp="true"; else HDD_Drive_Temp="false"; fi
         fi
         echo "Set Value: ("$HDD_Drive_Temp")"
         echo " "
         echo -n "Drive Temp Minimum for power cycle ("$HDD_Drive_Temp_Min") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Drive_Temp_Min="true"; else HDD_Drive_Temp_Min="false"; fi
         fi
         echo "Set Value: ("$HDD_Drive_Temp_Min")"
         echo " "
         echo -n "Drive Temp Maximum for power cycle ("$HDD_Drive_Temp_Max") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Drive_Temp_Max="true"; else HDD_Drive_Temp_Max="false"; fi
         fi
         echo "Set Value: ("$HDD_Drive_Temp_Max")"
         echo " "
         echo -n "Power On Hours ("$HDD_Power_On_Hours") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Power_On_Hours="true"; else HDD_Power_On_Hours="false"; fi
         fi
         echo "Set Value: ("$HDD_Power_On_Hours")"
         echo " "
         echo -n "Start / Stop Count ("$HDD_Start_Stop_Count") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Start_Stop_Count="true"; else HDD_Start_Stop_Count="false"; fi
         fi
         echo "Set Value: ("$HDD_Start_Stop_Count")"
         echo " "
         echo -n "Load Cycle Count ("$HDD_Load_Cycle") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Load_Cycle="true"; else HDD_Load_Cycle="false"; fi
         fi
         echo "Set Value: ("$HDD_Load_Cycle")"
         echo " "
         echo -n "Spin Retry Count ("$HDD_Spin_Retry") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Spin_Retry="true"; else HDD_Spin_Retry="false"; fi
         fi
         echo "Set Value: ("$HDD_Spin_Retry")"
         echo " "
         echo -n "Reallocated Sectors ("$HDD_Reallocated_Sectors") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Reallocated_Sectors="true"; else HDD_Reallocated_Sectors="false"; fi
         fi
         echo "Set Value: ("$HDD_Reallocated_Sectors")"
         echo " "
         echo -n "Reallocated Events ("$HDD_Reallocated_Events") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Reallocated_Events="true"; else HDD_Reallocated_Events="false"; fi
         fi
         echo "Set Value: ("$HDD_Reallocated_Events")"
         echo " "
         echo -n "Pending Sectors ("$HDD_Pending_Sectors") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Pending_Sectors="true"; else HDD_Pending_Sectors="false"; fi
         fi
         echo "Set Value: ("$HDD_Pending_Sectors")"
         echo " "
         echo -n "Offline Uncorrectable Errors ("$HDD_Offline_Uncorrectable") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Offline_Uncorrectable="true"; else HDD_Offline_Uncorrectable="false"; fi
         fi
         echo "Set Value: ("$HDD_Offline_Uncorrectable")"
         echo " "
         echo -n "UDMA CRC Errors ("$HDD_UDMA_CRC_Errors") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_UDMA_CRC_Errors="true"; else HDD_UDMA_CRC_Errors="false"; fi
         fi
         echo "Set Value: ("$HDD_UDMA_CRC_Errors")"
         echo " "
         echo -n "Raw Read Error Rate ("$HDD_Raw_Read_Error_Rate") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Raw_Read_Error_Rate="true"; else HDD_Raw_Read_Error_Rate="false"; fi
         fi
         echo "Set Value: ("$HDD_Raw_Read_Error_Rate")"
         echo " "
         echo -n "Seek Error Rate ("$HDD_Seek_Error_Rate") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Seek_Error_Rate="true"; else HDD_Seek_Error_Rate="false"; fi
         fi
         echo "Set Value: ("$HDD_Seek_Error_Rate")"
         echo " "
         echo -n "MultiZone Errors ("$HDD_MultiZone_Errors") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_MultiZone_Errors="true"; else HDD_MultiZone_Errors="false"; fi
         fi
         echo "Set Value: ("$HDD_MultiZone_Errors")"
         echo " "
         echo -n "Helium Level ("$HDD_Helium_Level") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Helium_Level="true"; else HDD_Helium_Level="false"; fi
         fi
         echo "Set Value: ("$HDD_Helium_Level")"
         echo " "
         echo -n "Last Test Age ("$HDD_Last_Test_Age") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Last_Test_Age="true"; else HDD_Last_Test_Age="false"; fi
         fi
         echo "Set Value: ("$HDD_Last_Test_Age")"
         echo " "
         echo -n "Last Test Type ("$HDD_Last_Test_Type") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then HDD_Last_Test_Type="true"; else HDD_Last_Test_Type="false"; fi
         fi
         echo "Set Value: ("$HDD_Last_Test_Type")"
         echo " "
         echo " "
         echo "returning..."
         sleep 2
         ;;


         E)
         clear
         echo "SSD Column Selection"
         echo " "
         echo -n "Device ID ("$SSD_Device_ID") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Device_ID="true"; else SSD_Device_ID="false"; fi
         fi
         echo "Set Value: ("$SSD_Device_ID")"
         echo " "
         echo -n "Serial Number ("$SSD_Serial_Number") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Serial_Number="true"; else SSD_Serial_Number="false"; fi
         fi
         echo "Set Value: ("$SSD_Serial_Number")"
         echo " "
         echo -n "Model Number ("$SSD_Model_Number") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Model_Number="true"; else SSD_Model_Number="false"; fi
         fi
         echo "Set Value: ("$SSD_Model_Number")"
         echo " "
         echo -n "Capacity ("$SSD_Capacity") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Capacity="true"; else SSD_Capacity="false"; fi
         fi
         echo "Set Value: ("$SSD_Capacity")"
         echo " "
         echo -n "SMART Status ("$SSD_SMART_Status") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_SMART_Status="true"; else SSD_SMART_Status="false"; fi
         fi
         echo "Set Value: ("$SSD_SMART_Status")"
         echo " " 
         echo -n "Drive Temp ("$SSD_Drive_Temp") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Drive_Temp="true"; else SSD_Drive_Temp="false"; fi
         fi
         echo "Set Value: ("$SSD_Drive_Temp")"
         echo " "
         echo -n "Drive Temp Minimum for power cycle ("$SSD_Drive_Temp_Min") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Drive_Temp_Min="true"; else SSD_Drive_Temp_Min="false"; fi
         fi
         echo "Set Value: ("$SSD_Drive_Temp_Min")"
         echo " "
         echo -n "Drive Temp Maximum for power cycle ("$SSD_Drive_Temp_Max") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Drive_Temp_Max="true"; else SSD_Drive_Temp_Max="false"; fi
         fi
         echo "Set Value: ("$SSD_Drive_Temp_Max")"
         echo " "
         echo -n "Power On Hours ("$SSD_Power_On_Hours") "
         read -n 1 Keyboard_yn
         if [[ ! $Keyboard_yn == "" ]]; then
            if [[ $Keyboard_yn == "t" ]]; then SSD_Power_On_Hours="true"; else SSD_Power_On_Hours="false"; fi
         fi
         echo "Set Value: ("$SSD_Power_On_Hours")"
         echo " "
         echo -n "Wear Level ("$SSD_Wear_Level") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Wear_Level="true"; else SSD_Wear_Level="false"; fi
        fi
        echo "Set Value: ("$SSD_Wear_Level")"
        echo " "
        echo -n "Reallocated Sectors ("$SSD_Reallocated_Sectors") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Reallocated_Sectors="true"; else SSD_Reallocated_Sectors="false"; fi
        fi
        echo "Set Value: ("$SSD_Reallocated_Sectors")"
        echo " "
        echo -n "Reallocated Events ("$SSD_Reallocated_Events") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Reallocated_Events="true"; else SSD_Reallocated_Events="false"; fi
        fi
        echo "Set Value: ("$SSD_Reallocated_Events")"
        echo " "
        echo -n "Pending Sectors ("$SSD_Pending_Sectors") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Pending_Sectors="true"; else SSD_Pending_Sectors="false"; fi
        fi
        echo "Set Value: ("$SSD_Pending_Sectors")"
        echo " "
        echo -n "Offline Uncorrectable Errors ("$SSD_Offline_Uncorrectable") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Offline_Uncorrectable="true"; else SSD_Offline_Uncorrectable="false"; fi
        fi
        echo "Set Value: ("$SSD_Offline_Uncorrectable")"
        echo " "
        echo -n "UDMA CRC Errors ("$SSD_UDMA_CRC_Errors") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_UDMA_CRC_Errors="true"; else SSD_UDMA_CRC_Errors="false"; fi
        fi
        echo "Set Value: ("$SSD_UDMA_CRC_Errors")"
        echo " "
        echo -n "Last Test Age ("$SSD_Last_Test_Age") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Last_Test_Age="true"; else SSD_Last_Test_Age="false"; fi
        fi
        echo "Set Value: ("$SSD_Last_Test_Age")"
        echo " "
        echo -n "Last Test Type ("$SSD_Last_Test_Type") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SSD_Last_Test_Type="true"; else SSD_Last_Test_Type="false"; fi
        fi
        echo "Set Value: ("$SSD_Last_Test_Type")"
        echo " "
        echo "returning..."
        sleep 2
        ;;


        F)
        clear
        echo "NVMe Column Selection"
        echo " "
        echo -n "Device ID ("$NVM_Device_ID") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Device_ID="true"; else NVM_Device_ID="false"; fi
        fi
        echo "Set Value: ("$NVM_Device_ID")"
        echo " "
        echo -n "Serial Number ("$NVM_Serial_Number") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Serial_Number="true"; else NVM_Serial_Number="false"; fi
        fi
        echo "Set Value: ("$NVM_Serial_Number")"
        echo " "
        echo -n "Model Number ("$NVM_Model_Number") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Model_Number="true"; else NVM_Model_Number="false"; fi
        fi
        echo "Set Value: ("$NVM_Model_Number")"
        echo " "
        echo -n "Capacity ("$NVM_Capacity") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Capacity="true"; else NVM_Capacity="false"; fi
        fi
        echo "Set Value: ("$NVM_Capacity")"
        echo " "
        echo -n "SMART Status ("$NVM_SMART_Status") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_SMART_Status="true"; else NVM_SMART_Status="false"; fi
        fi
        echo "Set Value: ("$NVM_SMART_Status")"
        echo " "
        echo -n "Critical Warning Status ("$NVM_Critical_Warning") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Critical_Warning="true"; else NVM_Critical_Warning="false"; fi
        fi
        echo "Set Value: ("$NVM_Critical_Warning")"
        echo " "
        echo -n "Drive Temp ("$NVM_Drive_Temp") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Drive_Temp="true"; else NVM_Drive_Temp="false"; fi
        fi
        echo "Set Value: ("$NVM_Drive_Temp")"
        echo " "
        echo -n "Drive Temp Minimum for power cycle ("$NVM_Drive_Temp_Min") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Drive_Temp_Min="true"; else NVM_Drive_Temp_Min="false"; fi
        fi
        echo "Set Value: ("$NVM_Drive_Temp_Min")"
        echo " "
        echo -n "Drive Temp Maximum for power cycle ("$NVM_Drive_Temp_Max") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Drive_Temp_Max="true"; else NVM_Drive_Temp_Max="false"; fi
        fi
        echo "Set Value: ("$NVM_Drive_Temp_Max")"
        echo " "
        echo -n "Power On Hours ("$NVM_Power_On_Hours") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Power_On_Hours="true"; else NVM_Power_On_Hours="false"; fi
        fi
        echo "Set Value: ("$NVM_Power_On_Hours")"
        echo " "
        echo -n "Wear Level ("$NVM_Wear_Level") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then NVM_Wear_Level="true"; else NVM_Wear_Level="false"; fi
        fi
        echo "Set Value: ("$NVM_Wear_Level")"
        echo " "
        echo " "
        echo "returning..."
        sleep 2
        ;;


        G)
        clear
        echo "Output Formats"
        echo " "
        echo "Power On Hours Time Format ("$powerTimeFormat") "
        echo -n "valid options are "ymdh", "ymd", "ym", "y", or "h" (year month day hour): "
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then powerTimeFormat=$Keyboard_yn; fi
        echo "Set Value: "$powerTimeFormat
        echo " "
        echo "Temperature Display ("$tempdisplay") "
        echo -n "you may use what you want, Common formats are: *C, ^C, or ^c: "
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then tempdisplay=$Keyboard_yn; fi
        echo "Set Value: "$tempdisplay
        echo " "
        echo "Non-existant Value ("$non_exist_value") "
        echo -n "you may use what you want, Common formats are: ---, N/A, or a space character: "
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then non_exist_value=$Keyboard_yn; fi
        echo "Set Value: "$non_exist_value
        echo " "
        echo "returning..."
        sleep 2
        ;;

        H)
        clear
        echo "Report Header Titles"
        echo " "
        echo -n 'HDD Report Header "'$HDDreportTitle'" '
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then HDDreportTitle=$Keyboard_yn; fi
        echo 'Set Value: "'$HDDreportTitle'"'
        echo " "
        echo -n 'SSD Report Header "'$SSDreportTitle'" '
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then SSDreportTitle=$Keyboard_yn; fi
        echo 'Set Value: "'$SSDreportTitle'"'
        echo " "
        echo -n 'NVM Report Header "'$NVMreportTitle'" '
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then NVMreportTitle=$Keyboard_yn; fi
        echo 'Set Value: "'$NVMreportTitle'"'
        echo " "
        echo "returning..."
        sleep 2
        ;;


        I)
        clear
        echo "Statistical Data Setup"
        echo " "
        echo "Statistical file location and name ("$statistical_data_file")"
        echo "Enter new location and file name or press Enter/Return to accecpt current value:"
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then statistical_data_file=$Keyboard_yn; fi
        echo "Set Value: ("$statistical_data_file")"
        echo " "
        echo " "
        echo -n "Statistical Data Recording Enabled ("$expDataEnable") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then expDataEnable="true"; else expDataEnable="false"; fi
        fi
        echo "Set Value: ("$expDataEnable")"
        echo " "
        echo -n "Statistical Data Email Enabled ("$expDataEmail") "
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then expDataEmail="true"; else expDataEmail="false"; fi
        fi
        echo "Set Value: ("$expDataEmail")"
        echo " "
        echo -n "Statistical Data Purge Days ("$expDataPurge") "
        read Keyboard_HDD
        if [[ ! $Keyboard_HDD == "" ]]; then expDataPurge=$Keyboard_HDD; fi
        echo "Set Value: ("$expDataPurge")"
        echo " "
        echo "What day of the week would you like the file attached?"
        echo "Current Value: "$expDataEmailSend
        echo "(All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)"
        echo -n "Enter: "
        read Keyboard_expDataEmailSend
        if [[ ! $Keyboard_expDataEmailSend == "" ]]; then expDataEmailSend=$Keyboard_expDataEmailSend; fi
        echo "Set Value: ("$expDataEmailSend")"
        echo " "
        echo "returning..."
        sleep 2
        ;;


        J)
        clear
        echo "Activate TLER"
        echo " "
        echo " "
        echo "Activate TLER ("$SCT_Drive_Enable") "
        echo "true = This will attempt to turn on TLER if the drive is reporting it is off."
        read -n 1 Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then
           if [[ $Keyboard_yn == "t" ]]; then SCT_Drive_Enable="true"; else SCT_Drive_Enable="false"; fi
        fi
        echo "Set Value: ("$SCT_Drive_Enable")"
        echo " "
        echo "TLER Warning Level: ("$SCT_Warning") "
        echo " 1) TLER_No_Msg = Only generate an error message if TLER cannot be turned on for a supported drive."
        echo " 2) TLER = Report error messages in WARNING Section and email header."
        echo " 3) all = Report drive which also do not support TLER."
        echo -n "Enter: "
        read Keyboard_SCT_Warning
        if [[ $Keyboard_SCT_Warning == "1" ]]; then SCT_Warning="TLER_No_Msg"; fi
        if [[ $Keyboard_SCT_Warning == "2" ]]; then SCT_Warning="TLER"; fi
        if [[ $Keyboard_SCT_Warning == "3" ]]; then SCT_Warning="all"; fi
        echo "Set Value: ("$SCT_Warning")"
        echo " "
        echo -n "SCT Read Timemout Setting ("$SCT_Read_Timeout") "
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then SCT_Read_Timeout=$Keyboard_yn; fi
        echo "Set Value: ("$SCT_Read_Timeout")"
        echo " "
        echo -n "SCT Write Timemout Setting ("$SCT_Write_Timeout") "
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then SCT_Write_Timeout=$Keyboard_yn; fi
        echo "Set Value: ("$SCT_Write_Timeout")"
        echo " "
        echo "returning..."
        sleep 2
        ;;

        K)
        clear
        echo "Drive Errors and Custom Builds"
        echo " "
        echo "Collecting data, Please wait..."
        # Lets go ahead and grab all the drive data we will need for the entire K section.
        get_smartHDD_listings
        get_smartSSD_listings
        get_smartNVM_listings
        smartdrivesall="$smartdrives $smartdrivesSSD $smartdrivesNVM"
        echo " "
        echo "NOTE: Enter a single letter 'd' will delete the data and move to the next section."
        echo " "
        echo "Ignore Drives - Enter the drive serial numbers, multiple drives separated by a comma."
        echo "Current: "$Ignore_Drives
        echo " "
        echo "Enter/Return to accept the current value(s) or press 'e' to Edit"
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then Ignore_Drives=$Keyboard_yn; fi
        if [[ $Keyboard_yn == "d" ]]; then Ignore_Drives="none"; fi
        if [[ $Keyboard_yn == "e" ]]; then
        # Let's list each drive and ask to keep or reject
           for drive in $smartdrivesall; do
              clear_variables
              get_drive_data
              echo " "
              echo "Do you want to ignore this drive (y/n): Drive ID: "$drive" Serial Number: "$serial
              read Keyboard_yn
              if [[ $Keyboard_yn == "y" ]]; then ignoredriveslist=$ignoredriveslist$serial","; fi
           done
           if [[ ! $ignoredriveslist == "" ]]; then Ignore_Drives="$(echo "$ignoredriveslist" | sed 's/.$//')"; else Ignore_Drives="none"; fi
        fi
        echo "Set Value: "$Ignore_Drives
        echo " "
        echo " "
        echo "AUTOMATIC DRIVE COMPENSATION - UDMA_CRC, MultiZone, and Reallocated Sectors"
        echo " "
        echo "You have the option to automatically setup offset values for UDMA_CRC, MultiZone, and Bad Sectors."
        echo "This will scan your drives and for any non-zero value the offset will automatically be added."
        echo " "
        echo "Enter 'y' for yes or 'n' for no."
        read Keyboard_yn
        if [[ $Keyboard_yn == "y" ]]; then
           autoselect=1
           echo "Automatic Configuration selected..."
           echo " "
           for drive in $smartdrivesall; do
              clear_variables
              get_drive_data
              if [[ ! $crcErrors == "0" ]]; then listofdrivescrc="$listofdrivescrc$serial":"$crcErrors,"; fi
              if [[ ! $multiZone == "0" ]] && [[ ! $multiZone == "" ]]; then listofdrivesmulti="$listofdrivesmulti$serial":"$multiZone,"; fi
              if [[ ! $reAlloc == "0" ]]; then listofdrivesbad="$listofdrivesbad$serial":"$reAlloc,"; fi
           done
           echo "Scanning Results:"
           if [[ ! $listofdrivescrc == "" ]]; then CRC_ERRORS="$(echo "$listofdrivescrc" | sed 's/.$//')"; echo "UDMA_CRC Errors detected"; else CRC_ERRORS=""; echo "No UDMA_CRC Errors"; fi
           if [[ ! $listofdrivesmulti == "" ]]; then MULTI_Zone="$(echo "$listofdrivesmulti" | sed 's/.$//')"; echo "MultiZone Errors Detected"; else MULTI_Zone=""; echo "No MultiZone Errors"; fi
           if [[ ! $listofdrivesbad == "" ]]; then BAD_SECTORS="$(echo "$listofdrivesbad" | sed 's/.$//')"; echo "Bad Sectors Detected"; else BAD_SECTORS=""; echo "No Reallocated Sectors"; fi
           echo " "
           echo "Values Set:"
           echo "CRC_Errors: "$CRC_ERRORS
           echo "Multi_Zone_Errors: "$MULTI_Zone
           echo "Reallocated_Sectors: "$BAD_SECTORS
           echo " "
        fi
        if [[ ! $autoselect == "1" ]]; then
           echo "Offset UDMA CRC Errors - Follow the format drive_serial_number:current_error_count and separated by comma for multiple drives."
           echo "Current: "$CRC_ERRORS
           read Keyboard_yn
           if [[ $Keyboard_yn == "d" ]]; then CRC_ERRORS=""; Keyboard_yn=""; fi
           echo "Set Value: "$CRC_ERRORS
           echo " "
           echo "Offset MultiZone Errors - Follow the same format as UDMA CRC Errors"
           echo "Current: "$MULTI_Zone
           read Keyboard_yn
           if [[ ! $Keyboard_yn == "" ]]; then MULTI_Zone=$Keyboard_yn; fi
           if [[ $Keyboard_yn == "d" ]]; then MULTI_Zone=""; fi
           echo "Set Value: "$MULTI_Zone
           echo " "
           echo "Offset Bad Sector Errors - Follow the same format as UDMA CRC Errors"
           echo "Current: "$BAD_SECTORS
           read Keyboard_yn
           if [[ ! $Keyboard_yn == "" ]]; then BAD_SECTORS=$Keyboard_yn; fi
           if [[ $Keyboard_yn == "d" ]]; then BAD_SECTORS=""; fi
           echo "Set Value: "$BAD_SECTORS
        fi
        echo " "
        echo "Drive Warranty Expiration Date Warning - This will provide a yellow background and a text message when the warranty date occurs."
        echo "The format is: drive_serial_number:yyyy-mm-dd and separated by a comma for multiple drives."
        echo "Enter 'd' to delete, 'e' to edit, or Enter/Return for no change."
        echo "Current: "$DRIVE_WARRANTY
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then DRIVE_WARRANTY=$Keyboard_yn; fi
        if [[ $Keyboard_yn == "d" ]]; then DRIVE_WARRANTY=""; fi
        if [[ $Keyboard_yn == "e" ]]; then
           for drive in $smartdrivesall; do
              clear_variables
              get_drive_data
              echo " "
              echo "Do you want to add this drive (y/n): Drive ID: "$drive" Serial Number: "$serial
              read Keyboard_yn
              if [[ $Keyboard_yn == "y" ]]; then
                 echo "Enter the date the drive expires in the following format: yyyy-mm-dd"
                 read Keyboard_yn
                 warrantydrivelist=$warrantydrivelist$serial":"$Keyboard_yn","
              fi
              echo "warrantydrivelist= "$warrantydrivelist
              done
              if [[ ! $warrantydrivelist == "" ]]; then DRIVE_WARRANTY="$(echo "$warrantydrivelist" | sed 's/.$//')"; else DRIVE_WARRANTY=""; fi
         fi
        echo "Set Value: "$DRIVE_WARRANTY
        echo " "
        echo "Custom Hacks ("$custom_hack") "
        echo "Available: mistermanko"
        read Keyboard_yn
        if [[ ! $Keyboard_yn == "" ]]; then custom_hack=$Keyboard_yn; fi
        if [[ $Keyboard_yn == "d" ]]; then custom_hack="none"; fi
        echo "Set Value: "$custom_hack
        echo " "
        echo "returning..."
        sleep 2
        ;; 


        W)
        echo " "
        echo "Writing Configuration File"
        echo " "
        echo " "
        sleep 1
        update_config_file
        echo "File updated."
        echo " "
        x=100
        sleep 1
        ;;


        X)
        echo "Exiting, Not Saving"
        sleep 2
        x=100
        ;;


        *)
        echo "Invalid Option"
        sleep 2
        ;;
# End Second Level
    esac
    done
    ;;


    H)
    clear
    echo "How to use this configuration tool"
    echo " "
    echo "This tool has many options and you should be able to perform a complete configuration using this tool."
    echo " "
    echo "In order to use the advanced options you will need to have created an external configuration file"
    echo "then the tool will be able to read and write to this file."
    echo " "
    echo "Throughout this process you will be asked questions that require three different responses:"
    echo " "
    echo "  1) String content: Where you will either enter a new string followed by the Enter/Return key,"
    echo "     or just press Enter/Return to accept the current value."
    echo " "
    echo "  2) Number content: Where you will either enter a new number followed by the Enter/Return key,"
    echo "     or just press Enter/Return to accept the current value."
    echo " "
    echo "  3) True/False content: Where you will either enter 't' or 'f' followed by the Enter/Return key,"
    echo "     or just press Enter/Return to accept the current value."
    echo " "
    echo "  4) Some options will give you a choice of 'd' to delete the value and continue, or 'e' to Edit."
    echo " "
    echo "Just to re-itterate: Press the Enter/Return key to accept the current value.  Press 't' or 'f' to change"
    echo "to 'true' or 'false'.  Enter a number or string followed by the Enter/Return key to change a value."
    echo " "
    echo "For more detailed Help information, run the program with the '-h' parameter."
    echo " "
    echo "Lastly this configuration process will not, I repeat, will not alter the script file.  It will only"
    echo "alter the configuration file which by default will be located in the same directory as the script is located."
    echo " "
    echo -n "Press any key to continue"
    read -n 1 key
    echo " "
    sleep 1
    ;;


    N)
    clear
    echo "Creating a new configuration file.  This will overwrite an existing file (blank to abort)."
    echo " "
    echo -n "Enter your email address to send the report to: "    
    read Keyboard_email
    if [[ $Keyboard_email == "" ]]; then
       echo "Aborting"
       sleep 2
       continue
    fi
    echo " "
    echo "Enter path and name of statistics file or just hit Enter to use default (recommended): "
    echo 'Default is '$SCRIPT_DIR'/statistical_data_file.csv'
    read Keyboard_statistics
    if [[ $Keyboard_statistics == "" ]]; then echo "Default Selected"; Keyboard_statistics="$SCRIPT_DIR/statisticalsmartdata.csv"; fi
    echo "Set Value: "$Keyboard_statistics
    echo " "
    echo "Would you like to automatically setup for some basic drive offsets (y/n): "
    read Keyboard_yn
    if [[ $Keyboard_yn == "y" ]]; then
    echo " "
    echo "Collecting data, Please wait..."
    get_smartHDD_listings
    get_smartSSD_listings
    get_smartNVM_listings
    smartdrivesall="$smartdrives $smartdrivesSSD $smartdrivesNVM"
    echo " "
    echo "AUTOMATIC DRIVE COMPENSATION - UDMA_CRC, MultiZone, and Reallocated Sectors"
    echo " "
    for drive in $smartdrivesall; do
       clear_variables
       get_drive_data
       if [[ ! $crcErrors == "0" ]]; then listofdrivescrc="$listofdrivescrc$serial":"$crcErrors,"; fi
       if [[ ! $multiZone == "0" ]] && [[ ! $multiZone == "" ]]; then listofdrivesmulti="$listofdrivesmulti$serial":"$multiZone,"; fi
       if [[ ! $reAlloc == "0" ]]; then listofdrivesbad="$listofdrivesbad$serial":"$reAlloc,"; fi
    done
    echo "Scanning Results:"
    if [[ ! $listofdrivescrc == "" ]]; then CRC_ERRORS="$(echo "$listofdrivescrc" | sed 's/.$//')"; echo "UDMA_CRC Errors detected"; else CRC_ERRORS=""; echo "No UDMA_CRC Errors"; fi
    if [[ ! $listofdrivesmulti == "" ]]; then MULTI_Zone="$(echo "$listofdrivesmulti" | sed 's/.$//')"; echo "MultiZone Errors Detected"; else MULTI_Zone=""; echo "No MultiZone Errors"; fi
    if [[ ! $listofdrivesbad == "" ]]; then BAD_SECTORS="$(echo "$listofdrivesbad" | sed 's/.$//')"; echo "Bad Sectors Detected"; else BAD_SECTORS=""; echo "No Reallocated Sectors"; fi
    echo " "
    echo "Values Set:"
    echo "CRC_Errors: "$CRC_ERRORS
    echo "Multi_Zone_Errors: "$MULTI_Zone
    echo "Reallocated_Sectors: "$BAD_SECTORS
    echo " "
    fi
    echo "Creating the new file..."
### This sets the default values up for the external config file.
(
echo "This file is used exclusively to configure the multi_report version 1.6c and later."
echo " "
echo "The configuration file will be created in the same directory as the script."
echo " "
echo "This configuration file only overrides the default values coded into the script.  If you do not want to change"
echo "certain values within the script, you can delete those lines from this configuration file to make it more palatable."
echo " "
echo "###### Email Address ######"
echo "# Enter your email address to send the report to.  The from address does not need to be changed."
echo " "
echo 'email="'$Keyboard_email'"'
echo 'from="TrueNAS@local.com"'
echo " "
echo "###### Custom Hack ######"
echo "# Custom Hacks are for users with generally very unsupported drives and the data must be manually manipulated."
echo "# The goal is to not have any script customized so I will look for fixes where I can."
echo "#"
echo "# Allowable custom hacks are: mistermanko"
echo 'custom_hack="none"'
echo " "
echo "###### Zpool Status Summary Table Settings"
echo " "
echo "usedWarn=80               # Pool used percentage for CRITICAL color to be used."
echo "scrubAgeWarn=37           # Maximum age (in days) of last pool scrub before CRITICAL color will be used (30 + 7 days for day of week). Default=37."
echo " "
echo "###### Temperature Settings"
echo "HDDtempWarn=45            # HDD Drive temp (in C) upper OK limit before a WARNING color/message will be used."
echo "HDDtempCrit=50            # HDD Drive temp (in C) upper OK limit before a CRITICAL color/message will be used."
echo 'HDDmaxovrd="true"         # HDD Max Drive Temp Override. This value when "true" will not alarm on any Current Power Cycle Max Temperature Limit.'
echo "SSDtempWarn=45            # SSD Drive temp (in C) upper OK limit before a WARNING color/message will be used."
echo "SSDtempCrit=50            # SSD Drive temp (in C) upper OK limit before a CRITICAL color/message will be used."
echo 'SSDmaxovrd="true"         # SSD Max Drive Temp Override. This value when "true" will not alarm on any Current Power Cycle Max Temperature Limit.'
echo "NVMtempWarn=50            # NVM Drive temp (in C) upper OK limit before a WARNING color/message will be used."
echo "NVMtempCrit=60            # NVM Drive temp (in C) upper OK limit before a CRITICAL color/message will be used."
echo " "
echo "###### SSD/NVMe Specific Settings"
echo " "
echo "wearLevelCrit=9           # Wear Level Alarm Setpoint lower OK limit before a WARNING color/message, 9% is the default."
echo " "
echo "###### General Settings"
echo "# Output Formats"
echo 'powerTimeFormat="h"       # Format for power-on hours string, valid options are "ymdh", "ymd", "ym", "y", or "h" (year month day hour).'
echo 'tempdisplay="*C"          # The format you desire the temperature to be displayed in. Common formats are: "*C", "^C", or "^c". Choose your own.'
echo 'non_exist_value="---"     # How do you desire non existent data to be displayed.  The Default is "---", popular options are "N/A" or " ".'
echo " "
echo "# Ignore or Activate Alarms"
echo 'ignoreUDMA="false"        # Set to "true" to ignore all UltraDMA CRC Errors for the summary alarm (Email Header) only, errors will appear in the graphical chart.'
echo 'ignoreSeekError="true"    # Set to "true" to ignore all Seek Error Rate/Health errors.  Default is true.'
echo 'ignoreReadError="true"    # Set to "true" to ignore all Raw Read Error Rate/Health errors.  Default is true.'
echo 'ignoreMultiZone="false"   # Set to "true" to ignore all MultiZone Errors. Default is false.'
echo 'disableWarranty="true"    # Set to "true to disable email Subject line alerts for any expired warranty alert. The email body will still report the alert.'
echo " "
echo "# Disable or Activate Input/Output File Settings"
echo 'includeSSD="true"         # Set to "true" will engage SSD Automatic Detection and Reporting, false = Disable SSD Automatic Detection and Reporting.'
echo 'includeNVM="true"         # Set to "true" will engage NVM Automatic Detection and Reporting, false = Disable NVM Automatic Detection and Reporting.'
echo 'reportnonSMART="true"     # Will force even non-SMART devices to be reported, "true" = normal operation to report non-SMART devices.'
echo 'disableRAWdata="false"    # Set to "true" to remove the 'smartctl -a' data and non-smart data appended to the normal report.  Default is false.'
echo " "
echo "# Media Alarms"
echo "sectorsWarn=1             # Number of sectors per drive to allow with errors before WARNING color/message will be used, this value should be less than sectorsCrit."
echo "sectorsCrit=9             # Number of sectors per drive with errors before CRITICAL color/message will be used."
echo "reAllocWarn=0             # Number of Reallocated sector events allowed.  Over this amount is an alarm condition."
echo "multiZoneWarn=0           # Number of MultiZone Errors to allow before a Warning color/message will be used.  Default is 0."
echo "multiZoneCrit=5           # Number of MultiZone Errors to allow before a Warning color/message will be used.  Default is 5."
echo 'deviceRedFlag="true"      # Set to "true" to have the Device Column indicate RED for ANY alarm condition.  Default is true.'
echo 'heliumAlarm="true"        # Set to "true" to set for a critical alarm any He value below 100.  Default is true.'
echo 'heliumMin=100             # Set to 100 for a zero leak helium result.  An alert will occur below this value.'
echo "rawReadWarn=5             # Number of read errors to allow before WARNING color/message will be used, this value should be less than rawReadCrit."
echo "rawReadCrit=100           # Number of read errors to allow before CRITICAL color/message will be used."
echo "seekErrorsWarn=5          # Number of seek errors to allow before WARNING color/message will be used, this value should be less than seekErrorsCrit."
echo "seekErrorsCrit=100        # Number of seek errors to allow before CRITICAL color/message will be used."
echo " "
echo "# Time-Limited Error Recovery (TLER)"
echo 'SCT_Drive_Enable="false"  # Set to "true" to send a command to enable SCT on your drives for user defined timeout if the TLER state is Disabled.'
echo 'SCT_Warning="TLER_No_Msg" # Set to "all" will generate a Warning Message for all devices not reporting SCT enabled. "TLER" reports only drive which support TLER.'
echo '                          # "TLER_No_Msg" will only report for TLER drives and not report a Warning Message if the drive can set TLER on.'
echo "SCT_Read_Timeout=70       # Set to the read threshold. Default = 70 = 7.0 seconds."
echo "SCT_Write_Timeout=70      # Set to the write threshold. Default = 70 = 7.0 seconds."
echo " "
echo "# SMART Testing Alarm"
echo "testAgeWarn=2             # Maximum age (in days) of last SMART test before CRITICAL color/message will be used."
echo " "
echo "###### Statistical Data File"
echo 'statistical_data_file="'$Keyboard_statistics'"'
echo 'expDataEnable="true"      # Set to "true" will save all drive data into a CSV file defined by "statistical_data_file" below.'
echo 'expDataEmail="true"       # Set to "true" to have an attachment of the file emailed to you. Default is true.'
echo "expDataPurge=730          # Set to the number of day you wish to keep in the data.  Older data will be purged. Default is 730 days (2 years). 0=Disable."
echo 'expDataEmailSend="Mon"    # Set to the day of the week the statistical report is emailed.  (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)'
echo " "
echo "###### FreeNAS config backup settings"
echo 'configBackup="true"      # Set to "true" to save config backup (which renders next two options operational); "false" to keep disable config backups.'
echo 'configSendDay="Mon"      # Set to the day of the week the config is emailed.  (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)'
echo 'saveBackup="false"       # Set to "false" to delete FreeNAS config backup after mail is sent; "true" to keep it in dir below.'
echo 'backupLocation="/tmp/"   # Directory in which to store the backup FreeNAS config files.'
echo " "
echo "########## REPORT CHART CONFIGURATION ##############"
echo " "
echo "###### REPORT HEADER TITLE ######"
echo 'HDDreportTitle="Spinning Rust Summary Report"     # This is the title of the HDD report, change as you desire.'
echo 'SSDreportTitle="SSD Summary Report"               # This is the title of the SSD report, change as you desire.'
echo 'NVMreportTitle="NVMe Summary Report"              # This is the title of the NVMe report, change as you desire.'
echo " "
echo "### CUSTOM REPORT CONFIGURATION ###"
echo "# By default most items are selected. Change the item to "false" to have it not displayed in the graph, "true" to have it displayed."
echo "# NOTE: Alarm setpoints are not affected by these settings, this is only what columns of data are to be displayed on the graph."
echo "# I would recommend that you remove columns of data that you don't really care about to make the graph less busy."
echo " "
echo "# For Zpool Status Summary"
echo 'Zpool_Pool_Name_Title="Pool Name"'
echo 'Zpool_Status_Title="Status"'
echo 'Zpool_Pool_Size_Title="Pool Size"'
echo 'Zpool_Free_Space_Title="Free Space"'
echo 'Zpool_Used_Space_Title="Space Used"'
echo 'Zpool_Read_Errors_Title="Read Errors"'
echo 'Zpool_Write_Errors_Title="Write Errors"'
echo 'Zpool_Checksum_Errors_Title="Cksum Errors"'
echo 'Zpool_Scrub_Repaired_Title="Scrub Repaired Bytes"'
echo 'Zpool_Scrub_Errors_Title="Scrub Errors"'
echo 'Zpool_Scrub_Age_Title="Last Scrub Age"'
echo 'Zpool_Scrub_Duration_Title="Last Scrub Duration"'
echo " "
echo "# For Hard Drive Section"
echo 'HDD_Device_ID="true"'
echo 'HDD_Device_ID_Title="Device ID"'
echo 'HDD_Serial_Number="true"'
echo 'HDD_Serial_Number_Title="Serial Number"'
echo 'HDD_Model_Number="true"'
echo 'HDD_Model_Number_Title="Model Number"'
echo 'HDD_Capacity="true"'
echo 'HDD_Capacity_Title="HDD Capacity"'
echo 'HDD_Rotational_Rate="true"'
echo 'HDD_Rotational_Rate_Title="RPM"'
echo 'HDD_SMART_Status="true"'
echo 'HDD_SMART_Status_Title="SMART Status"'
echo 'HDD_Raw_Read_Error_Rate="true"'
echo 'HDD_Raw_Read_Error_Rate_Title="Read Error Rate"'
echo 'HDD_Drive_Temp="true"'
echo 'HDD_Drive_Temp_Title="Curr Temp"'
echo 'HDD_Drive_Temp_Min="true"'
echo 'HDD_Drive_Temp_Min_Title="Temp Min"'
echo 'HDD_Drive_Temp_Max="true"'
echo 'HDD_Drive_Temp_Max_Title="Temp Max"'
echo 'HDD_Power_On_Hours="true"'
echo 'HDD_Power_On_Hours_Title="Power On Time"'
echo 'HDD_Start_Stop_Count="true"'
echo 'HDD_Start_Stop_Count_Title="Start Stop Count"'
echo 'HDD_Load_Cycle="true"'
echo 'HDD_Load_Cycle_Title="Load Cycle Count"'
echo 'HDD_Spin_Retry="true"'
echo 'HDD_Spin_Retry_Title="Spin Retry Count"'
echo 'HDD_Reallocated_Sectors="true"'
echo 'HDD_Reallocated_Sectors_Title="Re-alloc Sects"'
echo 'HDD_Reallocated_Events="true"'
echo 'HDD_Reallocated_Events_Title="Re-alloc Evnt"'
echo 'HDD_Pending_Sectors="true"'
echo 'HDD_Pending_Sectors_Title="Curr Pend Sects"'
echo 'HDD_Offline_Uncorrectable="true"'
echo 'HDD_Offline_Uncorrectable_Title="Offl Unc Sects"'
echo 'HDD_UDMA_CRC_Errors="true"'
echo 'HDD_UDMA_CRC_Errors_Title="UDMA CRC Error"'
echo 'HDD_Seek_Error_Rate="true"'
echo 'HDD_Seek_Error_Rate_Title="Seek Error Rate"'
echo 'HDD_MultiZone_Errors="true"'
echo 'HDD_MultiZone_Errors_Title="Multi Zone Error"'
echo 'HDD_Helium_Level="true"'
echo 'HDD_Helium_Level_Title="He Level"'
echo 'HDD_Last_Test_Age="true"'
echo 'HDD_Last_Test_Age_Title="Last Test Age"'
echo 'HDD_Last_Test_Type="true"'
echo 'HDD_Last_Test_Type_Title="Last Test Type"'
echo " "
echo "# For Solid State Drive Section"
echo 'SSD_Device_ID="true"'
echo 'SSD_Device_ID_Title="Device ID"'
echo 'SSD_Serial_Number="true"'
echo 'SSD_Serial_Number_Title="Serial Number"'
echo 'SSD_Model_Number="true"'
echo 'SSD_Model_Number_Title="Model Number"'
echo 'SSD_Capacity="true"'
echo 'SSD_Capacity_Title="HDD Capacity"'
echo 'SSD_SMART_Status="true"'
echo 'SSD_SMART_Status_Title="SMART Status"'
echo 'SSD_Drive_Temp="true"'
echo 'SSD_Drive_Temp_Title="Curr Temp"'
echo 'SSD_Drive_Temp_Min="true"'
echo 'SSD_Drive_Temp_Min_Title="Temp Min"'
echo 'SSD_Drive_Temp_Max="true"'
echo 'SSD_Drive_Temp_Max_Title="Temp Max"'
echo 'SSD_Power_On_Hours="true"'
echo 'SSD_Power_On_Hours_Title="Power On Time"'
echo 'SSD_Wear_Level="true"'
echo 'SSD_Wear_Level_Title="Wear Level"'
echo 'SSD_Reallocated_Sectors="true"'
echo 'SSD_Reallocated_Sectors_Title="Re-alloc Sects"'
echo 'SSD_Reallocated_Events="true"'
echo 'SSD_Reallocated_Events_Title="Re-alloc Evnt"'
echo 'SSD_Pending_Sectors="true"'
echo 'SSD_Pending_Sectors_Title="Curr Pend Sects"'
echo 'SSD_Offline_Uncorrectable="true"'
echo 'SSD_Offline_Uncorrectable_Title="Offl Unc Sects"'
echo 'SSD_UDMA_CRC_Errors="true"'
echo 'SSD_UDMA_CRC_Errors_Title="UDMA CRC Error"'
echo 'SSD_Last_Test_Age="true"'
echo 'SSD_Last_Test_Age_Title="Last Test Age"'
echo 'SSD_Last_Test_Type="true"'
echo 'SSD_Last_Test_Type_Title="Last Test Type"'
echo " "
echo "# For NVMe Drive Section"
echo 'NVM_Device_ID="true"'
echo 'NVM_Device_ID_Title="Device ID"'
echo 'NVM_Serial_Number="true"'
echo 'NVM_Serial_Number_Title="Serial Number"'
echo 'NVM_Model_Number="true"'
echo 'NVM_Model_Number_Title="Model Number"'
echo 'NVM_Capacity="true"'
echo 'NVM_Capacity_Title="HDD Capacity"'
echo 'NVM_SMART_Status="true"'
echo 'NVM_SMART_Status_Title="SMART Status"'
echo 'NVM_Critical_Warning="true"'
echo 'NVM_Critical_Warning_Title="Critical Warning"'
echo 'NVM_Drive_Temp="true"'
echo 'NVM_Drive_Temp_Title="Curr Temp"'
echo 'NVM_Drive_Temp_Min="false"               # I have not found this on an NVMe drive yet, so set to false'
echo 'NVM_Drive_Temp_Min_Title="Temp Min"'
echo 'NVM_Drive_Temp_Max="false"               # I have not found this on an NVMe drive yet, so set to false'
echo 'NVM_Drive_Temp_Max_Title="Temp Max"'
echo 'NVM_Power_On_Hours="true"'
echo 'NVM_Power_On_Hours_Title="Power On Time"'
echo 'NVM_Wear_Level="true"'
echo 'NVM_Wear_Level_Title="Wear Level"'
echo " "
echo " "
echo "###### Drive Ignore List"
echo "# What does it do:"
echo "#  Use this to list any drives to ignore and remove from the report.  This is very useful for ignoring USB Flash Drives"
echo "#  or other drives for which good data is not able to be collected (non-standard)."
echo "#"
echo "# How to use it:"
echo "#  We are using a comma delimited file to identify the drive serial numbers.  You MUST use the exact and full serial"
echo "#  number smartctl reports, if there is no identical match then it will not match. Additionally you may list drives"
echo "#  from other systems and they will not have any effect on a system where the drive does not exist.  This is great"
echo "#  to have one configuration file that can be used on several systems."
echo "#"
echo '# Example: "VMWare,1JUMLBD,21HNSAFC21410E"'
echo " "
echo 'Ignore_Drives="none"'
echo " "
echo " "
echo "###### Drive UDMA_CRC_Error_Count List"
echo "# What does it do:"
echo "#  If you have a drive which has an UDMA count other than 0 (zero), this setting will offset the"
echo "#  value back to zero for the concerns of monitoring future increases of this specific error. Any match will"
echo "#  subtract the given value to report a 0 (zero) value and highlight it in yellow to denote it was overridden."
echo "#  The Warning Title will not be flagged if this is zero'd out in this manner."
echo "#  NOTE: UDMA_CRC_Errors are typically permanently stored in the drive and cannot be reset to zero even though"
echo "#        they are frequently caused by a data cable communications error."
echo "#"
echo "# How to use it:"
echo "#  List each drive by serial number and include the current UDMA_CRC_Error_Count value."
echo "#  The format is very specific and will not work if you "wing it", use the Live EXAMPLE."
echo "#"
echo "#  Set the FLAG in the FLAGS Section ignoreUDMA to "false" (the default setting)."
echo "#"
echo "# If the error count exceeds the limit minus the offset then a warning message will be generated."
echo "# On the Status Report the UDMA CRC Errors block will be YELLOW with a value of "0" for an overridden value."
echo "#   -- NOTE: We are using the colon : as the separator between the drive serial number and the value to change."
echo "#"
echo "# Format: variable="Drive_Serial_Number:Current_UDMA_Error_Count" and add a comma if you have more than one drive."
echo "#"
echo "# The below example shows drive WD-WMC4N2578099 has 1 UDMA_CRC_Error, drive S2X1J90CA48799 has 2 errors."
echo "#"
echo '# Live Example: "WD-WMC4N2578099:1,S2X1J90CA48799:2,P02618119268:1"'
echo " "
echo 'CRC_ERRORS=""'
echo " "
echo " "
echo "###### Multi_Zone_Errors List"
echo "# What does it do:"
echo "#   This identifies drives with Multi_Zone_Errors which may be irritating people."
echo "#   Multi_Zone_Errors "for some drives, not all drives" are pretty much meaningless."
echo "#"
echo "# How to use it:"
echo "#   Use same format as CRC_Errors (see above)."
echo " "
echo 'MULTI_Zone=""'
echo " "
echo " "
echo "#######  Reallocated Sectors Exceptions"
echo "# What does it do:"
echo "#  This will offset any Reallocated Sectors count by the value provided."
echo "#"
echo "#  I do not recommend using this feature as I'm a believer in if you have over 5 bad sectors, odds are the drive will get worse."
echo "#  I'd recommend replacing the drive before complete failure.  But that is your decision."
echo "#"
echo "#  Why is it even an option?"
echo "#  I use it for testing purposes only but you may want to use it."
echo "#"
echo "# How to use it:"
echo "#   Use same format as CRC_Errors (see above)."
echo " "
echo 'BAD_SECTORS=""'
echo " "
echo "####### Warranty Expiration Date"
echo "# What does it do:"
echo "# This section is used to add warranty expirations for designated drives and to create an alert when they expire."
echo "# The date format is YYYY-MM-DD."
echo "#"
echo "# Below is an example for the format using my own drives, which yes, are expired."
echo "# As previously stated above, drive serial numbers must be an exact match to what smartctl reports to function."
echo "#"
echo "# If the drive does not exist, for example my drives are not on your system, then nothing will happen."
echo "#"
echo "# How to use it:"
echo '#   Use the format ="Drive_Serial_Number:YYYY-MM-DD" and add a comma if you have more than one drive.'
echo " "
echo 'DRIVE_WARRANTY="K1JUMLBD:2020-09-30,K1JRSWLD:2020-09-30,K1JUMW4D:2020-09-30,K1GVD84B:2020-10-12"'
echo " "
echo "###### Global table of colors"
echo "# The colors selected you can change but you will need to look up the proper HEX code for a color."
echo " "
echo 'okColor="#c9ffcc"       # Hex code for color to use in SMART Status column if drives pass (default is light green, #c9ffcc).'
echo 'warnColor="#f765d0"     # Hex code for WARN color (default is purple, #f765d0).'
echo 'critColor="#ff0000"     # Hex code for CRITICAL color (default is red, #ff0000).'
echo 'altColor="#f4f4f4"      # Table background alternates row colors between white and this color (default is light gray, #f4f4f4).'
echo 'whtColor="#ffffff"      # Hex for White background.'
echo 'ovrdColor="#ffff66"     # Hex code for Override Yellow.'
echo 'blueColor="#87ceeb"     # Hex code for Sky Blue, used for the SCRUB In Progress background.'
echo 'yellowColor="#f1ffad"   # Hex code for pale yellow.'
) > "$Config_File_Name"

    echo " "
    sleep 2
    echo "Humm, kind of slow..."
    sleep 2
    echo " "
    echo "Do you have enough RAM? Looks like about 8KB.  Troubleshooting..."
    sleep 2
    echo " "
    echo "Holy Cow! I found the problem, the system was identified as a Tandy TRS-80 Model 1"
    echo "Adjusting for the 1.774 MHz clock rate..."
    sleep 2
    echo "Success!"
    echo " "
    echo "New clean configuration complete."
    echo " "
    echo "Path and Name if the configuration file: "$Config_File_Name
    echo " "
    echo " "
    echo "If you desire more customization, rerun the -config and select Advanced options."
    echo " "
    exit 0
    ;;


    U)
    clear
    echo "Updating Configuration File Routine"
    echo " "
    echo "Use this update utility when you have a newer version of the script."
    echo " "
    echo "This update utility will recreate a new configuration file with all your current settings"
    echo "and will add any new variables required to the configuration file."
    echo " "
    echo "If you modified manually any part of the configuration file other than the variables,"
    echo "that data will be overwritten."
    echo " "
    echo "Press Enter/Return to continue or any other key entry to abort."
    read -n 1 key
    if [[ ! $key == "" ]]; then echo "        Aborting"; exit 1; fi
    echo " "
    echo " "
    echo "Loading the current configuration file..."
    load_config
    echo " "
    echo " " 
    echo "Cross your fingers - Making Changes..."
    update_config_file
    echo " "
    sleep 2
    for (( p=1; p<=3; p++ ))
    do
    clear
    echo "3JHD*&NASLKJ86qm"
    echo "*()DJKAUIYV>NKABNKLJHSKDFJH"
    echo "kjd786qmndVHJjd"
    sleep .2
    clear
    echo "ERXR29SO6IA}{"
    echo "dHUbvdl%h228GhwSd"
    echo "&^*7djhsdaGHJKasdYhjgasd435G455"
    sleep .2
    clear
    echo "jhYFdkjhs76^$9HJg"
    echo "Jyasuidha**(yuGfs6754G5hjsd%$&^"
    echo "sDjh65saa120kjJKhIUOIvb"
    sleep .2
    clear
    echo "3JHD*&NASLKJ"
    echo "*()DJKAUIYV>NKABNKLJHSKDFJH"
    echo "kjd786qmndVHJjd"
    sleep .2
    done
    clear
    echo " "
    echo " "
    echo "What a trip!"
    echo " "
    echo "Configuration File updated, I told you to cross your fingers!  Next time you will listen to me."
    echo " "
    exit 1
    ;;


    X)
    echo " "
    echo " "
    echo "Exiting..."
    echo " "
    echo " "
    z=50
    exit 1
    ;;


    *)
    echo " "
    echo " "
    echo "DO YOU WANT TO PLAY A GAME?"
    echo " "
    echo " "
    sleep 2
    ;;
# End First Level
esac
done
shopt -u nocasematch

}

################# HELP INSTRUCTIONS #################

display_help () {

clear
echo $programver
echo "Quick Description Information"
echo " "
echo "The purpose of Multi-Report is to provide an easy to setup script which will generate a simple"
echo "email containing a summary chart of your media and it's health.  Directly after the chart is"
echo "Failure Information, then SMART data for each drive, assuming the drive has SMART data."
echo "This script currently runs on both Core (freebsd) and Scale (debian) versions."
echo " "
echo "The script has become quite complex over time and with added features comes a pain in the neck"
echo "in configuration.  With version 1.6c an external configuration file was created so the end user"
echo "does not need to re-enter all their data but rather just reuse the original configuration file."
echo " "
echo "If the external configuration file does not exist, the script will use the values hard coded"
echo "into the script (just like versions 1.6b and earlier), however there is now an email address"
echo "check to ensure you have changed the email address within the script."
echo " "
echo "In order to generate an external configuration file you must use the [-config] parameter when"
echo "running the script.  Five options will be available:"
echo " "
echo "    N)ew configuration file"
echo "    A)dvanced configuration"
echo "    U)pdate current configuration file (Future Feature)"
echo "    H)ow to use this configuration tool"
echo "    X) Exit. Make no changes and exit"
echo " "
echo "The file will be created in the directory the script is located in."
echo " "
echo -n "Press any key to continue"
read -n 1 key
clear
echo $programver
echo "Quick Description Information"
echo " "
echo "The intention of the U)pdate Config File option is to add new parameters into your current"
echo "configuration file without requiring the end user to perform a full reconfiguration to add"
echo "new user defined parameters. It should save a lot of time when it's implemented."
echo " "
echo "Default settings should be sufficient to test this script, then you can customize it."
echo " "
echo "Besides the emailed chart the script can also email you attachments for your FreeNAS/TrueNAS"
echo "configuration file and a Statistical Data file."
echo " "
echo "The statistical data file is a comma delimited collection of drive data that can be opened in"
echo "any spreadsheet program such as MS Excel.  This data could prove to be useful in diagnosing"
echo "and troubleshooting drive or system problems.  The statistical data file is stored in the"
echo "same folder as the script being run is located."
echo " "
echo -n "Press any key to continue"
read -n 1 key
clear
echo $programver
echo "How to Read the Email Output"
echo " "
echo "Normal operation of this script will produce an output email and it may or maynot have"
echo "attachments per your configuration.  The email will contain the following information:"
echo " "
echo "- Subject with Summary Result of 'All is Good', '*WARNING*', or '*CRITICAL ERROR*'"
echo "  The summary result is based on your settings of the warning and critical setings, where"
echo "  All is Good = No Alarm indications.  *WARNING* = A warning threshold has been crossed"
echo "  and it means you should investigate and take action.  *CRITICAL* = Something significant"
echo "  has occured and your data could be at risk, take immediate action."
echo " "
echo "- The verison of the script and the version of TrueNAS you are running."
echo "- The date and time the script was run."
echo "- Zpool Status Report Summary: (Pool Name, Status, Pool Size, Errors, and Scrub Info)"
echo "- HDD Summary Report Chart: (Drive ID, Serial Number, and other good to know facts)"
echo "- SSD Summary Report Chart: (Basically the same as the HDD report)"
echo "- NVMe Summary Report Chart: (Basically the same as the SSD report)"
echo "- Text Section:  The Text section contains the text version of most of the previously"
echo "  displayed data.  It will tell you"
echo "-- if using an external configuration file"
echo "-- if saving statistical information"
echo "-- if a drive warranty has expired"
echo "-- Zpool native report - in which the gptid's are listed '*followed by a listing of the drives"
echo "   that make up the pool and the drives are listed in the order the gptid numbers are listed.*'"
echo "-- Drive relevant SMART data followed by if TLER/SCT is enabled/disabled or available."
echo "-- NON-SMART data will be listed for drives that do not support SMART."
echo " "
echo "While all this data is nice to have, there is no substitute for having due dilligence in"
echo "examining your hardware and ensuring it is working correctly.  This means you may need to"
echo "examine your SMART data closer."
echo " "
echo -n "Press any key to continue"
read -n 1 key
clear
echo $programver
echo "Usage"
echo " "
echo "Running the file without any switches will collect statistical data and generate a report."
echo " "
echo "Switches:"
echo "  -h = This message."
echo "  -s = Record drive statistics only, do not generate a corresponding email."
echo "  -config = Generate a configuration file in the directory the script is run from."
echo "  -delete = Deletes the statistical data file if the file exists."
echo "  -dump [all] = Generates an email attachment for all drives. This will also suppress the config_backup"
echo "    file and statistics file from being attached to the email unless you use the [all] option, then the"
echo "    config_backup and statistics files will be appended."
echo "  HDD | SSD | NVM input_file = (TEST) Use the selected summary report type and process the input"
echo "    file as the 'smartctl -a /dev/drive' data. Very useful for the developer in helping modify the"
echo "    script to add unrecognized drives.  I'd like to stress that the test mode is not very useful"
echo "    to the end user.  This is a developer tool. I only document this in case someone else wants"
echo "    to help update this script."
echo " "
echo "Expected usage:"
echo "  This script was designed to be run from the CRON service, generally once a day in order"
echo "to produce an email output to notify the user of any problems or trends.  Since I like to"
echo "view trends the script was modified to collect statistical data, great to analyze trends."
echo " "
echo "  I personally setup a CRON job to run this script once a day at 2AM using no switches."
echo "This will get me a nice email snapshot once a day.  Then I also will setup a CRON job to"
echo "run the file with the -s switch will collect statistical data and not generate a report."
echo "I setup this CRON job to run once every hour at 5 minutes past the hour to avoid conflicts"
echo "with the 2AM CRON job.  This provides me data on how my system is operating."
echo "--If you sleep your drives then this option may not be desirable.--"
echo " "
echo -n "Press any key to continue"
read -n 1 key
clear
echo $programver
echo "Customizations and Features"
echo " "
echo "There are quite a few built in features in the external configuration file, these are a few:"
echo " "
echo "Custom Chart Titles: Change the name of any or all headers and column names."
echo "Selectable Columns: Display or remove as many or few columns of data as desired. This is great"
echo "     for removing a column which has no relevant data."
echo "Alarm Setpoints: Practically everything has an alarm setpoint, from pool capacity to Scrub Age,"
echo "     to temperature Warnings and Critical Warnings, and a plethora of options."
echo "TLER: You can monitor and even have TLER automatically set if required, for drives which support it."
echo "     The default is to not automatically set TLER on, I believe the user should make that decision."
echo "Statistical Data: Modify the location of your data, if you want it emailed and when to email,"
echo "     and we include an automatic purge to ensure the data file doesn't get too large (default 2 years)."
echo "UDMA CRC Error Corrections: Have you ever had a hard drive UDMA_CRC_Error? Well they often are"
echo "    caused by a poor/loose data cable but the error will be recorded forever in the drive"
echo "    electronics. This option lets you zero out the value in the script. This feature is usable for"
echo "    Bad Sectors and Multi Zone Errors as well."
echo "Ignore Drive: Every wished you could just ignore a USB Flash Drive or any drive just giving you"
echo "    problems? With this feature the drive will be completely ignored in the script."
echo "Warranty Expiring Warning: You can configure the configuration file to provide a warning message"
echo "    for a drive on a certain date.  This a great tool to keep track on when it might be time to"
echo "    consider buying some replacement drives."
echo "Custom Colors: Use the HEX color codes to change the color scheme of the background and alerting"
echo "    colors on the charts.  This is ONLY changable manually, you have to edit the config file."
echo " "
echo "It is very important that if you edit the configuration file or the script, you need to maintain"
echo "the proper formatting of the text or you will throw a wrench into things."
echo " "
echo -n "Press any key to continue"
read -n 1 key
clear
echo $programver
echo "HOW TO HANDLE ERRORS"
echo " "
echo "There is a special TEST Feature used to help the programmer diagnose problems reading SMART"
echo "data correctly. I would not recommend anyone use this feature unless you are able to fix"
echo "the script.  If you are able to modify the script then you will need a properly formatted"
echo "test file.  Use the -dump parameter to create the test files and have them emailed to you."
echo "This is important or the format of the file could be compromised."
echo "Next run the multi_report.sh file with the option of HDD or SSD or NVM, depending on the"
echo "type of drive the test file represents.  Lastly add the name of the testfile."
echo "Example: multi_report.sh NVM nvm.txt"
echo " "
echo "In this scenario if you have multiple NVM's only the test file will be displayed under NVMe."
echo "   NOTE: Any test file will be assigned as /dev/ada50 or /dev/nvme50."
echo " "
echo "If you have a drive that you feel isn't properly recognized by this script, produce the"
echo "text file of the drive as indicated above (it must be produced this way), and send me the"
echo "file.  I may also ask for more information based on the failure."
echo " "
echo "All drives are not supported because manufacturers do not stick to one standard, so I need the"
echo "data format of the drives you are having issues with in the format listed below."
echo "smartctl -a /dev/ada1 > ada1_a.txt AND smartctl -x /dev/ada1 > ada1_x.txt"
echo "or better yet, use the -dump parameter to obtain all the drive data"
echo "and let me know the issue you are having via PM on the TrueNAS forums."
echo " "
echo "Also, any other issues, just PM me and be descriptive on the failure.  I can't reproduce"
echo "it if I have no clue what you did to create it. Screen captures are always nice."
echo " "
echo "OTHER INFO"
echo "Normalized Seek Error Rate.  Some drives (Seagate) report normalized values for seek error rates."
echo "Values:  100 is invalid until after the first 1 million seeks then the normalization is updated."
echo " 90 = 1 errors in 1,000 million seeks, 80 = 1 error in 100 million seeks, 70= 1 error in 10 million seeks,"
echo " 60 = 1 error in 1 million seeks, 50 = 1 error in 100,000 seeks, 40 = 1 error in 10,000 seeks,"
echo " 30 = 1 error in 1,000 seeks, 20 = 1 error in 100 seeks, and 10 = 1 error in 10 seeks (very bad)."
echo " The higher the number, the better."
echo " "
echo "But I have tried to identify Seagate drives and report the actual errors where possible."
echo " "
echo -n "Press any key to Exit"
read -n 1 key
echo " "
}

######################  DUMP DRIVE DATA ###################
# This routine will dump the selected drive data into individual files for troubleshooting.
#
# Let's make this a user interactive feature
#
dump_drive_data () {
if [[ $Silence == "off" ]]; then echo "Running dump_drive_data routine. Attching the drive data..."$drive; fi

 (
  # Write MIME section header for file attachment (encoded with base64)
  echo "--${boundary}"
  echo "Content-Type: text/html"
  echo "Content-Transfer-Encoding: base64"
  echo "Content-Disposition: attachment; filename=drive_${drive}_a.txt"
  base64 "/tmp/drive_${drive}_a.txt"

  echo "--${boundary}"
  echo "Content-Type: text/html"
  echo "Content-Transfer-Encoding: base64"
  echo "Content-Disposition: attachment; filename=drive_${drive}_x.txt"
  base64 "/tmp/drive_${drive}_x.txt"
 # echo "--${boundary}"
 # echo "Content-Type: text/html"

 ) >> "$logfile"
}

### DEFINE FUNCTIONS END ###

#######################
#######################
###                 ###
###  PROGRAM START  ###
###                 ###
#######################
#######################

# The order in which these processed occur is unfortunately dependent.
# The -s switch will just collect statistical data.
# The HDD|SSD|NVM switch will allow a raw text file for smartctl -a, followed by the input filename.

echo $programver
smartdata=""

if ! [[ "$1" == "-config" || "$1" == "-h" || "$1" == "-delete" || "$1" == "HDD" || "$1" == "SSD" || "$1" == "NVM" || "$1" == "-s" || "$1" == "" || "$1" == "-dump" || "$1" == "-monitor" ]]; then
echo $1 "is not a valid option."
echo "Use -h for help."
echo " "
exit 1
fi

if [[ "$1" == "-config" ]]; then
generate_config_file
exit 0
fi

if [[ "$1" == "-h" ]]; then
display_help
exit 0
fi

# if -dump then interactive user selected dumping, if "all" then automatic dumping of everything.
# Use dump_all=1 during the runnig routine to gather all the drive data and dump to drive ID files.
# if -dump all is used, then include config and statristical attachments (dump_all=2).
# Dump the files into /tmp/ and then email them.

if [[ "$1" == "-dump" ]]; then
   if [[ "$2" == "all" ]]; then dump_all="2"; else dump_all="1"; fi
else
   dump_all="0"
fi

if [[ "$1" == "-delete" ]]; then
echo "Preparing to Delete Statistical Data File"
echo " "
read -p "Press Enter/Return to Continue or CTRL-C to Abort Script"
rm "$statistical_data_file"
echo " "
echo "File Obliterated !!!"
echo " "
exit 0
fi

if [[ "$1" == "-monitor" ]]; then
echo "Future Use: This function will loop the script continuously every 5 minutes to monitor only"
echo "for drive temperature or select critical alarms only.  Once an alarm condition occurs then"
echo "and email will be generated for the issue.  The statistical data file will only record data"
echo "when an Alarm condition exists.  No other email will be generated except for an alarm."
# Modify this script under a different name, change the TMP file names to 'monitor_file_name'
# Remove the fluff, we are only looking to monitor for current alarm conditions.
# If no alarm conditions occur, do nothing and sleep for 5 minutes.
#
# Another possibility is to add in a 5 minute loop that will last just short of 24 hours so it will exit before the next CRON job.
# But we may need to incorporate the -s option into this.  The trick, ensure the file isn't open already, maybe BASH can see if it's open.
# Use lsof command to see if the file is open.
fi


load_config

# Cleanup previous run files.
cleanup_files

if [[ "$dump_all" == "1" ]]; then configBackup="false"; expDataEmail="false"; fi
if [[ "$dump_all" == "2" ]]; then configBackup="true"; expDataEmail="true"; configSendDay="All"; expDataEmailSend="All"; fi

# Not certain I need this here, comment out on final production tests.
testfile=""

datestamp2=$(date -Idate)
datestamp=$(date +%Y/%m/%d)
# FreeBSD gets second resolution unfortunately
  if [[ $softver != "Linux" ]]; then
     timestamp=$(date +%T)
  else
# Linux gets millisecond resolution
  timestamp=$(date +"%T.%2N")
  fi

if [[ $(date +"%m-%d") == "04-01" ]]; then Fun=1; echo "Fun Day"; else Fun=0; fi

if [[ "$1" == "HDD" ]]; then
### Add a test routine if $2 is null, exit stating missing parameter and then spit out the HELP command
testfile="$2"
echo "HDD Test File"
fi

if [[ $Silence == "off" ]]; then echo "Collecting Drive Information"; fi
get_smartHDD_listings
testfile=""

if [[ "$1" == "SSD" ]]; then
testfile="$2"
echo "SSD Test File"
fi
get_smartSSD_listings
testfile=""

if [[ "$1" == "NVM" ]]; then
testfile="$2"
echo "NVM Test File="$testfile
fi
get_smartNVM_listings
testfile=""

get_smartOther_listings

email_preformat

config_backup


if [[ $Silence == "off" ]]; then echo "Generating Zpool Report"; fi
zpool_report

  if [[ $expDataEnable == "true" ]]; then
     if test -e "$statistical_data_file"; then
# Purge items over expDataPurge days
        if [[ $Silence == "off" ]]; then echo "Statistical Datafile Exists"; fi
        statistical_data_file_created=0
     else
# The file does not exist, create it.
       if [[ $Silence == "off" ]]; then echo "Statistical datafile does not exist, Creating statistical datafile"; fi

       printf "Date,Time,Device ID,Drive Type,Serial Number,SMART Status,Temp,Power On Hours,Wear Level,Start Stop Count,Load Cycle,Spin Retry,Reallocated Sectors,\
       Reallocated Sector Events,Pending Sectors,Offline Uncorrectable,UDMA CRC Errors,Seek Error Rate,Multi Zone Errors,Read Error Rate,Helium Level\n" > "$statistical_data_file"
# And set flag the file was created.
       statistical_data_file_created=1
     fi
  fi

# Generate SMART HDD Report
SER1=""
if [[ $Silence == "off" ]]; then echo "Generating Drive Report"; fi
generate_table "HDD"
if [[ "$1" == "HDD" ]]; then
  testfile="$2"
fi
for drive in $smartdrives; do
  clear_variables
get_drive_data
#  get_drive_data "$smartdrives" "HDD"
  crunch_numbers "HDD"
  write_table "HDD"
done
end_table "HDD"
testfile=""

# Generate SSD Report
SER1=""
if [[ $includeSSD == "true" ]]; then
# Test if any SSD's are available, if not then no report, if yes then generate SSD/NVM Report.
   if [[ $smartdrivesSSD != "" ]]; then
     generate_table "SSD"
       if [[ "$1" == "SSD" ]]; then
          testfile="$2"
       fi
     for drive in $smartdrivesSSD; do
       clear_variables
get_drive_data
#       get_drive_data "$smartdrivesSSD" "SSD"
       crunch_numbers "SSD"
       write_table "SSD"
     done
     end_table "SSD"
     testfile=""
   fi
fi

# Generate NVMe Report
SER1=""
if [[ $includeNVM == "true" ]]; then
   if [[ $smartdrivesNVM != "" ]]; then
     generate_table "NVM"
       if [[ "$1" == "NVM" ]]; then
          testfile="$2"
       fi
       for drive in $smartdrivesNVM; do
         clear_variables
get_drive_data
#         get_drive_data "$smartdrivesNVM" "NVM"
         crunch_numbers "NVM"
         write_table "NVM"
       done
       end_table "NVM"
       testfile=""
   fi
fi

       for drive in $nonsmartdrives; do
         clear_variables
# We still use $2 in this routine, change to $1
#         get_drive_data "$nonsmartdrives" "NON"
         get_drive_data "NON" 
       done

# This purge happens here directly after data collection.
# A zero (0) value = Disable Purging (Keep all data)
if [[ $expDataPurge != 0 ]]; then
purge_exportdata
fi
if [[ $Silence == "off" ]]; then echo "Creating Detailed Report"; fi
detailed_report $2

if [[ $reportnonSMART == "true" ]]; then
  if [[ $disableRAWdata != "true" ]]; then
    non_smart_report
  fi
fi

if [[ "$1" == "-s" ]]; then
  if [[ $Silence == "off" ]]; then echo "Statistical Data Collection Only - No Email"; fi
  else
  email_datafile
  remove_junk_report


  if [[ $Silence == "off" ]]; then echo "Sending Email"; fi
  create_email
fi

# All reporting files are left in the /tmp/ directory for troubleshooting and cleaned up when the script is initial run.
