Peer Review/Questions of RV Automation Script
Thank you for taking the time to view my post. Below is my first Python script I’ve wrote over the last day so pardon any oversights.
Goal: To run the script on a Raspberry Pi with four relay hats and each hat having four relays to empty and rinse out the tanks on my RV automatically based on parameters entered on a simple webpage. Using a script like this will allow me to save water… I have forgotten about the water being on and the gate open before causing unnecessary water usage. Getting a general review of the code for optimization and/recommendations.
Background: I travel in my RV for work and have recently started making some quality of life changes and fun tweaks to it. I replaced the manual cable gates on my RV with electronic gates after one of the cables started jamming up and, disgustingly, I discovered my black tank was leaking at the tank exit connection. Another plus is that I can stay inside in the winter when needing to rinse and empty the tanks. I currently have a remote control relay board I use to open and close the three tanks on my RV and a switch to kill the ground for the electronic gates. The reason for the switch is because I installed the manual switches that came with the gates as a "just in case", but the fuse blows when I use the switches with the remote relay board having power. I cannot figure out what I wired wrong. I am going to install aftermarket tank rinsers in all of the tanks with a manifold that has a NC water valve for each rinser and the factory installed black tank rinser for a total of four rinsing options (I probably won’t use the factory one much once the aftermarket one is install, but want the option). The white water will have a ball valve that is controlled by an electric motor.
Current roadblocks:
- I cannot figure out a good search term to find how to interface the script with a webpage. Almost all search results show how to write a webpage in python, but not how to pipe things into a python script from a webpage. Links to tutorials for solutions would be appreciated.
- How to write a full error catchall so the power is cut in case something goes wrong with the script or Pi. All of the water valves that fill tanks are going to be NC aka the water valves that could cause flooding.
- Two timers on the webpage. One for the total remaining time of the script and one for the current task.
- A graceful way to be able to activate the White Water valve during the flush and fill process for a set amount of time so I could wash my hands or other things that briefly require water. I prefer to keep the white water closed any time I am flushing the tanks, even though I use two hoses out of sanitary caution.
- If possible, a way to name each relay address as a parameter. This will cut back on a lot of the comments and make the code easier to read. Something like PosPow = (board0, relay1)?
- Same as 4, but for i2cbus.write_byte_data, an easy parameter to make the code cleaner.
- This is probably a bit out of scope for the post, but I might as well mention it. The switches that came with the gates have a blinking light to indicate they are open, I’d like to use that light pulse to put a status of open or closed on the webpage. If a pulse isn’t received within one second the gate is closed. This could also be used to replace the manual Gate Toggle Time parameter.
- Probably something else I forgot while writing this and will edit once I remember.
Products referenced above:
Electronic Tank Gate: https://www.amazon.com/gp/product/B003VAYMB4 I have 2x 3" and 1x 1.5". That’s why there is a variance in the Grey2 Gate Toggle Time.
Electric Ball Valve: https://www.amazon.com/gp/product/B06Y11B8VN
NC Valve: https://www.amazon.com/gp/product/B06XW8MSTX
Pi Relay Board: https://www.amazon.com/gp/product/B07Q2P9D7K
Current Remote Control Relay Board: https://www.amazon.com/gp/product/B01D5XWDYO
I believe I have blabbed on enough so here is the code. Thank you again for your time.
#https://wiki.52pi.com/index.php/DockerPi_4_Channel_Relay_SKU:_EP-0099 import time from smbus import SMBus import sys #BEGIN PARAMETERS----------------------------------------------------------------------- #I2C Reference i2cbus = SMBus(1) #I2C Write #i2cbuswrite = i2cbus.write_byte_data #White Water Close Time #Time to be Web Based WWC = 2 #White Water Open Time #Time to be Web Based WWO = 2 #White Water Override During Script # #Override to be Web Based. Using Water During Flushing Process Affects Overall Water Pressure and Will Prevent Proper Tank Filling and Flushing WWOVER = False #???? Wrap Whole Script in an Override #White Water Override During Script Time #Time to be Web Based WWOVERT = 2*60 #Black1 Rinse #T/F to be Web Based B1R = True #Black1 Close/Fill Time #Time to be Web Based B1CT = 13*60 #Black1 Open/Drain Time #Time to be Web Based B1OT = 5*60 #Black1 Gate Toggle Time #Time to be Web Based B1GTT = 10 #Black1 Gate Cycles #Cycles to be Web Based B1GC = 5 #Black1 Tank Stir Time #Time to be Web Based B1TST = 15 #Black1 Post Fill Tank #T/F to be Web Based B1PF = True #Black1 Post Fill Time #Time to be Web Based B1PFT = 2*60 #Grey1 Rinse G1R = False #Grey1 Close/Fill Time G1CT = 10*60 #Grey1 Open/Drain Time G1OT = 5*60 #Grey1 Gate Toggle Time G1GTT = 10 #Grey1 Gate Cycles G1GC = 5 #Grey1 Tank Stir Time G1TST = 15 #Grey1 Post Fill Tank G1PF = True #Grey1 Post Fill Time G1PFT = 2*60 #Grey2 Rinse G2R = False #Grey2 Close/Fill Time G2CT = 10*60 #Grey2 Open/Drain Time G2OT = 5*60 #Grey2 Gate Toggle Time G2GTT = 7 #Grey2 Gate Cycles G2GC = 5 #Grey2 Tank Stir Time G2TST = 15 #Grey2 Post Fill Tank G2PF = True #Grey2 Post Fill Time G2PFT = 2*60 #Relay Function ron = 0xFF roff = 0x00 #Relay Addresses relay1 = 0x01 relay2 = 0x02 relay3 = 0x03 relay4 = 0x04 relays = [relay1, relay2, relay3, relay4] #Relay Board Address board0 = 0x10 board1 = 0x11 board2 = 0x12 board3 = 0x13 boards = [board0, board1, board2, board3] #Positive Power (board0, relay1 #Negative Power (board0, relay2 #White Water Close (board0, relay3 #White Water Open (board0, relay4 #Black Gate Close (board1, relay1 #Black Gate Open (board1, relay2 #Black Gate Added Water Tank Fill (board1, relay3 #Black Gate Factory Water Tank Fill (board1, relay4 #Grey1 Gate Close (board2, relay1 #Grey1 Gate Open (board2, relay2 #Grey1 Gate Added Water Tank Fill (board2, relay3 # (board2, relay4 #Grey2 Gate Close (board3, relay1 #Grey2 Gate Open (board3, relay2 #Grey2 Gate Added Water Tank Fill (board3, relay3 # (board4, relay4 #END PARAMETERS----------------------------------------------------------------------- #BEGIN DEBUG RESET RELAYS BEFORE SCRIPT----------------------------------------------- #Loop to turn off all gates for x in boards: currentboard = x for y in relays: currentrelay = y i2cbus.write_byte_data(x, y, roff) time.sleep(.025) time.sleep(1) #END DEBUG RESET RELAYS BEFORE SCRIPT-------------------------------------------------- #Turn On Power #Positive Power On (board0, relay1 i2cbus.write_byte_data(board0, relay1, ron) #Negative Power On (board0, relay2 i2cbus.write_byte_data(board0, relay2, ron) time.sleep(.025) #White Water Close (board0, relay3 i2cbus.write_byte_data(board0, relay3, ron) time.sleep(WWC) i2cbus.write_byte_data(board0, relay3, roff) time.sleep(1) #Sync All Gates to Off #Close Black1 (board1, relay1 i2cbus.write_byte_data(board1, relay1, ron) time.sleep(B1GTT) i2cbus.write_byte_data(board1, relay1, roff) #Close Grey1 (board2, relay1 i2cbus.write_byte_data(board2, relay1, ron) time.sleep(G1GTT) i2cbus.write_byte_data(board2, relay1, roff) #Close Grey2 (board3, relay1 i2cbus.write_byte_data(board3, relay1, ron) time.sleep(G2GTT) i2cbus.write_byte_data(board3, relay1, roff) try: #Grey1 & Grey2 Will Be Added Under this Try After Black1 is Fully Configured. #Rinse Black1 (board1, relay1 & (board1, relay2 if B1R is True: #Turn On Factory Water Tank Fill i2cbus.write_byte_data(board1, relay4, ron) #Time to Stir Up Tank time.sleep(B1TST) #Black1 Open for Intial Drain i2cbus.write_byte_data(board1, relay2, ron) time.sleep(B1GTT) i2cbus.write_byte_data(board1, relay2, roff) #Black1 Drain time.sleep(B1OT) #Black1 Rinse Cycle for x in range(B1GC): #Black1 Close i2cbus.write_byte_data(board1, relay1, ron) time.sleep(B1GTT) i2cbus.write_byte_data(board1, relay1, roff) #Black1 Fill time.sleep(B1CT) #Black1 Open i2cbus.write_byte_data(board1, relay2, ron) time.sleep(B1GTT) i2cbus.write_byte_data(board1, relay2, roff) #Black1 Drain time.sleep(B1OT) #Black1 Close i2cbus.write_byte_data(board1, relay1, ron) time.sleep(B1GTT) i2cbus.write_byte_data(board1, relay1, roff) #Black1 Water Post Flush Fill if B1PF is True: time.sleep(B1PFT) #Turn Off Factory Water i2cbus.write_byte_data(board1, relay4, roff) except KeyboardInterrupt: print("Keyboard Quit the Loop") for x in boards: #Loop to turn off all gates currentboard = x for y in relays: currentrelay = y i2cbus.write_byte_data(x, y, roff) finally: #Loop to turn off all gates for x in boards: currentboard = x for y in relays: currentrelay = y i2cbus.write_byte_data(x, y, roff) #White Water Open (board0, relay4 i2cbus.write_byte_data(board0, relay3, ron) time.sleep(WWO) i2cbus.write_byte_data(board0, relay3, roff) #Turn Off Power #Positive Power Off (board0, relay1 i2cbus.write_byte_data(board0, relay1, roff) #Negative Power Off (board0, relay2 i2cbus.write_byte_data(board0, relay2, roff) sys.exit()