I ported my Somfy sketch to Python with the help of the very good pigpio library, so that my Raspberry Pi can open the blinds in the morning and close them after sunset.
Everything works and I'm happy with it.
To add a bit of interactivity, I would like to be able to control the blinds via a webpage served by the Raspberry Pi. This would mean launching a Python script when a button is pressed on the webpage.
There would be n blinds, so 3*n buttons ({UP, STOP, DOWN} for every blind) on the page. They could either trigger the same script with two arguments (the blind and the command) or trigger a different script for each button (I don't mind).
But I've never set up a webserver. I barely know any HTML and I've never used a CGI, nor do I precisely understand what it is.
So, my questions are:
- What's the simplest (will have to deliver one page and trigger scripts) webserver I can use?
- What HTML code to use?
- The most important: how a click on a button/link will start a script (possibly passing two arguments)?
- How to make sure this will only work locally (checking the IP of the host, or downloading a certificate on my smartphone, the easiest route)?
The script is in the somfy directory. The same goes for the text files keeping track of the rolling code and remote address. Maybe the page could be placed there as well? If you really feel like you need the code, I'm giving it to you but I'm not sure it's necessary:
def envoi_commande(telco, bouton):
checksum = 0
with open("somfy/" + telco + ".txt", 'r') as file:
data = file.readlines()
teleco = int(data[0], 16)
code = int(data[1])
data[1] = str(code + 1)
print hex(teleco)
print code
with open("somfy/" + telco + ".txt", 'w') as file:
file.writelines(data)
pi = pigpio.pi() # connect to Pi
if not pi.connected:
exit()
pi.wave_add_new()
pi.set_mode(TXGPIO, pigpio.OUTPUT)
print "Remote : " + "0x%0.2X" % teleco
print "Button : " + "0x%0.2X" % bouton
print "Rolling code : " + str(code)
print ""
frame[0] = 0xA7; # Encryption key. Doesn't matter much
frame[1] = bouton << 4 # Which button did you press? The 4 LSB will be the checksum
frame[2] = code >> 8 # Rolling code (big endian)
frame[3] = (code & 0xFF) # Rolling code
frame[4] = teleco >> 16 # Remote address
frame[5] = ((teleco >> 8) & 0xFF) # Remote address
frame[6] = (teleco & 0xFF) # Remote address
print "Frame : ",
for octet in frame:
print "0x%0.2X" % octet,
print ""
for i in range(0, 7):
checksum = checksum ^ frame[i] ^ (frame[i] >> 4)
checksum &= 0b1111; # We keep the last 4 bits only
frame[1] |= checksum;
print "With cks : ",
for octet in frame:
print "0x%0.2X" % octet,
print ""
for i in range(1, 7):
frame[i] ^= frame[i-1];
print "Obfuscated :",
for octet in frame:
print "0x%0.2X" % octet,
print ""
wf=[]
wf.append(pigpio.pulse(1<<TXGPIO, 0, 9415))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 89565))
for i in range(2):
wf.append(pigpio.pulse(1<<TXGPIO, 0, 2560))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 2560))
wf.append(pigpio.pulse(1<<TXGPIO, 0, 4550))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
for i in range (0, 56):
if ((frame[i/8] >> (7 - (i%8))) & 1):
wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
else:
wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 30415))
#2 (I repeat the frame)
for i in range(7):
wf.append(pigpio.pulse(1<<TXGPIO, 0, 2560))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 2560))
wf.append(pigpio.pulse(1<<TXGPIO, 0, 4550))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
for i in range (0, 56):
if ((frame[i/8] >> (7 - (i%8))) & 1):
wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
else:
wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
wf.append(pigpio.pulse(0, 1<<TXGPIO, 30415))
pi.wave_add_generic(wf)
wid = pi.wave_create()
pi.wave_send_once(wid)
while pi.wave_tx_busy():
pass
pi.wave_delete(wid)
pi.stop()