使用Python整合物理设备与IOTA缠结 – IOTA借记卡,第2部分

使用Python整合物理设备与IOTA缠结 – IOTA借记卡,第2部分

项目介绍

这是该系列初学者教程的第7部分,目的是将物理设备与IOTA协议集成起来。在第7部教程中,我们将继续尝试使用基于IOTA的解决方案来复制传统的法币借记卡支付解决方案。

第7部教程是第6部教程的延续。在第6部教程中我们完成了“IOTA借记卡”信息的读取和写入,在第7部教程中,我们将构建一个简单的LED电路来代表提供服务的物理设备,我们可以使用IOTA借记卡来向这个物理设备购买服务并支付服务费用。

如果您感兴趣的话,可以浏览一下本系列教程的前6部分:

用例介绍

现在,我们已经配置好了全新的IOTA借记卡,并且可以按照上一个教程中描述到的那样使用它了,我们将把注意力转移到如何使用该卡来支付服务费用上。在上一个教程中,我使用了酒店前台的咖啡机或游泳池储物柜作为整合IOTA借记卡支付解决方案的示例。但老实说,像这样的支付解决方案可以集成到任何能够收取服务费用的机器或设备中,比如自动售货机、珯琥机、停车计费器或酒店房间的冰箱。客人甚至可以使用他的IOTA借记卡向酒店餐厅支付晚餐费或购买酒店礼品店的物品,这种解决方案避免了酒店业主被Visa或任何其他第三方支付服务提供商收取额外的费用。这种可能性基本上是无限的。

我们将使用第一个教程中的“IOTA冰箱支付系统”的简化版本来代表本教程中提供服务并收取服务费的物理设备。本教程的主要目的是使用IOTA借记卡发送有价值的交易,因此我们将从第一个教程中删除所有不需要的组件,线路连接和代码,因为本应用场景中并不需要它们。

关于价值交易

价值交易是在IOTA地址之间传输IOTA Token的IOTA交易,而在第五个教程中,我们则是将非价值交易发送到Tangle。一个典型的价值交易实际上由打包在bundle中的多个交易组成。一个bundle包含三种类型的交易:

输入TXs

从交易发送者的IOTA地址中扣除价值的负值交易

输出TXs

向交易接收者的IOTA地址中增加价值的正值交易

未花费TXs

将交易发送者的IOTA地址上剩余的价值转移到同一个种子中另一个新地址上的零和交易。这种交易的目的是为了防止将来从已经使用过的地址上支出。

虽然这听起来相当复杂,但好消息是我们不必担心设置bundle的复杂性,这一切都交由PyOTA库来处理。

注意!

请注意,当bundle中的所有交易都执行过后,现有IOTA的总供应量并没有发生改变,只有IOTA Token的所有权地址发生了改变。这当然是IOTA协议的基本属性,必须始终强制执行。

电路连接

现在,让我们看看如何连接这个项目中使用的电路。如前所述,本教程的电路是第一个教程中所用电路的简化版本。我将从电路中移除继电器和电池,因为不需要它们来证明我们在本教程中要做的事情。如果您希望将它们包含在您自己的项目版本中,也是可以的。Python代码在使用或不使用它们的情况下都可以很好地工作。

关于如何设置MFRC522 RFID读写器的详细信息,请参阅第五个教程(如果您之前尚未按照教程5操作过的话)。

有关连接LED的信息,请参阅第一个教程。如果你想简化LED电路,可以按照本文所讲的操作跳过继电器和电池,直接将LED连接到树莓派的GIO pin。注意,你仍然需要在电路中使用电阻器,否则可能会使LED过载并损坏。

使用Python整合物理设备与IOTA缠结 – IOTA借记卡,第2部分

注意!

由于教程1中用于GROUND(接地)的pin 6现在被MFRC522占用,我选择使用pin 9作为LED的GROUND。如果你使用面包板的话,还可以将MFRC522和LED的接地连接到面包板上的公共接地。

使用Python整合物理设备与IOTA缠结 – IOTA借记卡,第2部分

树莓派pin布局

Python代码

