Skip to content

Commit 61ed129

Browse files
authored
Add files via upload
1 parent 6f45e33 commit 61ed129

9 files changed

Lines changed: 314 additions & 0 deletions

File tree

Kegomatic/adabot.png

8.95 KB
Loading

Kegomatic/adabot.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import pygame, sys
2+
from pygame.locals import *
3+
4+
class adabot():
5+
image = ''
6+
x = 0
7+
y = 0
8+
ll = 0 # left limit
9+
rl = 0 # right limit
10+
direction = 'right'
11+
12+
def __init__(self, x, y, ll, rl):
13+
self.image = pygame.image.load('adabot.png')
14+
self.image = self.image.convert_alpha()
15+
self.x = x
16+
self.y = y
17+
self.ll = ll
18+
self.rl = rl
19+
20+
def update(self):
21+
if (self.direction == 'right'):
22+
self.x += 5
23+
else:
24+
self.x -= 5
25+
26+
if (self.x > self.rl or self.x < self.ll):
27+
self.direction = 'right' if self.direction == 'left' else 'left'

Kegomatic/beer-bg.png

163 KB
Loading

Kegomatic/flowmeter.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import time
2+
import random
3+
class FlowMeter():
4+
PINTS_IN_A_LITER = 2.11338
5+
SECONDS_IN_A_MINUTE = 60
6+
MS_IN_A_SECOND = 1000.0
7+
displayFormat = 'metric'
8+
beverage = 'beer'
9+
enabled = True
10+
clicks = 0
11+
lastClick = 0
12+
clickDelta = 0
13+
hertz = 0.0
14+
flow = 0 # in Liters per second
15+
thisPour = 0.0 # in Liters
16+
totalPour = 0.0 # in Liters
17+
18+
def __init__(self, displayFormat, beverage):
19+
self.displayFormat = displayFormat
20+
self.beverage = beverage
21+
self.clicks = 0
22+
self.lastClick = int(time.time() * FlowMeter.MS_IN_A_SECOND)
23+
self.clickDelta = 0
24+
self.hertz = 0.0
25+
self.flow = 0.0
26+
self.thisPour = 0.0
27+
self.totalPour = 0.0
28+
self.enabled = True
29+
30+
def update(self, currentTime):
31+
self.clicks += 1
32+
# get the time delta
33+
self.clickDelta = max((currentTime - self.lastClick), 1)
34+
# calculate the instantaneous speed
35+
if (self.enabled == True and self.clickDelta < 1000):
36+
self.hertz = FlowMeter.MS_IN_A_SECOND / self.clickDelta
37+
self.flow = self.hertz / (FlowMeter.SECONDS_IN_A_MINUTE * 7.5) # In Liters per second
38+
instPour = self.flow * (self.clickDelta / FlowMeter.MS_IN_A_SECOND)
39+
self.thisPour += instPour
40+
self.totalPour += instPour
41+
# Update the last click
42+
self.lastClick = currentTime
43+
44+
def getBeverage(self):
45+
return str(random.choice(self.beverage))
46+
47+
def getFormattedClickDelta(self):
48+
return str(self.clickDelta) + ' ms'
49+
50+
def getFormattedHertz(self):
51+
return str(round(self.hertz,3)) + ' Hz'
52+
53+
def getFormattedFlow(self):
54+
if(self.displayFormat == 'metric'):
55+
return str(round(self.flow,3)) + ' L/s'
56+
else:
57+
return str(round(self.flow * FlowMeter.PINTS_IN_A_LITER, 3)) + ' pints/s'
58+
59+
def getFormattedThisPour(self):
60+
if(self.displayFormat == 'metric'):
61+
return str(round(self.thisPour,3)) + ' L'
62+
else:
63+
return str(round(self.thisPour * FlowMeter.PINTS_IN_A_LITER, 3)) + ' pints'
64+
65+
def getFormattedTotalPour(self):
66+
if(self.displayFormat == 'metric'):
67+
return str(round(self.totalPour,3)) + ' L'
68+
else:
69+
return str(round(self.totalPour * FlowMeter.PINTS_IN_A_LITER, 3)) + ' pints'
70+
71+
def clear(self):
72+
self.thisPour = 0;
73+
self.totalPour = 0;

Kegomatic/kegomatic-splash.png

209 KB
Loading

