-
Notifications
You must be signed in to change notification settings - Fork 10
/
barcode_reader.py
315 lines (303 loc) · 11.8 KB
/
barcode_reader.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
#!/usr/bin/python
import signal, sys
import json
import requests
from evdev import InputDevice, categorize, ecodes
#This will allow you to work the grocy inventory with a barcode scanner
#I found I needed to just declare some things right off the bat when the app loads such as the ADD and barcode
UPC_DATABASE_API=''
#I've been waiting for my token but you can register for one at developers.walmart.com
walmart_token=''
#This UPC lookup doesn't require a token or anything
walmart_search=1
#This UPC DB also doesn't require a token but does have a limit of 100 calls per day
upc_item_db=1
#Your Grocy API Key
GROCY_API=''
#This is some arbitrary number. We used a barcode generator and put in some random 7 digit number to use as our ADDID. You could use a barcode off of something that you will never inventory
add_id='43235735'
#This is the URL of your grocy app or IP address.
base_url = 'http://grocy.thefuzz4.net/api'
ADD = 0
barcode = ''
message_text = ''
#This is where you want the product to go. I created an entry ADDED_UPDATE_LOCATION so that it stands out when going through the prduct list so I know it needs to be addressed.
#This could be enhanced with barcodes that represent each location you have, then have the main function do some stuff but eh not worth it for me at this time
location_id = 6
device = InputDevice('/dev/input/event0') # Replace with your device
scancodes = {
11: u'0',
2: u'1',
3: u'2',
4: u'3',
5: u'4',
6: u'5',
7: u'6',
8: u'7',
9: u'8',
10: u'9'
}
NOT_RECOGNIZED_KEY = u'X'
homeassistant_url='YOUR_HOME_ASSISTANT_URL/DOMAIN/SERVICE'
homeassistant_api='YOUR_HOME_ASSISTANT_API'
def increase_inventory(upc):
global response_code
global product_name
#Need to lookup our product_id, if we don't find one we'll do a search and add it
product_id_lookup(upc)
print ("Increasing %s") % (product_name)
url = base_url+"/stock/products/%s/add" % (product_id)
data = {'amount': purchase_amount,
'transaction_type': 'purchase'}
#We have everything we need now in order to complete the rest of this function
grocy_api_call_post(url, data)
#As long as we get a 200 back from the app it means that everything went off without a hitch
if response_code != 200:
print ("Increasing the value of %s failed") % (product_name)
else:
if homeassistant_token != '':
message_text="I increased %s by a count of %s to a total count of %s" % (product_name, purchase_amount, stock_amount)
homeassistant_call(message_text)
barcode = ''
def decrease_inventory(upc):
global response_code
#Going to see if we can find a product_id, if we don't find it we'll add it. Problem here though is that we need to have a quantity in the system. If there isn't any we'll error because there is nothing to decrease. This is ok
product_id_lookup(upc)
print("Stepping into the decrease")
#Lets make sure we can actually decrease this before we get too crazy
if stock_amount > 0:
print ("Decreasing %s by 1") % (product_name)
url = base_url+"/stock/products/%s/consume" % (product_id)
data = {'amount': 1,
'transaction_type': 'consume',
'spoiled': 'false'}
#We now have everything we need and we can now proceed
grocy_api_call_post(url, data)
if response_code == 400:
print ("Decreasing the value of %s failed, are you sure that there was something for us to decrease?") % (product_name)
message_text=("I failed to decrease %") % (product_name)
homeassistant_call(message_text)
else:
print ("The current stock amount for %s is 0 so there was nothing for us to do here") % (product_name)
if homeassistant_token != '':
message_text=("The stock amount for %s was zero, so there was nothing for me to decrease") % (product_name)
homeassistant_call(message_text)
if homeassistant_token != '' and response_code == 200:
message_text=("Consumed %s. You now have %s left") % (product_name, stock_amount)
homeassistant_call(message_text)
barcode=''
def product_id_lookup(upc):
#Need to declare this as a global and we'll do this again with a few others because we need them elsewhere
global product_id
print("Looking up the product_id")
#Lets check to see if the UPC exists in grocy
url = base_url+"/stock/products/by-barcode/%s" % (upc)
headers = {
'cache-control': "no-cache",
'GROCY-API-KEY': GROCY_API
}
r = requests.get(url, headers=headers)
r.status_code
print (r.status_code)
#Going to check and make sure that we found a product to use. If we didn't find it lets search the internets and see if we can find it.
if r.status_code == 400:
message_text=("I did not have the product locally so I am now going to search for it and add it to the system")
if homeassistant_token != '':
homeassistant_call(message_text)
upc_lookup(upc)
else:
j = r.json()
global product_id
product_id = j['product']['id']
global purchase_amount
purchase_amount = j['product']['qu_factor_purchase_to_stock']
global product_name
product_name = j['product']['name']
print ("Our product_id is %s") % (product_id)
global stock_amount
stock_amount = j['stock_amount']
def upc_lookup(upc):
found_it=0
if walmart_search == 1 and found_it==0:
print("Looking up in Wal-Mart Search")
url = "https://search.mobile.walmart.com/v1/products-by-code/UPC/%s?storeId=1" % (upc)
headers = {
'Content-Type': 'application/json',
'cache-control': "no-cache"
}
try:
r = requests.get(url=url, headers=headers)
j = r.json()
if r.status_code == 200:
print("Walmart Search found it so now we're going to gather some info here and then add it to the system")
if 'data' in j:
name = j['data']['common']['name']
description = ''
#We now have what we need to add it to grocy so lets do that
#Sometimes buycott returns a success but it never actually does anything so lets just make sure that we have something
add_to_system(upc, name, description)
found_it=1
if r.status_code == 400:
found_it=0
except ValueError:
print("We failed to decode the json for this item %s") % (upc)
message_text=("Walmart errored on this item. Stupid walmart")
homeassistant_call(message_text)
except requests.exceptions.Timeout:
print("The connection timed out")
except requests.exceptions.TooManyRedirects:
print ("Too many redirects")
except requests.exceptions.RequestException as e:
print (e)
if upc_item_db == 1 and found_it==0:
#This is a free service that limits you to 100 hits per day if we can't find it here we'll still create it in the system but it will be just a dummy entry
print("Looking up in UPCItemDB")
url = "https://api.upcitemdb.com/prod/trial/lookup?upc=%s" % (upc)
headers = {
'Content-Type': 'application/json',
'cache-control': "no-cache"
}
try:
r = requests.get(url=url, headers=headers)
j = r.json()
if r.status_code == 200:
if 'total' in j:
total = j['total']
if total != 0:
print("UPCItemDB found it so now we're going to gather some info here and then add it to the system")
name=j['items'][0]['title']
description = j['items'][0]['description']
#We now have what we need to add it to grocy so lets do that
add_to_system(upc, name, description)
found_it=1
except requests.exceptions.Timeout:
print("The connection timed out")
except requests.exceptions.TooManyRedirects:
print ("Too many redirects")
except requests.exceptions.RequestException as e:
print (e)
if ean_data_db == 1 and found_it==0:
#This is a free service that limits you to 100 hits per day if we can't find it here we'll still create it in the system but it will be just a dummy entry
print("Looking up in EANDB")
url = "https://eandata.com/feed/?v=3&keycode=%s&mode=json&find=011110018427" % (ean_data_db, upc)
headers = {
'Content-Type': 'application/json',
'cache-control': "no-cache"
}
try:
r = requests.get(url=url, headers=headers)
j = r.json()
if r.status_code == 200:
if 'product' in j:
total = j['total']
if total != 0:
print("UPCItemDB found it so now we're going to gather some info here and then add it to the system")
name = j['product'][0]['attributes']['product']
description=''
#We now have what we need to add it to grocy so lets do that
add_to_system(upc, name, description)
found_it=1
except requests.exceptions.Timeout:
print("The connection timed out")
except requests.exceptions.TooManyRedirects:
print ("Too many redirects")
except requests.exceptions.RequestException as e:
print (e)
if found_it==0:
print ("The item with %s was not found so we're adding a dummy one") % (upc)
name="The product was not found in the external sources you will need to fix %s" % (upc)
description='dummy'
add_to_system(upc, name, description)
found_it=1
if found_it==1:
#By now we have our product added to the system. We can now lookup our product_id again and then proceed with whatever it is we were doing
product_id_lookup(upc)
else:
message_text=("I was unable to find a productID for %s and it is not in the system")
homeassistant_call(message_text)
print(message_text)
#Rather than have this in every section of the UPC lookup we just have a function that we call for building the json for the api call to actually add it to the system
def add_to_system(upc, name, description):
url = base_url+"/objects/products"
data ={"name": name,
"description": description,
"barcode": upc,
"location_id": location_id,
"qu_id_purchase": 1,
"qu_id_stock":0,
"qu_factor_purchase_to_stock": 1,
"default_best_before_days": -1
}
grocy_api_call_post(url, data)
if response_code==204:
print("Just added %s to the system") % (name)
product_id_lookup(upc)
else:
print("Adding the product with %s failed") % (upc)
#This is a function that is referred to a lot through out the app so its easier for us to just use it as a function rather than type it out over and over
def grocy_api_call_post(url, data):
headers = {
'cache-control': "no-cache",
'GROCY-API-KEY': GROCY_API
}
try:
r = requests.post(url=url, json=data, headers=headers)
r.status_code
global response_code
response_code = r.status_code
print (r.status_code)
except requests.exceptions.Timeout:
print("The connection timed out")
except requests.exceptions.TooManyRedirects:
print ("Too many redirects")
except requests.exceptions.RequestException as e:
print (e)
def homeassistant_call(message_text):
print("Calling homeassistant to speak some text")
headers = {
'Authorization': 'Bearer {}'.format(homeassistant_token),
'Content-Type': 'application/json'
}
data = { "message":message_text,
"data":{"type":"tts"},
"target":["media_player.jason_s_2nd_echo_show_2"]
}
r = requests.post(url=homeassistant_url, json=data, headers=headers)
r.status_code
if r.status_code != 200:
print("HomeAssistant call failed with a status code of %s") % (r.status_code)
for event in device.read_loop():
if event.type == ecodes.EV_KEY:
eventdata = categorize(event)
if eventdata.keystate == 1: # Keydown
scancode = eventdata.scancode
if scancode == 28: # Enter
print (barcode)
if barcode != '' and len(barcode) >= 7:
if barcode == add_id and ADD == 0:
ADD = 1
barcode=''
print("Entering add mode")
if homeassistant_token != '':
message_text="Entering add mode"
homeassistant_call(message_text)
elif barcode == add_id and ADD == 1:
ADD = 0
barcode=''
print("Entering consume mode")
if homeassistant_token != '':
message_text="Entering consume mode"
homeassistant_call(message_text)
elif ADD == 1:
upc=barcode
barcode=''
increase_inventory(upc)
elif ADD == 0:
upc=barcode
barcode=''
decrease_inventory(upc)
else:
key = scancodes.get(scancode, NOT_RECOGNIZED_KEY)
barcode = barcode + key
if key == NOT_RECOGNIZED_KEY:
print('unknown key, scancode=' + str(scancode))