本教程的主要目的是使用IOTA借记卡为物理设备提供的服务支付费用。在我的例子中,用LED灯来表示物理设备,LED闪烁时表示它正在提供服务。在我们开始编写代码之前,让我们先快速了解一下代码背后的逻辑以及它是如何工作的。

  • python脚本首先检查服务费接收者(酒店所有者)IOTA地址上的余额,这样我们就有了一个基准来监控该地址上是否有新的收入。
  • 接下来,python脚本会显示一条欢迎消息,询问顾客要购买多少服务(LED闪烁次数)。在我的例子中,我把兑换比率设置为1 IOTA可兑换LED闪烁1次。
  • 接下来,会要求顾客将他的IOTA借记卡靠近RFID阅读器。RFID阅读器检测到借记卡后,Python脚本就会从卡上读取IOTA种子。
  • 接下来,我们检查借记卡种子上是否有足够的资金来支付顾客订购的服务(LED闪烁次数)。
  • 如果借记卡上的IOTA足够购买对应的服务,我们就定义一个新交易然后将其发送到Tangle。
  • 接下来,我们开始监控接收方(酒店所有者)IOTA地址上的余额变化,看看是否有新资金被添加,即检查一下上一步中的交易是否已经确认。
  • 最后,当交易确认后,物理设备就开始为顾客提供其所购买的服务(LED开始闪烁)。

注意!

如果您系统的了解过本系列教程的话,那么您就会意识到,当酒店所有者想要从接收服务费的地址上支出任何资金时,就会出现地址重用问题。在教程4中,我们使用带有二维码的LCD显示屏解决了地址重用问题,这是一种方便的方式,用户可以使用移动版IOTA钱包进行支付。现在我们使用IOTA借记卡进行支付,用户不需要知道使用哪个接收地址支付LED,这都可以在幕后管理。如果您想在本项目中实现地址重用问题的解决方案,请使用与第四个教程中类似的方法,不使用LCD。

# Imports some required libraries
import iota
from iota import Address
import RPi.GPIO as GPIO
import MFRC522
import signal
import time

# Setup O/I PIN's
LEDPIN=12
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(LEDPIN,GPIO.OUT)
GPIO.output(LEDPIN,GPIO.LOW)

# URL to IOTA fullnode used when interacting with the Tangle
iotaNode = "https://field.deviota.com:443"
api = iota.Iota(iotaNode, "")

# Hotel owner recieving address, replace with your own recieving address
hotel_address = b'IKNETWIYVUSILFMIBYEBUMAJOGHU9EEEQLFAVCZLPJWJGYOTWBKKIAFBEUMFYMNFUOQVBJJFFWFISMLGZZTJMHEGFY'

# Some variables to control program flow
continue_reading = True
transaction_confirmed = False

# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
global continue_reading
print "Ctrl+C captured, ending read."
continue_reading = False
GPIO.cleanup()

# Function that reads the seed stored on the IOTA debit card
def read_seed():

seed = ""
seed = seed + read_block(8)
seed = seed + read_block(9)
seed = seed + read_block(10)
seed = seed + read_block(12)
seed = seed + read_block(13)
seed = seed + read_block(14)

# Return the first 81 characters of the retrieved seed
return seed[0:81]

# Function to read single block from RFID tag
def read_block(blockID):

status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, blockID, key, uid)

if status == MIFAREReader.MI_OK:

str_data = ""
int_data=(MIFAREReader.MFRC522_Read(blockID))
for number in int_data:
str_data = str_data + chr(number)
return str_data

else:
print "Authentication error"

# Function for checking address balance
def checkbalance(hotel_address):

address = Address(hotel_address)
gb_result = api.get_balances([address])
balance = gb_result['balances']
return (balance[0])

# Function that blinks the LED
def blinkLED(blinks):
for x in range(blinks):
print("LED ON")
GPIO.output(LEDPIN,GPIO.HIGH)
time.sleep(1)
print("LED OFF")
GPIO.output(LEDPIN,GPIO.LOW)
time.sleep(1)

# Function that displays welcome message and returns the number of blinks ordered
def showWelcome():
print("\nWelcome to the LED blink service")
print("\nThe price of the service is 1 IOTA for 1 blink")
ans=input("\nHow many blinks would you like to purchase? :")
print("\nHold your IOTA debit card close to ")
print("the reader to pay for the service...")
print("Press Ctrl+C to exit...")
return int(ans)

# Get hotel owner address balance at startup
print("\n Getting startup balance... Please wait...")
currentbalance = checkbalance(hotel_address)
lastbalance = currentbalance

# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# Show welcome message
blinks = showWelcome()

# This loop keeps checking for near by RFID tags. If one is found it will get the UID and authenticate
while continue_reading:

# Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

# If a card is found
if status == MIFAREReader.MI_OK:
print "Card detected"

# Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()

# If we have the UID, continue
if status == MIFAREReader.MI_OK:

# Print UID
print "Card read UID: %s,%s,%s,%s" % (uid[0], uid[1], uid[2], uid[3])

# This is the default key for authentication
key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]

# Select the scanned tag
MIFAREReader.MFRC522_SelectTag(uid)

# Get seed from IOTA debit card
SeedSender=read_seed()

# Stop reading/writing to RFID tag
MIFAREReader.MFRC522_StopCrypto1()

# Create PyOTA object using seed from IOTA debit card
api = iota.Iota(iotaNode, seed=SeedSender)

print("\nChecking for available funds... Please wait...")

# Get available funds from IOTA debit card seed
card_balance = api.get_account_data(start=0, stop=None)

balance = card_balance['balance']

# Check if enough funds to pay for service
if balance < blinks:
print("Not enough funds available on IOTA debit card")
exit()

# Create new transaction
tx1 = iota.ProposedTransaction( address = iota.Address(hotel_address), message = None, tag = iota.Tag(b'HOTEL9IOTA'), value = blinks)

# Send transaction to tangle
print("\nSending transaction... Please wait...")
SentBundle = api.send_transfer(depth=3,transfers=[tx1], inputs=None, change_address=None, min_weight_magnitude=14, security_level=2)

# Display transaction sent confirmation message
print("\nTransaction sent... Please wait while transaction is confirmed...")

# Loop executes every 10 seconds to checks if transaction is confirmed
while transaction_confirmed == False:
print("\nChecking balance to see if transaction is confirmed...")
currentbalance = checkbalance(hotel_address)
if currentbalance > lastbalance:
print("\nTransaction is confirmed")
blinkLED(blinks)
transaction_confirmed = True
lastbalance = currentbalance
showWelcome()
time.sleep(10)

您可以从这里下载到这段源代码。

运行项目

要运行该项目,首先复制上文中提供的代码,然后进入树莓派上安装MFRC522-python库的文件夹中,在该文件夹中创建一个文本文件,将前面的Python代码粘贴进去并保存,最后将该文本文件重命名为iota_debit_card_pay.py。

要执行该程序,只需启动一个新的终端窗口,进入到iota_debit_card_pay.py文件的保存位置并输入:

python iota_debit_card_pay.py

您现在应该可以在终端窗口中看到正在执行的代码,询问你要购买的服务时长(LED灯闪烁的次数)。

对上一个教程的进一步改进

既然我们已经基本了解了如何使用PyOTA来创建价值交易,那么在上一个教程(教程6)中添加一个新选项应该非常简单,使我们可以将资金从酒店所有者的种子转移到IOTA借记卡的种子上(顾客支付法币,然后使用酒店的帐户给顾客的IOTA借记卡充值)。您可能还记得,我们有生成一个新地址的功能,当将新资金转移到IOTA借记卡时会用到这个新地址。现在的问题是如何逆转本教程中的支付流程,即我们不是将价值交易从IOTA借记卡种子发送到酒店所有者的IOTA地址,而是将酒店所有者种子的价值交易发送到IOTA借记卡的地址上。在上一个教程的代码中实现这个功能应该是一个很好的练习,我将把它留给读者。

下一步是什么?

您可能已经注意到,使用IOTA借记卡付款时,系统不会要求您提供任何授权或凭据。虽然在某些用例中这可能没问题,但是在其他用例中就可能不太合适。想象一下,如果你丢失了IOTA借记卡,然后它被一个坏人捡走了,没有任何保护机制的话,就无法阻止他使用你的卡进行消费。在下一个教程中,我们将通过为IOTA借记卡实施PIN码授权机制来解决这个问题。敬请关注…

捐赠作者

如果你喜欢本教程并希望作者能够继续创作,请随时向作者的IOTA地址捐赠一小笔捐款。作者的IOTA捐助地址:IKNETWIYVUSILFMIBYEBUMAJOGHU9EEEQLFAVCZLPJWJGYOTWBKKIAFBEUMFYMNFUOQVBJJFFWFISMLGZZTJMHEGFY

 

原文链接:https://medium.com/coinmonks/integrating-physical-devices-with-iota-the-iota-debit-card-part-2-1f073060ae1d

inhuman

专栏作者:inhuman

个人简介:我共发表了 189 篇文章,总计被阅读了144,014 次,共获得了 1,612 个赞。

作者邮箱 作者主页 Ta的文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注