grocy/scripts/barcode_reader.py
2019-04-27 00:09:03 -06:00

241 lines
9.7 KiB
Python
Executable File

#!/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
UPC_DATABASE_API='YOUR_TOKEN'
buycott_token='YOUR_TOKEN'
GROCY_API='YOUR_TOKEN'
add_id='YOUR_ADD_BARCODE'
base_url = 'YOUR_BASE_URL'
ADD = 0
barcode = ''
found = ''
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'
def increase_inventory(upc):
#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
barcode = ''
def decrease_inventory(upc):
#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
else:
print ("The current stock amount is 0 so there was nothing for us to do here")
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
#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:
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):
if UPC_DATABASE_API != '':
print("Looking up the UPC")
url = "https://api.upcdatabase.org/product/%s/%s" % (upc, UPC_DATABASE_API)
headers = {
'cache-control': "no-cache",
}
try:
r = requests.get(url, headers=headers)
if r.status_code==200:
print("UPC DB found it so now going to add it to the system")
j = r.json()
name = j['title']
description = j['description']
#We now have what we need to add it to grocy so lets do that
add_to_system(upc, name, description)
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 buycott_token != '':
print("Looking up in Buycott")
url = "https://www.buycott.com/api/v4/products/lookup"
headers = {
'Content-Type': 'application/json'
}
data={'barcode':upc,
'access_token':buycott_token
}
try:
r = requests.get(url=url, json=data, headers=headers)
j = r.json()
if r.status_code == 200:
print("Buycott found it so now we're going to gather some info here and then add it to the system")
name = j['products'][0]['product_name']
description = j['products'][0]['product_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
if name != '':
add_to_system(upc, name, description)
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
else:
#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:
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)
else:
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=''
add_to_system(upc, name, description)
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
#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
if response_code != 204:
#Something went wrong and the add the product was not added
print("Adding the product with %s failed not sure why but it did") % (upc)
product_id_lookup(upc)
#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": 6,
"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)
if response_code !=204:
print("Adding the product failed")
#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
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 != '':
if barcode == add_id and ADD == 0:
ADD = 1
barcode=''
print("Entering add mode")
elif barcode == add_id and ADD == 1:
ADD = 0
barcode=''
print("Entering consume mode")
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))