Article Outline
Example Python program let_there_be_light_addr.py
Modules
- import requests
- import json
- import configparser
- from tkinter import *
- import tkinter.font
- import tkinter.ttk
- from PIL import ImageTk, Image
- import pyqrcode
- import time
- import datetime
- from iota import Iota
- from iota import Address
Methods
- def exitGUI():
- def updateQRcode(QRaddr):
- def showXBM():
- def generateNewAddress(addrIndexCount):
- def checkbalance(addr):
- def updatePaymentStatus(paymentStatus):
- def getLightPriceIOTA():
- def displayprice():
- def getTransExist(addr):
- def getNewIndex():
- def maintask(balcheckcount, lightbalance, lightstatus, transFound, addr, addrIndex):
Code
Python tkinter example
# Import the requests library to send http request to coinbase.com
import requests
# Import json library for reading json data returned by the http request
import json
# Import the configparser library used for reading and writing to let_there_be_light.ini
import configparser
# Import some funtions from TkInter
from tkinter import *
import tkinter.font
import tkinter.ttk
# Import some functions from Pillow
from PIL import ImageTk, Image
# Import the PyQRCode library
import pyqrcode
# Imports some Python Date/Time functions
import time
import datetime
# Imports the PyOTA library
from iota import Iota
from iota import Address
# Define the Exit function
def exitGUI():
root.destroy()
# Seed used for generating addresses and collecting funds.
# IMPORTANT!!! Replace with your own seed
MySeed = b"WRITE9YOUR9OWN9SEED9HERE9....................."
# URL to IOTA fullnode used when checking balance
iotaNode = "https://nodes.thetangle.org:443"
# Create an IOTA object
api = Iota(iotaNode, MySeed)
# Define main form as root
root = Tk()
# Set the form background to white
root.config(background="white")
# TkInter font to be used in GUI
myFont = tkinter.font.Font(family = 'Helvetica', size = 12, weight = "bold")
# Set main form to full screen
root.overrideredirect(True)
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.focus_set() # <-- move focus to this widget
root.bind("<Escape>", lambda e: e.widget.quit())
# Define mainFrame
mainFrame = tkinter.Frame(root)
mainFrame.config(background="white")
mainFrame.place(relx=0.5, rely=0.5, anchor=CENTER)
# Create and render the QR code
qrframe = tkinter.Frame(mainFrame)
qrframe.grid(row=0,column=0,rowspan=3)
code = pyqrcode.create('')
code_xbm = code.xbm(scale=3)
code_bmp = tkinter.BitmapImage(data=code_xbm)
code_bmp.config(background="white")
qrcode = tkinter.Label(qrframe, image=code_bmp, borderwidth = 0)
qrcode.grid(row=0, column=0)
# Create and render logo
# Make sure you download and place the "iota_logo75.jpg" file in the same folder as your python file.
# The logofile can be dowloaded from: https://github.com/huggre/pay_the_light_gui/blob/master/iota_logo75.jpg
path = "iota_logo75.jpg"
img = ImageTk.PhotoImage(Image.open(path))
iotalogo = tkinter.Label(mainFrame, image = img, borderwidth = 0)
iotalogo.grid(row=0,column=1)
# Create and render timer
timeText = tkinter.Label(mainFrame, text="", font=("Helvetica", 50))
timeText.config(background='white')
timeText.grid(row=1,column=1)
# Create and render Exit button
exitButton = Button(mainFrame, text='Exit', font=myFont, command=exitGUI, bg='white', height=1, width=10)
exitButton.grid(row=2,column=1)
# Create and render price text
priceTextFrame = tkinter.Frame(mainFrame)
priceTextFrame.grid(row=3,column=0,columnspan=2)
priceText = tkinter.Label(priceTextFrame, text="Here comes price", font=("Helvetica", 12))
priceText.config(background='white')
priceText.grid(row=3,column=0)
# Create and render progress bar
progFrame = tkinter.Frame(mainFrame)
progFrame.grid(row=4,column=0,columnspan=2)
mpb = tkinter.ttk.Progressbar(progFrame,orient ="horizontal",length = 435, mode ="determinate")
mpb.grid(row=4,column=0)
mpb["maximum"] = 30
mpb["value"] = 0
# Create and render payment status text
paymentStatusFrame = tkinter.Frame(mainFrame)
paymentStatusFrame.grid(row=5,column=0,columnspan=2)
paymentStatusText = tkinter.Label(paymentStatusFrame, text="Waiting for new transactions", font=("Helvetica", 9))
paymentStatusText.config(background='white')
paymentStatusText.grid(row=5,column=0)
# Create and render light status text
statusTextFrame = tkinter.Frame(mainFrame)
statusTextFrame.grid(row=6,column=0,columnspan=2)
statusText = tkinter.Label(statusTextFrame, text="Light is OFF", font=("Helvetica", 9))
statusText.config(background='white')
statusText.grid(row=6,column=0)
# Define function to update QR code based on new address
def updateQRcode(QRaddr):
code = pyqrcode.create(QRaddr)
code_xbm = code.xbm(scale=3)
code_bmp = tkinter.BitmapImage(data=code_xbm)
code_bmp.config(background="white")
qrcode.configure(image=code_bmp)
qrcode.image = code_bmp
# Define function to replace QR code with hourglass icon
# Make sure you download and place the "hourglass.xbm" file in the same folder as your python file.
# The hourglass icon file can be dowloaded from: https://gist.github.com/huggre/c126863786991b49c2965d42b12f6b3d
def showXBM():
xbm_img = tkinter.BitmapImage(file="hourglass.xbm")
xbm_img.config(background="white")
qrcode.configure(image=xbm_img)
qrcode.image = xbm_img
# Define function to generate new IOTA address
def generateNewAddress(addrIndexCount):
result = api.get_new_addresses(index=addrIndexCount, count=1, security_level=2)
addresses = result['addresses']
QRaddr=str(addresses[0].with_valid_checksum())
updateQRcode(QRaddr)
address = [addresses[0]]
return(address)
# Define function for checking address balance on the IOTA tangle.
def checkbalance(addr):
gb_result = api.get_balances(addr)
balance = gb_result['balances']
return (balance[0])
# Define Function to displays payment status in GUI
def updatePaymentStatus(paymentStatus):
paymentText="Payment Status: " + paymentStatus
paymentStatusText.configure(text=paymentText)
# Define function to return light price in IOTA's based on market value on marketcap.com
def getLightPriceIOTA():
r = requests.get('https://api.coinmarketcap.com/v1/ticker/iota/')
for coin in r.json():
fprice = float(coin["price_usd"])
lightprice_IOTA = fprice * lightprice_USD
return (lightprice_IOTA)
# Define function to display price in GUI
def displayprice():
sprice = "PRICE: " + str(lightprice_USD) + " USD / " + str(round(getLightPriceIOTA(),3)) + " MIOTA pr. minute"
priceText.configure(text=sprice)
# Define function to check for existing address transactions
def getTransExist(addr):
result = api.find_transactions(addresses=addr)
myhashes = result['hashes']
if len(myhashes) > 0:
transFound = True
else:
transFound = False
return(transFound)
# Define function for reading and storing address indexes
# Make sure you download and place the "let_there_be_light.ini" file in the same folder as your python file.
# The let_there_be_light.ini file can be dowloaded from: https://gist.github.com/huggre/c5185df916ca00d2e1d12943a9d9d03a
def getNewIndex():
config = configparser.ConfigParser()
config.read('let_there_be_light.ini')
oldIndex = config.getint('IndexCounter', 'addrIndexCount')
newIndex = oldIndex +1
config.set('IndexCounter', 'addrIndexCount', str(newIndex))
with open('let_there_be_light.ini', 'w') as configfile:
config.write(configfile)
return(newIndex)
# Define some variables
lightbalance = 0
balcheckcount = 0
lightstatus = False
addrfound = False
transFound = False
# The price of the service in USD pr. minute. Change at will
lightprice_USD = 0.01
# Function that returns next index used by the generateNewAddress function
addrIndex = getNewIndex()
# Generate new payment address
addr = generateNewAddress(addrIndex)
# Display price in GUI
displayprice()
# Display payment status in GUI
updatePaymentStatus("Waiting for new transactions")
# Main loop that executes every 1 second
def maintask(balcheckcount, lightbalance, lightstatus, transFound, addr, addrIndex):
# Check for new funds and add to lightbalance when found.
if balcheckcount == 30:
# Check if address has any transactions
if transFound == False:
transFound = getTransExist(addr)
if transFound == True:
showXBM()
updatePaymentStatus("New transaction found, please wait while transaction is confirmed")
# If new transactions has been found, check for positive balance and add to lightbalance
if transFound == True:
balance = checkbalance(addr)
if int(balance) > 0:
lightbalance = lightbalance + int(((balance/1000000) * 60) / (getLightPriceIOTA()))
addrIndex = getNewIndex()
addr = generateNewAddress(addrIndex)
updatePaymentStatus("Waiting for new transactions")
transFound = False
balcheckcount = 0
# Manage light balance and light ON/OFF
if lightbalance > 0:
if lightstatus == False:
statusText.config(text="Light is ON")
lightstatus=True
lightbalance = lightbalance -1
else:
if lightstatus == True:
statusText.config(text="Light is OFF")
lightstatus=False
# Print remaining light balance
strlightbalance = datetime.timedelta(seconds=lightbalance)
timeText.config(text=strlightbalance)
# Increase balance check counter
balcheckcount = balcheckcount +1
# Update progress bar
mpb["value"] = balcheckcount
# Run maintask function after 1 sec.
root.after(1000, maintask, balcheckcount, lightbalance, lightstatus, transFound, addr, addrIndex)
# Run maintask function after 1 sec.
root.after(1000, maintask, balcheckcount, lightbalance, lightstatus, transFound, addr, addrIndex)
root.mainloop()
Useful Links
- Articles: https://python-commandments.org/
- Python shell: https://bsdnerds.org/learn-python/
- Tutorial: https://pythonprogramminglanguage.com/