python/Elycin/pihole-stat-rainbow-hat/pihole_stat_rainbow_hat.py

pihole_stat_rainbow_hat.py
#!/usr/bin/env python3

# Import Modules
import time
import rainbowhat
import pihole
import sys
import configuration


# The main class of the project.
class PiholeStatRainbowHat:
    def __init__(self, server=None, password=None, update_frequency=10):
        self.__update_frequency = update_frequency
        self.__running = None
        self.__request_stop = False
        self.__pihole_interface = None

        # Check if initialized variables
        if server is not None and password is not None:
            self.set_server(server=server)
            self.set_password(password=password)

    # Set the server where the PiHole panel is.
    def set_server(self, server):
        if self.__running:
            print("Please stop the script before running.")
        else:
            try:
                self.__pihole_interface = pihole.PiHole(server)
                print("Instantiated new instance of Pi-hole API.")
            except:
                sys.stderr.print("There was a problem while attempting to connect to the specified Pi-hole server.")

    # Set the administration password for the PiHole Interface so this script can use it.
    def set_password(self, password):
        if self.__running:
            print("Please stop the script before running.")
        else:
            try:
                self.__pihole_interface.authenticate(password)
                print("Authentication succeeded.")
            except:
                sys.stderr.print("Invalid password while attempting to authenticate with Pi-hole API.")

    # Set the frequency in seconds of when the display should be updated.
    def set_update_frequency(self, frequency_in_seconds):
        # Run safety checks to make sure it's within valid ranges.
        if frequency_in_seconds  <  0:
            print("A invalid update interval of %d was given, it will be defaulted to 10 seconds.")
            frequency_in_seconds = 10
        elif frequency_in_seconds > 3600:
            print("Please specify an interval less than one hour, it will be defaulted to 3600 seconds.")
            frequency_in_seconds = 3600

        # Update the class variable
        self.__update_frequency = frequency_in_seconds

    # Get the frequency of how often the display should update in seconds - API
    def get_update_frequency(self):
        return self.__update_frequency

    # Calculates the value from the pihole interface.
    def get_percentage(self):
        # Get the latest data
        self.__pihole_interface.refresh()

        # Add to variables for easy access.
        total = self.__pihole_interface.queries.replace(",", "")
        blocked = self.__pihole_interface.blocked.replace(",", "")

        # Print to the console
        print("Update received!")
        print("Total Queries: " + total)
        print("Blocked: " + blocked)

        # Return
        return (int(blocked) / int(total)) * 100

    # Send a stop signal for the work loop.
    def stop(self):
        print("The script is preparing to safely shut down.")
        print("When the loop runs for the next time, this script will exit.")
        self.__request_stop = True

    # The method that does the work.
    def work(self):
        self.__running = True

        while not self.__request_stop:
            try:
                # Get the raw percentage
                raw_percentage = self.get_percentage()

                # Determine the number of decimals we should use.
                if int(raw_percentage)  <  10:
                    precision = 3
                else:
                    precision = 2

                # Format the percentage based on the precision
                formatted_percentage = round(raw_percentage, precision)

                # Update the rainbow hat
                rainbowhat.display.clear()
                rainbowhat.display.print_float(formatted_percentage)
                rainbowhat.display.show()

                # Print to the console.
                print("Rainbow HAT has been updated successfully: %s%% of DNS requests have been blocked."
                      % formatted_percentage)
                print()
            except:
                rainbowhat.display.clear()
                rainbowhat.display.print_str('ERR')
                rainbowhat.display.show()

            # Wait for the next run
            time.sleep(self.__update_frequency)

        # Update the running variable to mark that we have stopped.
        self.__running = False


# If the script is not invoked from another class, we're running it directly.
if __name__ == "__main__":

    # Please see the examples for multiple methods of utilizing this script.
    app = PiholeStatRainbowHat(
        server=configuration.server_ip,
        password=configuration.server_password,
        update_frequency=configuration.update_frequency
    )
    app.work()