diff --git a/.rsync-filter b/.rsync-filter new file mode 100644 index 0000000..7923e94 --- /dev/null +++ b/.rsync-filter @@ -0,0 +1 @@ +- custom diff --git a/README.md b/README.md index 49735e6..0f6fc66 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,8 @@ Building and deployment $ cd arduino && pio run && cd .. $ cd raspi/mgmt && ansible-playbook playbook.yml && ansible-playbook arduino.yml + +Customization +============= + +`raspi/mgmt/custom/{{ IP }}` is overlaid over default raspi/ code diff --git a/raspi/gameplayconfig.py b/raspi/gameplayconfig.py new file mode 100644 index 0000000..730c092 --- /dev/null +++ b/raspi/gameplayconfig.py @@ -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' diff --git a/raspi/mgmt/hosts b/raspi/mgmt/hosts index dd42fcc..76204c9 100644 --- a/raspi/mgmt/hosts +++ b/raspi/mgmt/hosts @@ -1,5 +1,11 @@ -[raspi] +[raspi-wifi] 192.168.43.12 192.168.43.44 192.168.43.219 192.168.43.231 + +[raspi] +10.21.37.150 +10.21.37.180 +10.21.37.185 +10.21.37.226 diff --git a/raspi/mgmt/playbook.yml b/raspi/mgmt/playbook.yml index 9ef4c07..08a8bea 100644 --- a/raspi/mgmt/playbook.yml +++ b/raspi/mgmt/playbook.yml @@ -3,6 +3,8 @@ become_user: root tasks: - synchronize: src=../.. dest=/home/pi/sejf + - synchronize: src="custom/{{ inventory_hostname }}" dest=/home/pi/sejf/raspi + ignore_errors: yes - file: path=/etc/xdg/autostart/pprompt.desktop state=absent - copy: src=autostart dest=/home/pi/.config/lxsession/LXDE-pi/autostart - copy: src=sejf.desktop dest=/etc/xdg/autostart diff --git a/raspi/mgmt/sejf.desktop b/raspi/mgmt/sejf.desktop index cdbdd9b..7874fc6 100755 --- a/raspi/mgmt/sejf.desktop +++ b/raspi/mgmt/sejf.desktop @@ -2,6 +2,6 @@ Type=Application Name=sejf NoDisplay=true -Exec=python /home/pi/sejf/raspi/pySejf.py +Exec=/home/pi/sejf/raspi/run.sh Terminal=true NotShowIn=GNOME;KDE;XFCE; diff --git a/raspi/pySejf.py b/raspi/pySejf.py index c289e9f..0cb5075 100644 --- a/raspi/pySejf.py +++ b/raspi/pySejf.py @@ -9,6 +9,7 @@ import threading import logging import socket import json +import string logging.basicConfig(level=logging.INFO) import random, pygame @@ -45,9 +46,10 @@ class ImageSlide(Slide): class FinalSlide(ImageSlide): 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): global wall_a if(wall_a): @@ -58,9 +60,6 @@ class FinalEverythingSlide(ImageSlide): return True - def exit(self, next_slide): - return False - class SnakeSlide(Slide): def enter(self, prev_slide=None): self.xs = [290, 290, 290, 290, 290]; @@ -74,28 +73,41 @@ class SnakeSlide(Slide): #img.fill((255, 0, 0)) self.f = FONT_SNAKE self.clock = pygame.time.Clock() + self.finished = False return True + def finish(self): + self.finished = True + self.finish_time = time.time() + def handle(self, e): print(e) if e.type == KEYDOWN: - 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_LEFT and self.dirs != 1:self.dirs = 3 - elif e.key == K_RIGHT and self.dirs != 3:self.dirs = 1 + 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_LEFT and self.dirs != 1: self.dirs = 3 + 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) def render(self, screen): self.clock.tick(TICK_SNAKE) + if self.finished: + f=FONT_SNAKE + t=f.render(MSG_SNAKE+str(self.score), True, (0, 0, 0)) + screen.blit(t, (10, 270)) + return + i = len(self.xs)-1 while i >= 2: if collide(self.xs[0], self.xs[i], self.ys[0], self.ys[i], 20, 20, 20, 20): - die(screen, self.score) - self.score = 0 - self.enter() + self.finish() + return i-= 1 if collide(self.xs[0], self.applepos[0], self.ys[0], self.applepos[1], 20, 10, 20, 10): @@ -106,9 +118,8 @@ class SnakeSlide(Slide): 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: - die(screen, self.score) - score = 0 - self.enter() + self.finish() + return self.xs[1:] = self.xs[:-1] self.ys[1:] = self.ys[:-1] @@ -123,8 +134,9 @@ class SnakeSlide(Slide): screen.blit(IMG_SNAKE, (0, 0)) print("drawing snake...") if(self.score > SNAKE_SCORE): - die(screen, self.score) - self.enter() + self.finish() + signalWin(4) + return for i in range(0, len(self.xs)): screen.blit(self.img, (self.xs[i], self.ys[i])) @@ -136,17 +148,7 @@ class SnakeSlide(Slide): pygame.init() pygame.mixer.init() -#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' +from gameplayconfig import * #ilosc powtorzen mp3 MP3_LOOPS = 4 @@ -230,13 +232,15 @@ else: print "this RPi is." 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_SUC10, GPIO.OUT) GPIO.setup(PIN_RELAY, GPIO.OUT) -GPIO.output(PIN_SUC9, 1) -GPIO.output(PIN_SUC10, 1) -GPIO.output(PIN_RELAY, 1) +GPIO.output(PIN_SUC9, 1) +GPIO.output(PIN_SUC10, 1) + +# Well, we flipped it... +GPIO.output(PIN_RELAY, 0) WINSIZEX, WINSIZEY = 900, 680 timeSec = 0 @@ -244,9 +248,6 @@ UP = 1 DOWN = 3 RIGHT = 2 LEFT = 4 -lastJoyState = RIGHT -score = 0 -dynamoValSPI = [0,0,0] #numery slajdow SLIDE_START = 0 @@ -288,11 +289,11 @@ def go_to_slide(new_slide): logging.warning('Same slide...') 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') 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') return False @@ -330,6 +331,7 @@ class BroadcastThread(threading.Thread): print('sending') cs.sendto(json.dumps({ 'slide': slide, + 'name': socket.gethostname(), }), ('255.255.255.255', 54545)) time.sleep(1) @@ -345,7 +347,6 @@ class ReceiveThread(threading.Thread): try: msg, (host, port) = s.recvfrom(1024) self.states[host] = json.loads(msg) - print(self.states) if all(s['slide'] in [SLIDE_CONGRATS, SLIDE_CONGRATS_EVERYTHING] for s in self.states.values()): @@ -376,10 +377,12 @@ for c in ['/dev/ttyUSB0', '/dev/ttyACM0']: rth.daemon = True rth.start() + webapp.app.rth = rth + def win(): print "GAME OVER - YOU WIN" - GPIO.output(PIN_RELAY, 0) + GPIO.output(PIN_RELAY, 1) def signalWin(success): pin = 0 @@ -446,9 +449,6 @@ def die(screen, score): screen.blit(t, (10, 270)) pygame.display.update() pygame.time.wait(2000) - global slide - slide = SLIDE_SNAKE_DEAD - waitForEvents() ############# old main ######## CONSTANTS @@ -546,11 +546,11 @@ def main(): # Set the x, y postions of the mouse click x, y = event.pos if enterButton.collidepoint(x, y): - if passwordLetter == password1: + if passwordLetter == PASSWORD1: print 'password correct for task 9.' signalWin(9) - if passwordLetter == password2: + if passwordLetter == PASSWORD2: print 'password correct for task 10.' signalWin(10) diff --git a/raspi/run.sh b/raspi/run.sh new file mode 100755 index 0000000..fb0f19e --- /dev/null +++ b/raspi/run.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Simple SUPERVISOR script to keep pySejf running... +( +flock -n 9 || exit 1 + +cd $(dirname $(realpath $0)) + +while true; do + python pySejf.py 2>&1 | tee -a /tmp/pysejf.log + sleep 0.5; +done +) 9>/var/lock/pysejf diff --git a/raspi/templates/index.html b/raspi/templates/index.html index 2872457..7483848 100644 --- a/raspi/templates/index.html +++ b/raspi/templates/index.html @@ -2,18 +2,33 @@ + + {% for n in range(10) %} {% endfor %} + + {% for n in range(10) %} {% endfor %} +
Włącz{{ n + 1 }}Wszystko
Wyłącz{{ n + 1 }}Wszystko
+ +RESTART diff --git a/raspi/webapp.py b/raspi/webapp.py index 52d186d..b52346b 100644 --- a/raspi/webapp.py +++ b/raspi/webapp.py @@ -1,6 +1,8 @@ import flask import string +import time import threading +import socket app = flask.Flask(__name__) @@ -14,9 +16,41 @@ def clear_task(task): app.port.write(string.lowercase[task]) 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('/') 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): app.port = ser