Kegomatic/kegomatic.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#!/usr/bin/python
2+
import os
3+
import time
4+
import math
5+
import logging
6+
import pygame, sys
7+
from pygame.locals import *
8+
import RPi.GPIO as GPIO
9+
from twitter import *
10+
from flowmeter import *
11+
from adabot import *
12+
from seekrits import *
13+
14+
t = Twitter( auth=OAuth(OAUTH_TOKEN, OAUTH_SECRET, CONSUMER_KEY, CONSUMER_SECRET) )
15+
#boardRevision = GPIO.RPI_REVISION
16+
GPIO.setmode(GPIO.BCM) # use real GPIO numbering
17+
GPIO.setup(23,GPIO.IN, pull_up_down=GPIO.PUD_UP)
18+
GPIO.setup(24,GPIO.IN, pull_up_down=GPIO.PUD_UP)
19+
20+
# set up pygame
21+
pygame.init()
22+
23+
# set up the window
24+
VIEW_WIDTH = 1024
25+
VIEW_HEIGHT = 576
26+
pygame.display.set_caption('KEGBOT')
27+
lastTweet = 0
28+
view_mode = 'normal'
29+
30+
# hide the mouse
31+
pygame.mouse.set_visible(False)
32+
33+
# set up the flow meters
34+
fm = FlowMeter('metric', ["beer"])
35+
fm2 = FlowMeter('metric', ["root beer"])
36+
tweet = ''
37+
# set up the colors
38+
BLACK = (0,0,0)
39+
WHITE = (255,255,255)
40+
41+
# set up the window surface
42+
windowSurface = pygame.display.set_mode((VIEW_WIDTH,VIEW_HEIGHT), FULLSCREEN, 32)
43+
windowInfo = pygame.display.Info()
44+
FONTSIZE = 48
45+
LINEHEIGHT = 28
46+
basicFont = pygame.font.SysFont(None, FONTSIZE)
47+
48+
# set up the backgrounds
49+
bg = pygame.image.load('beer-bg.png')
50+
tweet_bg = pygame.image.load('tweet-bg.png')
51+
52+
# set up the adabots
53+
back_bot = adabot(361, 151, 361, 725)
54+
middle_bot = adabot(310, 339, 310, 825)
55+
front_bot = adabot(220, 527, 220, 888)
56+
57+
# draw some text into an area of a surface
58+
# automatically wraps words
59+
# returns any text that didn't get blitted
60+
def drawText(surface, text, color, rect, font, aa=False, bkg=None):
61+
rect = Rect(rect)
62+
y = rect.top
63+
lineSpacing = -2
64+
65+
# get the height of the font
66+
fontHeight = font.size("Tg")[1]
67+
68+
while text:
69+
i = 1
70+
71+
# determine if the row of text will be outside our area
72+
if y + fontHeight > rect.bottom:
73+
break
74+
75+
# determine maximum width of line
76+
while font.size(text[:i])[0] < rect.width and i < len(text):
77+
i += 1
78+
79+
# if we've wrapped the text, then adjust the wrap to the last word
80+
if i < len(text):
81+
i = text.rfind(" ", 0, i) + 1
82+
83+
# render the line and blit it to the surface
84+
if bkg:
85+
image = font.render(text[:i], 1, color, bkg)
86+
image.set_colorkey(bkg)
87+
else:
88+
image = font.render(text[:i], aa, color)
89+
90+
surface.blit(image, (rect.left, y))
91+
y += fontHeight + lineSpacing
92+
93+
# remove the text we just blitted
94+
text = text[i:]
95+
96+
return text
97+
98+
def renderThings(flowMeter, flowMeter2, tweet, windowSurface, basicFont):
99+
# Clear the screen
100+
windowSurface.blit(bg,(0,0))
101+
102+
# draw the adabots
103+
back_bot.update()
104+
windowSurface.blit(back_bot.image,(back_bot.x, back_bot.y))
105+
middle_bot.update()
106+
windowSurface.blit(middle_bot.image,(middle_bot.x, middle_bot.y))
107+
front_bot.update()
108+
windowSurface.blit(front_bot.image,(front_bot.x, front_bot.y))
109+
110+
# Draw Ammt Poured
111+
text = basicFont.render("CURRENT", True, WHITE, BLACK)
112+
textRect = text.get_rect()
113+
windowSurface.blit(text, (40,20))
114+
if fm.enabled:
115+
text = basicFont.render(fm.getFormattedThisPour(), True, WHITE, BLACK)
116+
textRect = text.get_rect()
117+
windowSurface.blit(text, (40,30+LINEHEIGHT))
118+
if fm2.enabled:
119+
text = basicFont.render(fm2.getFormattedThisPour(), True, WHITE, BLACK)
120+
textRect = text.get_rect()
121+
windowSurface.blit(text, (40, 30+(2*(LINEHEIGHT+5))))
122+
123+
# Draw Ammt Poured Total
124+
text = basicFont.render("TOTAL", True, WHITE, BLACK)
125+
textRect = text.get_rect()
126+
windowSurface.blit(text, (windowInfo.current_w - textRect.width - 40, 20))
127+
if fm.enabled:
128+
text = basicFont.render(fm.getFormattedTotalPour(), True, WHITE, BLACK)
129+
textRect = text.get_rect()
130+
windowSurface.blit(text, (windowInfo.current_w - textRect.width - 40, 30 + LINEHEIGHT))
131+
if fm2.enabled:
132+
text = basicFont.render(fm2.getFormattedTotalPour(), True, WHITE, BLACK)
133+
textRect = text.get_rect()
134+
windowSurface.blit(text, (windowInfo.current_w - textRect.width - 40, 30 + (2 * (LINEHEIGHT+5))))
135+
136+
if view_mode == 'tweet':
137+
windowSurface.blit(tweet_bg,(0,0))
138+
textRect = Rect(545,265,500,225)
139+
drawText(windowSurface, tweet, BLACK, textRect, basicFont, True, None)
140+
141+
# Display everything
142+
pygame.display.flip()
143+
144+
# Beer, on Pin 23.
145+
def doAClick(channel):
146+
currentTime = int(time.time() * FlowMeter.MS_IN_A_SECOND)
147+
if fm.enabled == True:
148+
fm.update(currentTime)
149+
150+
# Root Beer, on Pin 24.
151+
def doAClick2(channel):
152+
currentTime = int(time.time() * FlowMeter.MS_IN_A_SECOND)
153+
if fm2.enabled == True:
154+
fm2.update(currentTime)
155+
156+
def tweetPour(theTweet):
157+
try:
158+
t.statuses.update(status=theTweet)
159+
except:
160+
logging.warning('Error tweeting: ' + theTweet + "\n")
161+
162+
GPIO.add_event_detect(23, GPIO.RISING, callback=doAClick, bouncetime=20) # Beer, on Pin 23
163+
GPIO.add_event_detect(24, GPIO.RISING, callback=doAClick2, bouncetime=20) # Root Beer, on Pin 24
164+
165+
# main loop
166+
while True:
167+
# Handle keyboard events
168+
for event in pygame.event.get():
169+
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
170+
GPIO.cleanup()
171+
pygame.quit()
172+
sys.exit()
173+
elif event.type == KEYUP and event.key == K_1:
174+
fm.enabled = not(fm.enabled)
175+
elif event.type == KEYUP and event.key == K_2:
176+
fm2.enabled = not(fm2.enabled)
177+
elif event.type == KEYUP and event.key == K_9:
178+
fm.clear()
179+
elif event.type == KEYUP and event.key == K_0:
180+
fm2.clear()
181+
182+
currentTime = int(time.time() * FlowMeter.MS_IN_A_SECOND)
183+
184+
if currentTime - lastTweet < 5000: # Pause for 5 seconds after tweeting to show the tweet
185+
view_mode = 'tweet'
186+
else:
187+
view_mode = 'normal'
188+
189+
if (fm.thisPour > 0.23 and currentTime - fm.lastClick > 10000): # 10 seconds of inactivity causes a tweet
190+
tweet = "Someone just poured " + fm.getFormattedThisPour() + " of " + fm.getBeverage() + " from the Adafruit kegomatic!"
191+
lastTweet = int(time.time() * FlowMeter.MS_IN_A_SECOND)
192+
fm.thisPour = 0.0
193+
tweetPour(tweet)
194+
195+
if (fm2.thisPour > 0.23 and currentTime - fm2.lastClick > 10000): # 10 seconds of inactivity causes a tweet
196+
tweet = "Someone just poured " + fm2.getFormattedThisPour() + " of " + fm2.getBeverage() + " from the Adafruit kegomatic!"
197+
lastTweet = int(time.time() * FlowMeter.MS_IN_A_SECOND)
198+
fm2.thisPour = 0.0
199+
tweetPour(tweet)
200+
201+
# reset flow meter after each pour (2 secs of inactivity)
202+
if (fm.thisPour <= 0.23 and currentTime - fm.lastClick > 2000):
203+
fm.thisPour = 0.0
204+
205+
if (fm2.thisPour <= 0.23 and currentTime - fm2.lastClick > 2000):
206+
fm2.thisPour = 0.0
207+
208+
# Update the screen
209+
renderThings(fm, fm2, tweet, windowSurface, basicFont)

Kegomatic/rootbeer-bg.png

160 KB
Loading

Kegomatic/seekrits.py.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
OAUTH_TOKEN = ''
2+
OAUTH_SECRET = ''
3+
CONSUMER_KEY = ''
4+
CONSUMER_SECRET = ''
5+

Kegomatic/tweet-bg.png

161 KB
Loading

0 commit comments

Comments
 (0)