Skip to content

Commit

Permalink
Add waveshare relay plugin.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan-in-CA committed Dec 30, 2023
1 parent 973b898 commit 19b2121
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 0 deletions.
54 changes: 54 additions & 0 deletions waveshare_relay_board/waveshare_relay_board.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
$def with (m_vals)

$var title: $_(u'SIP - Relay Board Settings')
$var page: plugins
<script>
// Initialize behaviors
jQuery(document).ready(function(){

jQuery("#cSubmit").click(function() {
jQuery("#pluginForm").submit();
});
jQuery("button#cCancel").click(function(){
window.location="/";
});
});
</script>

<div id="plugin">
<div class="title">$_(u'Waveshare Relay Board Settings')
</div>
<p>$_(u'A plugin for using Waveshare RPi Relay Board (B) to control sprinkler valves. See ')
<a href="https://www.waveshare.com/wiki/RPi_Relay_Board_(B)">RPi Relay Board (B)</a>
</p>
<p>$_(u'This plugin is a copy of the relay board plugin, modified to use the pi pins utilised in the Waveshare RPi Relay Board (B)')</p>
<br>
<form id="pluginForm" action="/rbu" method="get">
<div class='option' title='Number of relays in use (Waveshare relay board (B) has a total of 8 relays)'><span class='label'>$_(u'Relay channels'):</span>
<select name="relays">
<option value="1" ${" selected" if m_vals[u"relays"]==1 else ""}>1</option>
<option value="2" ${" selected" if m_vals[u"relays"]==2 else ""}>2</option>
<option value="3" ${" selected" if m_vals[u"relays"]==3 else ""}>3</option>
<option value="4" ${" selected" if m_vals[u"relays"]==4 else ""}>4</option>
<option value="5" ${" selected" if m_vals[u"relays"]==5 else ""}>5</option>
<option value="6" ${" selected" if m_vals[u"relays"]==6 else ""}>6</option>
<option value="7" ${" selected" if m_vals[u"relays"]==7 else ""}>7</option>
<option value="8" ${" selected" if m_vals[u"relays"]==8 else ""}>8</option>
</select>
<span class='tooltip'>$_(u'Number of relays in use (Waveshare relay board (B) has a total of 8 relays)')</span>
</div>
<div class='option' title='Active low means the relay turns on when the input is low and turns off when the input is high. Active high does the opposite.'><span class='label'>$_(u'Active'):</span>
<input type="radio" name="active" value="low" ${" checked" if m_vals[u"active"]==u"low" else u""}>$_('Low')
<input type="radio" name="active" value="high" ${" checked" if m_vals[u"active"]==u"high" else u""}>$_('High')
<span class='tooltip'>$_('Active low means the relay turns on when the input is low and turns off when the input is high. Active high does the opposite.')</span>
</div>
<br>
<p><b>$_(u'IMPORTANT'):</b> $_(u'If') <b>$_(u'Active')</b> $_(u'is changed'), <b>$_(u'Relay channels')</b> $_(u'will be set to') <b>1</b> $_(u'to prevent all the relays being switched on, and possibly damaging the power supply.')
$_(u'After verifying that the first relay is off, return to this page and set') <b>$_(u'Relay channels')</b> $_(u'to the correct number.')
</p>
</form>
</div>
<div class="controls">
<button id="cSubmit" class="submit"><b>$_(u'Submit')</b></button>
<button id="cCancel" class="cancel danger">$_(u'Cancel')</button>
</div>
14 changes: 14 additions & 0 deletions waveshare_relay_board/waveshare_relay_board.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Description: Allows the SIP program to use the Waveshare RPI Relay Board (B) (https://www.waveshare.com/wiki/RPi_Relay_Board_(B)) to control sprinkler valves etc. This plugin is an exact copy of plugin relay_board excpet for the pinout which is adjusted to the pins used for controlling the relays in Waveshare RPI Relay Board (B).
Copyright 2023
Author: Antonios Hatzikonstantinou
Email: ahatzikonstantinou@protonmail.com
License: GNU GPL 3.0

Requirements:

##### List all plugin files below preceded by a blank line [file_name.ext path] relative to SIP directory #####

waveshare_relay_board.py plugins
waveshare_relay_board.html templates
waveshare_relay_board.json data (generated)
waveshare_relay_board.manifest plugins/manifests
227 changes: 227 additions & 0 deletions waveshare_relay_board/waveshare_relay_board.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
#!/usr/bin/env python

# Python 2/3 compatibility imports
from __future__ import print_function
from six.moves import range

# standard library imports
import json
import time

# local module imports
from blinker import signal
import gv # Get access to SIP's settings, gv = global variables
from sip import template_render
from urls import urls # Get access to SIP's URLs
import web
from webpages import ProtectedPage

gv.use_gpio_pins = False # Signal SIP to not use GPIO pins

# Load the Raspberry Pi GPIO (General Purpose Input Output) library
try:
if gv.use_pigpio:
import pigpio
pi = pigpio.pi()
else:
import RPi.GPIO as GPIO
pi = 0
except IOError:
pass

# Add a new url to open the data entry page.
# fmt: off
urls.extend(
[
u"/wrb", u"plugins.waveshare_relay_board.settings",
u"/wrbj", u"plugins.waveshare_relay_board.settings_json",
u"/wrbu", u"plugins.waveshare_relay_board.update",
]
)
# fmt: on

# Add this plugin to the home page plugins menu
gv.plugin_menu.append([_(u"Waveshare Relay Board"), u"/wrb"])

params = {}

# Read in the parameters for this plugin from it's JSON file
def load_params():
global params
try:
with open(u"./data/waveshare_relay_board.json", u"r") as f: # Read the settings from file
params = json.load(f)
except IOError: # If file does not exist create file with defaults.
params = {u"relays": 8, u"active": u"low"}
with open(u"./data/waveshare_relay_board.json", u"w") as f:
json.dump(params, f, indent=4, sort_keys=True)
return params


load_params()

#### define the GPIO pins that will be used ####
try:
if gv.platform == u"pi": # If this will run on Raspberry Pi:
if not gv.use_pigpio:
GPIO.setmode(
GPIO.BOARD
) # IO channels are identified by header connector pin numbers. Pin numbers are
relay_pins = [
29,
31,
33,
36,
35,
38,
40,
37,
3,
5,
24,
26,
11,
12,
13,
15,
16,
18,
22,
7,
]
for i in range(len(relay_pins)):
try:
relay_pins[i] = gv.pin_map[relay_pins[i]]
except:
relay_pins[i] = 0
pin_rain_sense = gv.pin_map[8]
pin_relay = gv.pin_map[10]
else:
print(u"relay board plugin only supported on pi.")
except:
print(u"Relay board: GPIO pins not set")
pass


#### setup GPIO pins as output and either high or low ####
def init_pins():
global pi

try:
for i in range(params[u"relays"]):
if gv.use_pigpio:
pi.set_mode(relay_pins[i], pigpio.OUTPUT)
else:
GPIO.setup(relay_pins[i], GPIO.OUT)
if params[u"active"] == u"low":
if gv.use_pigpio:
pi.write(relay_pins[i], 1)
else:
GPIO.output(relay_pins[i], GPIO.HIGH)
else:
if gv.use_pigpio:
pi.write(relay_pins[i], 0)
else:
GPIO.output(relay_pins[i], GPIO.LOW)
time.sleep(0.1)
except:
pass


#### change outputs when blinker signal received ####
def on_zone_change(arg): # arg is just a necessary placeholder.
""" Switch relays when core program signals a change in zone state."""

global pi

with gv.output_srvals_lock:
for i in range(params[u"relays"]):
try:
if gv.output_srvals[i]: # if station is set to on
if (
params[u"active"] == u"low"
): # if the relay type is active low, set the output low
if gv.use_pigpio:
pi.write(relay_pins[i], 0)
else:
GPIO.output(relay_pins[i], GPIO.LOW)
else: # otherwise set it high
if gv.use_pigpio:
pi.write(relay_pins[i], 1)
else:
GPIO.output(relay_pins[i], GPIO.HIGH)
else: # station is set to off
if (
params[u"active"] == u"low"
): # if the relay type is active low, set the output high
if gv.use_pigpio:
pi.write(relay_pins[i], 1)
else:
GPIO.output(relay_pins[i], GPIO.HIGH)
else: # otherwise set it low
if gv.use_pigpio:
pi.write(relay_pins[i], 0)
else:
GPIO.output(relay_pins[i], GPIO.LOW)
# print 'relay switched off', i + 1, "pin", relay_pins[i] # for testing ############
except Exception as e:
print(u"Problem switching relays", e, relay_pins[i])
pass


init_pins()

zones = signal(u"zone_change")
zones.connect(on_zone_change)

################################################################################
# Web pages: #
################################################################################


class settings(ProtectedPage):
"""Load an html page for entering relay board adjustments"""

def GET(self):
with open(u"./data/waveshare_relay_board.json", u"r") as f: # Read the settings from file
params = json.load(f)
return template_render.relay_board(params)


class settings_json(ProtectedPage):
"""Returns plugin settings in JSON format"""

def GET(self):
web.header(u"Access-Control-Allow-Origin", u"*")
web.header(u"Content-Type", u"application/json")
return json.dumps(params)


class update(ProtectedPage):
"""Save user input to waveshare_relay_board.json file"""

def GET(self):
qdict = web.input()
changed = False
if params[u"relays"] != int(
qdict[u"relays"]
): # if the number of relay channels changed, update the params
params[u"relays"] = int(qdict[u"relays"])
changed = True
if params[u"active"] != str(
qdict[u"active"]
): # if active low/high changed, update the params
params[u"active"] = str(qdict[u"active"])
params[
u"relays"
] = (
1
) # since changing active could turn all the relays on, reduce the relay channels to 1
changed = True
if changed:
init_pins()
with open(
u"./data/waveshare_relay_board.json", u"w"
) as f: # write the settings to file
json.dump(params, f, indent=4, sort_keys=True)
raise web.seeother(u"/")

0 comments on commit 19b2121

Please sign in to comment.