Electronics

Home domotics

back

DIY - HOME DOMOTICS TUTORIAL

linux logo PART 2: Setting up an Apache webserver with dynamic content

Test a simpe webpage.

To test the Apache server, make a simple html-file and save it to the webservers root location ([SAMBA public folder]\usr\firmware\webpages) on the Raspberry Pi. The index.html:


<!DOCTYPE html>
<html>
<head>
<title> Domotics system </title>
</head >
<body>

<h1> Yes, the webpage works! </h1>
<p> Great! </p>

</body>
</html>

Test the webpage by navigating to the Raspberry Pi's IP address. The result should look as follows:


Browser window showing first webpage

Download "index.html"



Python firmware for publishing dynamic content on the webpage

The firmware described hereunder consists of different modules (files):

  • Main.py: This is the main thread of the firmware
  • > AllSharedVariables.py: Class containing instance variables which will be made public for other python modules and the webserver
  • > AllSharedConstants.py: Class containing instance variables (constants) which will be made public for other python modules
  • > SharedVariablePublisher.py: Publish all shared variables to XML-FILE at regular basis.


Main.py:

from AllSharedVariables import ASV
from AllSharedConstants import ASC
import threading
import time
import sys
import os
import random

if ASC.USE_DYN_VARS_PUBLISHER_MODULE:
    from DynVarPublisher import DynVarPublisher

#        _
#  |\/| |_| | |\|
#  |  | | | | | |
#
def Main():
    asv = ASV() # create an instance of All Shared Variables
    asc = ASC() # create an instance of All Shared Constants
    STOP_APPLICATION = []

    #       _   _  _          _      ___
    #  | | (_  |_ |_|  | |\| |_| | |  |
    #  |_|  _) |_ |\   | | | |   |_|  |
    #
    myUserInputThread = threading.Thread(target=input_thread, args=(STOP_APPLICATION, ))
    myUserInputThread.daemon = True                            # Daemonize thread
    myUserInputThread.start()   
    
    ModulePrintIntro = "MAIN APPLICATION MODULE - "

    printIntro(asc)

    #   _ ___  _   _   _      _   _         _  _      ___  _    ___
    #  (_  |  | | |_| |_     |_| (_ \  /   |  | | |\|  |  |_ \/  |
    #   _) |  |_| |\  |_     | |  _) \/    |_ |_| | |  |  |_ /\  |  o o o
    #
    NrOfSysArguments = len(sys.argv)
    for argumentnr in range(1,NrOfSysArguments):
        if sys.argv[argumentnr] == "save":
            asv.SaveASV(asc.SETTINGSFILE)
            print(ModulePrintIntro + "Saving sensor settings to file at startup...")

    #   _   _  _ ___  _   _   _      _   _         _  _      ___  _    ___
    #  |_| |_ (_  |  | | |_| |_     |_| (_ \  /   |  | | |\|  |  |_ \/  |
    #  |\  |_  _) |  |_| |\  |_     | |  _) \/    |_ |_| | |  |  |_ /\  |   o o o
    #
    #  All shared variables are reset to the last saved context
    print(ModulePrintIntro + "Loading sensor settings...")
    asv.LoadASV(asc.SETTINGSFILE)

    if asc.USE_DYN_VARS_PUBLISHER_MODULE:
        # Create Dynamic Variable Publishing Module object
        dynvarpublisher = DynVarPublisher(asv, asc, verbosity = 2)

    # --------------------------------------------------------------------------------
    # START THE SERVICES ...
    # --------------------------------------------------------------------------------
    if asc.USE_DYN_VARS_PUBLISHER_MODULE:
        # START Publishing Module service
        print(ModulePrintIntro + "Starting dynamic variable publishing service...")
        dynvarpublisher.startservice()  # This service will will make dynamic variable available to display on the webserver interface
        
    sys.stdout.flush()

    while True:
        #        _          ___     _   _  _   _
        #  |\/| |_| | |\|    | |_| |_| |_ |_| | \
        #  |  | | | | | |    | | | |\  |_ | | |_/
        #
        
        # Update some shared variables to display on a webpage...
        asv.TestVariableA = asv.TestVariableA + 1
        asv.TestVariableB = round(random.random() * 100, 1)

        time.sleep(asc.WAITTIME_MAIN)

        if STOP_APPLICATION:
            asv.AppHeartBeat = False;

        # --------------------------------------------------------------------------------
        # STOP THE SERVICES ...
        # --------------------------------------------------------------------------------
        if not asv.AppHeartBeat:

            if asc.USE_DYN_VARS_PUBLISHER_MODULE:
                dynvarpublisher.stopservice()
                
            break


