-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbar.py
336 lines (281 loc) · 12.5 KB
/
bar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
import time
import sys
import RPi.GPIO as GPIO
#from RPi import GPIO
import json
from threading import Thread
import traceback
import pickle
class Bar:
class Drink:
class Version:
def __init__(self, shortname: str, ingredients: [object], proportions: [float], glassize: int) -> object:
self.shortname = shortname
self.glassize = glassize
assert (len(ingredients) == len(proportions)), "No. of drinks and no. of proportions must be equal."
self.ingredients = ingredients # list of Ingredient-Instances
self.proportions = proportions # list of distribution
# for ingredient in ingredients:
# ingredient.assignTo(self)
@classmethod
def by_mililiters(cls, shortname, ingredients, volumina):
# self.shortname = shortname
assert (len(ingredients) == len(volumina)), "No. of drinks and no. of proportions must be equal."
glassize = 0
for volume in volumina:
glassize += volume
proportions = []
for volume in volumina:
proportions.append(volume / glassize * 100)
return cls(shortname, ingredients, proportions, glassize)
@property
def available(self):
for ingredient, proportion in zip(self.ingredients, self.proportions):
need = proportion / 100 * self.glassize
if not ingredient.available(need):
return False
return True
# def make(self): (deprecated)
# # To Do
# threads = []
# needs = []
# for ingredient, proportion in zip(self.ingredients, self.proportions):
# need = proportion / 100 * self.glassize
# t = Thread(target=ingredient.pump.pour, args=(need,))
# t.start()
# threads.append(t)
# needs.append(need)
# while threads:
# for thread, ingredient, need in zip(threads, self.ingredients, needs):
# if thread.is_alive():
# continue
# threads.remove(thread)
# ingredient.use(need)
def make(self):
# To Do
threads = []
for ingredient, proportion in zip(self.ingredients, self.proportions):
need = proportion / 100 * self.glassize
t = Thread(target=ingredient.pump.pour, args=(need,))
t.start()
threads.append(t)
ingredient.use(need)
@property
def duration(self):
duration = 0
for ingredient, proportion in zip(self.ingredients, self.proportions):
need = proportion / 100 * self.glassize
duration = max(duration, ingredient.pump.duration(volume=need))
return duration
def change_ingredients(self, ingredients: [object], proportions: [float]):
assert (len(ingredients) == len(proportions)), "No. of drinks and no. of proportions must be equal."
self.ingredients = ingredients # list of Ingredient-Instances
self.proportions = proportions # list of distribution
def __init__(self, name: str, type: str, picture: str, description: str) -> object:
self.name = name
self.type = type
self.picture = picture # name of picture file
self.description = description
self.versions = []
def create_version(self, shortname: str, ingredients: [object], proportions: [float], glassize: int):
version = self.Version(shortname, ingredients, proportions, glassize)
self.versions.append(version)
def delete_version(self, versionid):
del self.versions[versionid]
@property
def available(self):
for version in self.versions:
if version.available:
return True
return False
class Ingredient:
# available = false # => muss in Methode
def __init__(self, name: str, percentage: float, bottlesize: float, remaining: float = None) -> object:
self.name = name
self.percentage = percentage # in 0 - 100
self.bottlesize = bottlesize # in ml
if remaining is None:
self.remaining = bottlesize
else:
self.remaining = remaining # in ml
self.assignedTo = []
def assignPump(self, pump: object):
self.pump = pump
def unplug(self):
self.pump = None
def available(self, need=0):
if self.pump is None:
return False
if self.remaining - need < 0:
return False
return True
def use(self, amount):
self.remaining = self.remaining - amount
def swapBottle(self):
self.remaining = self.bottlesize
def assignTo(self, version: object):
self.assignedTo.append(version)
def deleteFrom(self, version: object):
self.assignedTo.remove(version)
def change_Ingredient(self, name: str, percentage: float, bottlesize: float, pump: object = None, remaining: float = None):
self.name = name
self.percentage = percentage
self.bottlesize = bottlesize
if remaining is None:
self.remaining = bottlesize
else:
self.remaining = remaining # in ml
if pump is None:
self.unplug()
else:
self.assignPump(pump)
# follow_up: method for new bottle, state of bottle, auto availability
class Pump:
def __init__(self, pin: int, flowrate: int = 500) -> object:
#self.number = number
self.pin = pin
self.flowrate = flowrate # standard: 500 ml/min
def pour(self, volume):
duration = volume / self.flowrate * 60
GPIO.output(self.pin, GPIO.LOW)
print('Start pouring from pin {} ...'.format(self.pin))
time.sleep(duration)
GPIO.output(self.pin, GPIO.HIGH)
print('Stop pouring from pin {}, time elapsed: {}s.'.format(self.pin, duration))
def duration(self, volume):
return volume / self.flowrate * 60
def clean(self):
GPIO.output(self.pin, GPIO.LOW)
print('Start cleaning pin {} ...'.format(self.pin))
time.sleep(10)
GPIO.output(self.pin, GPIO.HIGH)
print('Stop cleaning pin {} ...'.format(self.pin))
def __init__(self, folder:str = None):
# check if saved drinks, ingredients, pumps, versions
# otherwise create empty objects
self.drinks = []
self.ingredients = []
self.pumps = []
if folder:
print("Reloading config from json..")
self.reload_config(folder)
def create_drink(self, name: str, type: str, picture: str, description: str):
drink = self.Drink(name, type, picture, description)
self.drinks.append(drink)
def delete_drink(self, drink):
self.drinks.remove(drink)
def create_ingredient(self, name: str, percentage: float, bottlesize: float, remaining: float = None, pump: int = None):
ingredient = self.Ingredient(name, percentage, bottlesize, remaining)
if pump != None:
ingredient.assignPump(self.pumps[pump])
self.ingredients.append(ingredient)
def pos_delete_ingredient(self, ingredient):
for drink in self.drinks:
for version in drink.versions:
for assignedIng in version.ingredients:
if ingredient == assignedIng:
return False
return True
def delete_ingredient(self, ingredient):
for drink in self.drinks:
for version in drink.versions:
for assignedIng in version.ingredients:
if ingredient == assignedIng:
return "assigned"
self.ingredients.remove(ingredient)
return 0
def create_pump(self, pin: int, flowrate: int = 500):
pump = self.Pump(pin, flowrate)
self.pumps.append(pump)
def pos_delete_pump(self, pump):
for ingredient in self.ingredients:
if ingredient.pump == pump:
return False
return True
def delete_pump(self, pump: object):
if not self.pos_delete_ingredient(pump):
return "assigned"
self.pumps.remove(pump)
return 0
def save_config(self, folder):
json_pumps = []
json_ingredients = []
json_drinks=[]
for pump in self.pumps:
json_pumps.append({
"pin": pump.pin,
"flowrate": pump.flowrate
})
for ing in self.ingredients:
dic = {
"name": ing.name,
"percentage": ing.percentage,
"bottlesize": ing.bottlesize,
"remaining": ing.remaining,
"pump": self.pumps.index(ing.pump)
}
json_ingredients.append(dic)
for drink in self.drinks:
dic = {
"name": drink.name,
"type": drink.type,
"picture": drink.picture,
"description": drink.description
}
versions = []
for version in drink.versions:
vdic = {
"shortname": version.shortname,
"glassize": version.glassize,
"proportions": version.proportions
}
ingredients = []
for ing in version.ingredients:
ingredients.append(self.ingredients.index(ing))
vdic["ingredients"] = ingredients
versions.append(vdic)
dic["versions"] = versions
json_drinks.append(dic)
with open(folder + "/pumps.json", "w") as write_file:
json.dump(json_pumps, write_file, indent=4, sort_keys=True)
with open(folder + "/ingredients.json", "w") as write_file:
json.dump(json_ingredients, write_file, indent=4, sort_keys=True)
with open(folder + "/drinks.json", "w") as write_file:
json.dump(json_drinks, write_file, indent=4, sort_keys=True)
def reload_config(self, folder):
try:
pumps = []
ingredients = []
drinks = []
with open(folder + "/pumps.json", "r") as read_file:
pumps = json.load(read_file)
print(pumps)
with open(folder + "/ingredients.json", "r") as read_file:
ingredients = json.load(read_file)
print(ingredients)
with open(folder + "/drinks.json", "r") as read_file:
drinks = json.load(read_file)
print(drinks)
print("Reloading pumps..")
for pump in pumps:
self.create_pump(pin=pump["pin"], flowrate=pump["flowrate"])
print("Reloading bottles..")
for ing in ingredients:
self.create_ingredient(name=ing["name"], percentage=ing["percentage"], bottlesize=ing["bottlesize"],
remaining=ing["remaining"], pump=ing["pump"])
print("Reloading drinks..")
for iddrink, drink in enumerate(drinks):
self.create_drink(name=drink["name"], type=drink["type"],
picture=drink["picture"], description=drink["description"])
versions = drink["versions"]
for version in versions:
version_ings = []
for ingid in version["ingredients"]:
version_ings.append(self.ingredients[ingid])
self.drinks[iddrink].create_version(shortname=version["shortname"], ingredients=version_ings,
proportions=version["proportions"], glassize=version["glassize"])
print("Reloading done!")
return 0
except:
print("Could not reload from json. Something went wrong..")
return 1