Compare commits

...

4 Commits

11 changed files with 159 additions and 68 deletions

1
.rsync-filter Normal file
View File

@ -0,0 +1 @@
- custom

View File

@ -4,3 +4,8 @@ Building and deployment
$ cd arduino && pio run && cd .. $ cd arduino && pio run && cd ..
$ cd raspi/mgmt && ansible-playbook playbook.yml && ansible-playbook $ cd raspi/mgmt && ansible-playbook playbook.yml && ansible-playbook
arduino.yml arduino.yml
Customization
=============
`raspi/mgmt/custom/{{ IP }}` is overlaid over default raspi/ code

View File

@ -331,8 +331,8 @@ void pin_mazeISR() {
void openDrawer(){ void openDrawer(){
log("The drawer is open."); log("The drawer is open.");
digitalWrite(pin_drawer_relay, HIGH); digitalWrite(pin_drawer_relay, HIGH);
delay(DRAWER_OPEN_DELAY); // delay(DRAWER_OPEN_DELAY);
digitalWrite(pin_drawer_relay, LOW); // digitalWrite(pin_drawer_relay, LOW);
} }
void checkPassword(){ void checkPassword(){
@ -417,7 +417,7 @@ void setupPins(){
digitalWrite(pin_rpi_pos, HIGH); digitalWrite(pin_rpi_pos, HIGH);
//inicjalizacja przerwan PCINT idacych od RPi //inicjalizacja przerwan PCINT idacych od RPi
pinMode(pin_rpi_win4, INPUT); //nie moze byc pullup, bo podciagalby do 5V - te piny trzyma w stanie wysokim RPi pinMode(pin_rpi_win4, INPUT); //nie moze byc pullup, bo podciagalby do 5V - te piny trzyma w stanie wysokim RPi
enableInterrupt(pin_rpi_win4, win4ISR, CHANGE); enableInterrupt(pin_rpi_win4, win4ISR, CHANGE);
pinMode(pin_rpi_win9, INPUT); pinMode(pin_rpi_win9, INPUT);
enableInterrupt(pin_rpi_win9, win9ISR, CHANGE); enableInterrupt(pin_rpi_win9, win9ISR, CHANGE);

11
raspi/gameplayconfig.py Normal file
View File

@ -0,0 +1,11 @@
#gameplay
#wynik w snake, ktory wygrywa
SNAKE_SCORE = 2
#predkosc gry w snake - w zakresie od 1 do 10
TICK_SNAKE = 10
#ilosc segmentow dodanych do snake po zlapaniu jablka
SNAKE_ADDSIZE = 10
#hasla klawiatury ekranowej dla obu zagadek
PASSWORD1 = 'one'
PASSWORD2 = 'two'

View File

@ -1,5 +1,11 @@
[raspi] [raspi-wifi]
192.168.43.12 192.168.43.12
192.168.43.44 192.168.43.44
192.168.43.219 192.168.43.219
192.168.43.231 192.168.43.231
[raspi]
10.21.37.150
10.21.37.180
10.21.37.185
10.21.37.226

View File

@ -3,8 +3,12 @@
become_user: root become_user: root
tasks: tasks:
- synchronize: src=../.. dest=/home/pi/sejf - synchronize: src=../.. dest=/home/pi/sejf
- file: path=/etc/xdg/autostart/pprompt.desktop state=absent - synchronize: src="custom/{{ inventory_hostname }}" dest=/home/pi/sejf/raspi
ignore_errors: yes
- copy: src=sejf.service dest=/etc/systemd/system/sejf.service
- systemd: name=sejf state=restarted enabled=yes
- copy: src=autostart dest=/home/pi/.config/lxsession/LXDE-pi/autostart - copy: src=autostart dest=/home/pi/.config/lxsession/LXDE-pi/autostart
- copy: src=sejf.desktop dest=/etc/xdg/autostart
- apt: name=python-flask state=present - apt: name=python-flask state=present
- apt: name=avrdude state=present - apt: name=avrdude state=present
- file: path=/etc/xdg/autostart/pprompt.desktop state=absent
- file: path=/etc/xdg/autostart/sejf.desktop state=absent

View File

@ -1,7 +0,0 @@
[Desktop Entry]
Type=Application
Name=sejf
NoDisplay=true
Exec=python /home/pi/sejf/raspi/pySejf.py
Terminal=true
NotShowIn=GNOME;KDE;XFCE;

13
raspi/mgmt/sejf.service Executable file
View File

@ -0,0 +1,13 @@
[Unit]
Description=sejf
After=lightdm.service
[Service]
ExecStart=/usr/bin/python -u /home/pi/sejf/raspi/pySejf.py
Restart=always
Environment=DISPLAY=:0
User=pi
KillSignal=SIGKILL
[Install]
WantedBy=default.target

View File

@ -9,6 +9,7 @@ import threading
import logging import logging
import socket import socket
import json import json
import string
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
import random, pygame import random, pygame
@ -45,9 +46,10 @@ class ImageSlide(Slide):
class FinalSlide(ImageSlide): class FinalSlide(ImageSlide):
def exit(self, next_slide): def exit(self, next_slide):
return False # Allow change to exit slide
return isinstance(next_slide, FinalSlide)
class FinalEverythingSlide(ImageSlide): class FinalEverythingSlide(FinalSlide):
def enter(self, prev_slide): def enter(self, prev_slide):
global wall_a global wall_a
if(wall_a): if(wall_a):
@ -58,9 +60,6 @@ class FinalEverythingSlide(ImageSlide):
return True return True
def exit(self, next_slide):
return False
class SnakeSlide(Slide): class SnakeSlide(Slide):
def enter(self, prev_slide=None): def enter(self, prev_slide=None):
self.xs = [290, 290, 290, 290, 290]; self.xs = [290, 290, 290, 290, 290];
@ -74,30 +73,61 @@ class SnakeSlide(Slide):
#img.fill((255, 0, 0)) #img.fill((255, 0, 0))
self.f = FONT_SNAKE self.f = FONT_SNAKE
self.clock = pygame.time.Clock() self.clock = pygame.time.Clock()
self.finished = False
return True return True
def finish(self):
self.finished = True
self.finish_time = time.time()
def handle(self, e): def handle(self, e):
print(e) print(e)
if e.type == KEYDOWN: if e.type == KEYDOWN:
if e.key == K_UP and self.dirs != 0:self.dirs = 2 if e.key == K_UP and self.dirs != 0: self.dirs = 2
elif e.key == K_DOWN and self.dirs != 2:self.dirs = 0 elif e.key == K_DOWN and self.dirs != 2: self.dirs = 0
elif e.key == K_LEFT and self.dirs != 1:self.dirs = 3 elif e.key == K_LEFT and self.dirs != 1: self.dirs = 3
elif e.key == K_RIGHT and self.dirs != 3:self.dirs = 1 elif e.key == K_RIGHT and self.dirs != 3: self.dirs = 1
if self.finished and time.time() - self.finish_time > 3:
self.enter()
print(self.dirs) print(self.dirs)
def render(self, screen): def render(self, screen):
self.clock.tick(TICK_SNAKE) self.clock.tick(TICK_SNAKE)
if not self.finished:
self.interact()
#rysuj tlo
screen.fill(WHITE)
screen.blit(IMG_SNAKE, (0, 0))
for i in range(0, len(self.xs)):
screen.blit(self.img, (self.xs[i], self.ys[i]))
screen.blit(self.appleimage, self.applepos);
t=self.f.render(str(self.score), True, (0, 0, 0));
screen.blit(t, (10, 10));
if self.finished:
f=FONT_SNAKE
t=f.render(MSG_SNAKE+str(self.score), True, (0, 0, 0))
screen.blit(t, (10, 270))
return
def interact(self):
# snek collision
i = len(self.xs)-1 i = len(self.xs)-1
while i >= 2: while i >= 2:
if collide(self.xs[0], self.xs[i], self.ys[0], self.ys[i], 20, 20, 20, 20): if collide(self.xs[0], self.xs[i], self.ys[0], self.ys[i], 20, 20, 20, 20):
die(screen, self.score) self.finish()
self.score = 0 return
self.enter()
i-= 1 i-= 1
# Apple collision
if collide(self.xs[0], self.applepos[0], self.ys[0], self.applepos[1], 20, 10, 20, 10): if collide(self.xs[0], self.applepos[0], self.ys[0], self.applepos[1], 20, 10, 20, 10):
self.score+=1 self.score+=1
for i in range(0, SNAKE_ADDSIZE): for i in range(0, SNAKE_ADDSIZE):
@ -106,9 +136,8 @@ class SnakeSlide(Slide):
self.applepos=(random.randint(0,WINSIZEX),random.randint(0,WINSIZEY)) self.applepos=(random.randint(0,WINSIZEX),random.randint(0,WINSIZEY))
if self.xs[0] < 0 or self.xs[0] > WINSIZEX or self.ys[0] < 0 or self.ys[0] > WINSIZEY: if self.xs[0] < 0 or self.xs[0] > WINSIZEX or self.ys[0] < 0 or self.ys[0] > WINSIZEY:
die(screen, self.score) self.finish()
score = 0 return
self.enter()
self.xs[1:] = self.xs[:-1] self.xs[1:] = self.xs[:-1]
self.ys[1:] = self.ys[:-1] self.ys[1:] = self.ys[:-1]
@ -118,35 +147,16 @@ class SnakeSlide(Slide):
elif self.dirs==2:self.ys[0] -= 20 elif self.dirs==2:self.ys[0] -= 20
elif self.dirs==3:self.xs[0] -= 20 elif self.dirs==3:self.xs[0] -= 20
#rysuj tlo
screen.fill(WHITE)
screen.blit(IMG_SNAKE, (0, 0))
print("drawing snake...") print("drawing snake...")
if(self.score > SNAKE_SCORE): if(self.score > SNAKE_SCORE):
die(screen, self.score) signalWin(4)
self.enter() self.finish()
return
for i in range(0, len(self.xs)):
screen.blit(self.img, (self.xs[i], self.ys[i]))
screen.blit(self.appleimage, self.applepos);
t=self.f.render(str(self.score), True, (0, 0, 0));
screen.blit(t, (10, 10));
pygame.init() pygame.init()
pygame.mixer.init() pygame.mixer.init()
#gameplay from gameplayconfig import *
#wynik w snake, ktory wygrywa
SNAKE_SCORE = 2
#predkosc gry w snake - w zakresie od 1 do 10
TICK_SNAKE = 10
#ilosc segmentow dodanych do snake po zlapaniu jablka
SNAKE_ADDSIZE = 10
#hasla klawiatury ekranowej dla obu zagadek
password1 = 'one'
password2 = 'two'
#ilosc powtorzen mp3 #ilosc powtorzen mp3
MP3_LOOPS = 4 MP3_LOOPS = 4
@ -230,13 +240,15 @@ else:
print "this RPi is." print "this RPi is."
GPIO.setup(PIN_SUC4, GPIO.OUT) GPIO.setup(PIN_SUC4, GPIO.OUT)
GPIO.output(PIN_SUC4, 1) GPIO.output(PIN_SUC4, 1)
GPIO.setup(PIN_SUC9, GPIO.OUT) GPIO.setup(PIN_SUC9, GPIO.OUT)
GPIO.setup(PIN_SUC10, GPIO.OUT) GPIO.setup(PIN_SUC10, GPIO.OUT)
GPIO.setup(PIN_RELAY, GPIO.OUT) GPIO.setup(PIN_RELAY, GPIO.OUT)
GPIO.output(PIN_SUC9, 1) GPIO.output(PIN_SUC9, 1)
GPIO.output(PIN_SUC10, 1) GPIO.output(PIN_SUC10, 1)
GPIO.output(PIN_RELAY, 1)
# Well, we flipped it...
GPIO.output(PIN_RELAY, 0)
WINSIZEX, WINSIZEY = 900, 680 WINSIZEX, WINSIZEY = 900, 680
timeSec = 0 timeSec = 0
@ -244,9 +256,6 @@ UP = 1
DOWN = 3 DOWN = 3
RIGHT = 2 RIGHT = 2
LEFT = 4 LEFT = 4
lastJoyState = RIGHT
score = 0
dynamoValSPI = [0,0,0]
#numery slajdow #numery slajdow
SLIDE_START = 0 SLIDE_START = 0
@ -288,11 +297,11 @@ def go_to_slide(new_slide):
logging.warning('Same slide...') logging.warning('Same slide...')
return False return False
if slides.get(slide) and not slides[slide].exit(new_slide): if slides.get(slide) and not slides[slide].exit(slides.get(new_slide)):
logging.warning('exit rejected') logging.warning('exit rejected')
return False return False
if slides.get(new_slide) and not slides[new_slide].enter(slide): if slides.get(new_slide) and not slides[new_slide].enter(slides.get(slide)):
logging.warning('enter rejected') logging.warning('enter rejected')
return False return False
@ -330,6 +339,7 @@ class BroadcastThread(threading.Thread):
print('sending') print('sending')
cs.sendto(json.dumps({ cs.sendto(json.dumps({
'slide': slide, 'slide': slide,
'name': socket.gethostname(),
}), ('255.255.255.255', 54545)) }), ('255.255.255.255', 54545))
time.sleep(1) time.sleep(1)
@ -345,7 +355,6 @@ class ReceiveThread(threading.Thread):
try: try:
msg, (host, port) = s.recvfrom(1024) msg, (host, port) = s.recvfrom(1024)
self.states[host] = json.loads(msg) self.states[host] = json.loads(msg)
print(self.states)
if all(s['slide'] in [SLIDE_CONGRATS, SLIDE_CONGRATS_EVERYTHING] if all(s['slide'] in [SLIDE_CONGRATS, SLIDE_CONGRATS_EVERYTHING]
for s in self.states.values()): for s in self.states.values()):
@ -354,6 +363,7 @@ class ReceiveThread(threading.Thread):
logging.exception('Receiver failed') logging.exception('Receiver failed')
time.sleep(0.5) time.sleep(0.5)
ser = None
for c in ['/dev/ttyUSB0', '/dev/ttyACM0']: for c in ['/dev/ttyUSB0', '/dev/ttyACM0']:
try: try:
@ -376,10 +386,12 @@ for c in ['/dev/ttyUSB0', '/dev/ttyACM0']:
rth.daemon = True rth.daemon = True
rth.start() rth.start()
webapp.app.rth = rth
def win(): def win():
print "GAME OVER - YOU WIN" print "GAME OVER - YOU WIN"
GPIO.output(PIN_RELAY, 0) GPIO.output(PIN_RELAY, 1)
def signalWin(success): def signalWin(success):
pin = 0 pin = 0
@ -446,9 +458,6 @@ def die(screen, score):
screen.blit(t, (10, 270)) screen.blit(t, (10, 270))
pygame.display.update() pygame.display.update()
pygame.time.wait(2000) pygame.time.wait(2000)
global slide
slide = SLIDE_SNAKE_DEAD
waitForEvents()
############# old main ############# old main
######## CONSTANTS ######## CONSTANTS
@ -546,11 +555,11 @@ def main():
# Set the x, y postions of the mouse click # Set the x, y postions of the mouse click
x, y = event.pos x, y = event.pos
if enterButton.collidepoint(x, y): if enterButton.collidepoint(x, y):
if passwordLetter == password1: if passwordLetter == PASSWORD1:
print 'password correct for task 9.' print 'password correct for task 9.'
signalWin(9) signalWin(9)
if passwordLetter == password2: if passwordLetter == PASSWORD2:
print 'password correct for task 10.' print 'password correct for task 10.'
signalWin(10) signalWin(10)

View File

@ -2,18 +2,33 @@
<body> <body>
<table> <table>
<ul>
{% for k, v in states %}
<li>
{% if v['name'] == hostname %}<b>{% endif %}
<a href="http://{{ k }}:5000">{{ v['name'] }}</a> ({{ v['slide'] }})
{% if v['name'] == hostname %}</b>{% endif %}
</li>
{% endfor %}
</ul>
<tr> <tr>
<th>Włącz</th> <th>Włącz</th>
{% for n in range(10) %} {% for n in range(10) %}
<td><a href="/set/{{ n }}">{{ n + 1 }}</a></td> <td><a href="/set/{{ n }}">{{ n + 1 }}</a></td>
{% endfor %} {% endfor %}
<td><a href="/set/all">Wszystko</a></td>
</tr> </tr>
<tr> <tr>
<th>Wyłącz</th> <th>Wyłącz</th>
{% for n in range(10) %} {% for n in range(10) %}
<td><a href="/clear/{{ n }}">{{ n + 1 }}</a></td> <td><a href="/clear/{{ n }}">{{ n + 1 }}</a></td>
{% endfor %} {% endfor %}
<td><a href="/clear/all">Wszystko</a></td>
</tr> </tr>
</table> </table>
<a href="/restart" style="color: red">RESTART</a>
</body> </body>
</html> </html>

View File

@ -1,6 +1,8 @@
import flask import flask
import string import string
import time
import threading import threading
import socket
app = flask.Flask(__name__) app = flask.Flask(__name__)
@ -14,9 +16,41 @@ def clear_task(task):
app.port.write(string.lowercase[task]) app.port.write(string.lowercase[task])
return flask.redirect('/') return flask.redirect('/')
@app.route('/set/all')
def set_all():
app.port.write(string.uppercase)
return flask.redirect('/')
@app.route('/clear/all')
def clear_all():
app.port.write(string.lowercase)
return flask.redirect('/')
@app.route('/restart')
def restart():
import thread
thread.interrupt_main()
return flask.redirect('/') # xD
@app.route('/') @app.route('/')
def index(): def index():
return flask.render_template('index.html') states = app.rth.states.items()
states.sort(key=lambda (k, v): v['name'])
return flask.render_template(
'index.html', hostname=socket.gethostname(), states=states)
@app.route('/arduino/reset')
def reset():
app.port.dtr = False
time.sleep(0.5)
app.port.dtr = True
time.sleep(0.5)
app.port.dtr = False
time.sleep(0.5)
app.port.dtr = True
return flask.redirect('/')
def init(ser): def init(ser):
app.port = ser app.port = ser