def input_thread(STOP_APPLICATION):
    print("MAIN APPLICATION MODULE - " + "Listening to users input...")
    raw_input()
    STOP_APPLICATION.append(None)
    print("MAIN APPLICATION MODULE - " + "Stop application request detected...")

def printIntro(asc):
    print("\n\n")
    print("#############################################################################")
    print("                                             ")    
    print("    Home Domotics system")
    print("    Firmware: 03/2019")
    print("")
    if(asc.SYSTEM == "WINDOWS"):
        print(asc.PRINT_WINDOWS_LOGO)
    else:
        print(asc.PRINT_LINUX_LOGO)
    print("")
    print("#############################################################################")
    print("")
    print("    STARTING FIRMWARE...")
    print("")
    print("#############################################################################")
    print("\n\n")

    

if __name__ == '__main__':
    Main()

AllSharedVariables.py:

####################################################################################################
#
#   MODULE:         ALL SHARED VARIABLES 
#   AUTHOR(S):      Werner Vandermeiren
#   LATEST UPDATE:  12/03/2019
#
#   METHODS:
#   SaveASV()               serializes the ASV class and saves it to a file
#                           (to init the shared variables at startup)
#   LoadASV()               read the serialized file and set the ASV instance accordingly
#
####################################################################################################

import pickle
import sys
import platform
from AllSharedConstants import ASC

####################################################################################################
#  _          _       _   _   _  _         _   _     _   _      _  _
# |_| |  |   (_  |_| |_| |_) |_ | \  \  / |_| |_) | |_| |_) |  |_ (_
# | | |_ |_   _) | | | | |\  |_ |_/   \/  | | |\  | | | |_) |_ |_  _)
#
####################################################################################################
class ASV:

    # ALL variables are defined as instance variables  in order to be able to use pickle

    def __init__(self):
        
        self.TestVariableA = 0
        self.TestVariableB = 0
        
        # - Real time clock related --------------------------------------------------------------------
        self.Date = "00/00/0000"
        self.Time = "00:00:00"
        
    def SaveASV(self, file):
        with open(file, 'wb') as outputfile:
            pickle.dump(self, outputfile, pickle.HIGHEST_PROTOCOL)

    def LoadASV(self, file):
        try:
            print("---> ASV MODULE - loading sensor settings...")
            instance = pickle.load(open(file, 'rb'))
            self.__dict__.update(instance.__dict__)
            print("---> ASV MODULE - Done!")
        except:
            print("---> ASV MODULE - Error occured reading the settings-file")


    

AllSharedConstants.py:

####################################################################################################
#
#   MODULE:         ALL SHARED CONSTANTS
#   AUTHOR(S):      Werner Vandermeiren
#   LATEST UPDATE:  12/03/2019
#
####################################################################################################

import sys
import platform

####################################################################################################
#  _          _       _   _   _  _     _  _       _ ___  _      ___  _
# |_| |  |   (_  |_| |_| |_) |_ | \   |  | | |\| (_  |  |_| |\|  |  (_
# | | |_ |_   _) | | | | |\  |_ |_/   |_ |_| | |  _) |  | | | |  |   _)
#
####################################################################################################
class ASC:

    if platform.python_version()[0] == "3":
        PYTHON_VERSION = 3
    else:
        PYTHON_VERSION = 2

    if sys.platform == 'win32':
        SYSTEM = "WINDOWS"  
    else:
        SYSTEM = "LINUX"
   
    # LINUX SYSTEM
    XML_FILEPATH_DYNVAR = "/usr/firmware/webpages/dynvars.xml"
    SETTINGSFILE = "settings.dat"

    # WAIT TIME OF THREADS (sec):
    WAITTIME_MAIN = 0.5
    
    # other usefull constants
    ON = 1
    OFF = 0
    BUSY = 1
    IDLE = 0
    TRUE = 1
    FALSE = 0
    NO_ARG = 0          

    PRINT_LINUX_LOGO = "    |  | |\| | | \/" + "\n" + \
                       "    |_ | | | |_| /\   system detected..."
    
    PRINT_WINDOWS_LOGO = "                _   _        _   \n" \
                         "    |  | | |\| | \ | | |  | |_   \n"\
                         "    |/\| | | | |_/ |_| |/\|  _|   system detected..."
        


    PRINT_SEPARATOR_A = "---------------------------------------------------------------------------"
    PRINT_SEPARATOR_B = "==========================================================================="
    PRINT_SEPARATOR_C = "###########################################################################"