Skip to content

Instantly share code, notes, and snippets.

@huggre
Created July 3, 2020 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huggre/5815111ed70f5b0ed456ff5c979e3d4a to your computer and use it in GitHub Desktop.
Save huggre/5815111ed70f5b0ed456ff5c979e3d4a to your computer and use it in GitHub Desktop.
# import the necessary packages
from __future__ import print_function
from PIL import Image
from PIL import ImageTk
import tkinter as tki
from tkinter import scrolledtext
from pyzbar import pyzbar
import threading
import imutils
import cv2
import os
import csv
import json
# Import the PyOTA library
import iota
from iota import Address
class ReverseVendingMachine:
def __init__(self, vs):
# IOTA seed used for payment transaction
# Replace with your own devnet seed
seed = b"YOUR9SEED9GOES9HERE"
# URL to IOTA fullnode used when interacting with the Tangle
iotaNode = "https://nodes.devnet.iota.org:443"
# Define api object
self.api = iota.Iota(iotaNode, seed=seed)
# Define Total reward variable
self.total_reward = 0
# Define some objects
self.vs = vs
self.frame = None
self.thread = None
self.stopEvent = None
# Initialize the root window and VideoStream panel
self.root = tki.Tk()
self.panel = None
# Define window header label
self.header_lbl = tki.Label(self.root, text='Recycle with IOTA')
self.header_lbl.config(font=("Courier", 30))
self.header_lbl.grid(row=0, column=0, columnspan=2, sticky=(tki.N, tki.S, tki.E, tki.W))
# Define barcode text box
self.barcode_txt = tki.Text(self.root, height=1, width=30)
self.barcode_txt.grid(column=0, row=1, sticky=(tki.S, tki.E, tki.W))
# Define Item list
self.item_list=scrolledtext.ScrolledText(self.root, width=30, height=10, wrap=tki.WORD)
self.item_list.grid(column=0, row=2, sticky=(tki.N, tki.S, tki.E, tki.W))
# Define barcode "Scan Item" button
scan_item_btn = tki.Button(self.root, width=30, text = 'Scan Item...', command=self.scanItem)
scan_item_btn.grid(column=1, row=1, sticky=(tki.N, tki.S, tki.E, tki.W))
# Define Total Reward text box
self.total_txt = tki.Text(self.root, height=1, width=30)
self.total_txt.grid(column=0, row=3, sticky=(tki.S, tki.E, tki.W))
# Define "Clame Reward" button
get_reward_btn = tki.Button(self.root, text = 'Get Reward', command=self.initiateGetReward)
get_reward_btn.grid(column=0, row=4, sticky=(tki.N, tki.S, tki.E, tki.W))
# Define Message box
self.msg_box=scrolledtext.ScrolledText(self.root, width=30, height=10, wrap=tki.WORD)
self.msg_box.grid(column=0, row=5, columnspan=2, sticky=(tki.N, tki.S, tki.E, tki.W))
# ...
self.root.bind('<Return>', (lambda event: self.scanItem()))
# Set a callback to handle when the window is closed
self.root.wm_title("The Reverse Vending Machine")
self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose)
def getReward(self):
# Try/except statement to get around a RunTime
# error that Tkinter throws due to threading
try:
# Loop the vieoStream until we get a QR code
while not self.stopEvent.is_set():
# Grab the frame from the video stream and resize it to
# have a maximum width of 300 pixels
self.frame = self.vs.read()
self.frame = imutils.resize(self.frame, width=300)
# Get QR codes from camera using pyzbar
qrcodes = pyzbar.decode(self.frame)
# Loop over the detected qrcodes
for qrcode in qrcodes:
# Extract the bounding box location of the barcode and draw
# the bounding box surrounding the barcode on the image
(x, y, w, h) = qrcode.rect
cv2.rectangle(self.frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
# The barcode data is a bytes object so if we want to draw it
# on our output image we need to convert it to a string first
qrcodeData = qrcode.data.decode("utf-8")
qrcodeType = qrcode.type
# Draw the barcode data and barcode type on the image
text = "{} ({})".format(qrcodeData, qrcodeType)
cv2.putText(self.frame, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
# QR codes generated by the IOTA wallet or thetangle.org
# is actually a dict object so we use json to convert the
# qrcodeData string to a dict.
jsondata = json.loads(qrcodeData)
# Get address from dict
addr = jsondata.get('address')
# Now that we have the IOTA address we can exit the while loop and initiate the payment process
self.stopEvent.set()
# OpenCV represents images in BGR order; however PIL
# represents images in RGB order, so we need to swap
# the channels, then convert to PIL and ImageTk format
image = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
image = ImageTk.PhotoImage(image)
# If the videoStream panel is not None, we need to initialize it
if self.panel is None:
self.panel = tki.Label(image=image)
self.panel.image = image
self.panel.grid(row=2, column=1, rowspan=3)
# Otherwise, simply update the panel
else:
self.panel.configure(image=image)
self.panel.image = image
# Now that we have the IOTA address, lets send the reward to the cusomer
# Clear the VideoStream panel
self.panel.config(image='')
# Display sending reward message
self.msg_box.insert(tki.INSERT, 'Sending reward of ' + str(self.total_reward) + ' IOTA to address: ' + addr + '\n')
# Create transaction object
tx1 = iota.ProposedTransaction( address = iota.Address(addr), message = None, tag = iota.Tag(iota.TryteString.from_unicode('HOTELIOTA')), value = self.total_reward)
# Send transaction to tangle
self.msg_box.insert(tki.INSERT, 'Sending transaction..., please wait\n')
SentBundle = self.api.send_transfer(depth=3,transfers=[tx1], inputs=None, change_address=None, min_weight_magnitude=9)
# Display transaction sent confirmation message
self.msg_box.insert(tki.INSERT, 'Transaction sendt..., thanks for recycling with IOTA\n')
# Cleanup and prepare for next customer...
# Clear Item list
self.item_list.delete(1.0, 'end')
# Clear total reward text box
self.total_txt.delete(1.0, 'end')
# Reset Total award variable
self.total_reward = 0
# Display system is ready message
self.msg_box.insert(tki.INSERT, 'System is ready...\n')
except RuntimeError:
print("[INFO] caught a RuntimeError")
def initiateGetReward(self):
# Show "get QR code" message
self.msg_box.insert(tki.INSERT, 'Please hold a valid IOTA address QR code in front of the camera..\n')
# Start new get reward thread
self.stopEvent = threading.Event()
self.thread = threading.Thread(target=self.getReward, args=())
self.thread.start()
def scanItem(self):
barcode = self.barcode_txt.get("1.0",'end-1c')
barcode = barcode.rstrip("\n") #, Strip any trailing returns from the string
barcode_found = False
with open('barcodesdb.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for row in csv_reader:
if row[0] == barcode:
item_reward=row[1]
self.total_reward = self.total_reward + int(item_reward)
barcode_found = True
if barcode_found == True:
# If a barcode match was found in the barcode database, add Item to list
# and update the total reward texbox.
# Else, diplay barcode not message
self.item_list.insert(tki.INSERT, barcode + ': Reward=' + item_reward + ' IOTA\n')
self.msg_box.insert(tki.INSERT, 'Item approved\n')
self.total_txt.delete(1.0, 'end')
self.barcode_txt.delete(1.0, 'end')
self.total_txt.insert(tki.INSERT, 'Total Reward: ' + str(self.total_reward))
else:
self.msg_box.insert(tki.INSERT, 'Barcode not found in database\n')
def onClose(self):
# Set the stop event, cleanup the camera, and allow the rest of
# the quit process to continue
print("[INFO] closing...")
self.stopEvent.set()
self.vs.stop()
self.root.quit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment