Advertisement
Guest User

brizzi relay buzzer

a guest
Jul 22nd, 2019
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.59 KB | None | 0 0
  1. import logging
  2. import binascii
  3. import time
  4. import os
  5. # from smartcard.System import readers
  6. from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
  7. from smartcard.CardConnection import CardConnection
  8. from smartcard.CardMonitoring import CardMonitor, CardObserver
  9. from smartcard.util import *
  10. # from smartcard.scard import *
  11.  
  12. # gpio
  13. import RPi.GPIO as GPIO
  14.  
  15. '''
  16. https://stackoverflow.com/questions/7621897/python-logging-module-globally
  17. '''
  18.  
  19.  
  20. def setup_custom_logger(name):
  21. formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(module)s - %(message)s')
  22.  
  23. handler = logging.StreamHandler()
  24. handler.setFormatter(formatter)
  25.  
  26. logger = logging.getLogger(name)
  27. logger.setLevel(logging.DEBUG)
  28. logger.addHandler(handler)
  29. return logger
  30.  
  31. SOUND_FILE = "/home/pi/ok.wav"
  32.  
  33. '''
  34. main logger
  35. '''
  36. LOGGER_MAIN = setup_custom_logger("brizzi_root")
  37. GPIO_CONTROL_MAIN = None
  38.  
  39.  
  40. class GPIOControl:
  41. # pin definition
  42. pin_buzzer = 21
  43. pin_gate = 20
  44.  
  45. def __init__(self):
  46. try:
  47. self.initialize = False
  48.  
  49. GPIO.setwarnings(False)
  50. GPIO.setmode(GPIO.BCM)
  51.  
  52. # setup pin
  53. GPIO.setup(self.pin_buzzer, GPIO.OUT)
  54. GPIO.output(self.pin_buzzer, GPIO.HIGH)
  55. GPIO.setup(self.pin_gate, GPIO.OUT)
  56. GPIO.output(self.pin_gate, GPIO.HIGH)
  57.  
  58. self.initialize = True
  59. except Exception as err:
  60. pass
  61. self.initialize = False
  62.  
  63. # cleanup gpio
  64. def gpio_cleanup(self):
  65. try:
  66. GPIO.cleanup()
  67. except:
  68. pass
  69.  
  70. # buzzer on off
  71. def buzzer_on_off(self, isOn=False):
  72. GPIO.output(self.pin_buzzer, isOn and GPIO.LOW and GPIO.HIGH)
  73.  
  74. # gate on off
  75. def gate_on_off(self, isOn=False):
  76. GPIO.output(self.pin_gate, isOn and GPIO.LOW or GPIO.HIGH)
  77.  
  78. def buzzer_beep(self, repeat_num=1, delay_ms=200):
  79. for i in range(0, repeat_num):
  80. self.buzzer_on_off()
  81. time.sleep(delay_ms / 1000)
  82. self.buzzer_on_off(True)
  83. time.sleep(delay_ms / 1000)
  84.  
  85. def gate_open(self, delay_close_ms=6000):
  86. self.gate_on_off(True)
  87. time.sleep(delay_close_ms / 1000)
  88. self.gate_on_off()
  89.  
  90. def gate_close(self):
  91. self.gate_on_off()
  92.  
  93.  
  94. class BrizziProcessor:
  95. '''
  96. pdu
  97. '''
  98. SAMCARD_SELECT = "00A4040C09A00000000000000011"
  99. SAMCARD_AUTH_KEY = "80B0000020{card_number:0<16.16}{card_uid:0<14.14}FF0000030080000000{key_card:0<16.16}"
  100. SAMCARD_CREATE_HASH = "80B4000058{:0<16.16}{:0<14.14}FF0000030080000000{:0<16.16}{:0<32.32}{:0<20.20}{:0<12.12}{:0<12.12}{:0<12.12}{:0>12.12}{:0<4.4}FFFFFFFF"
  101. PICC_SELECT_AID1 = "5A010000"
  102. PICC_GET_CARD_NUMBER = "BD00000000170000"
  103. PICC_GET_CARD_STATUS = "BD01000000200000"
  104. PICC_SELECT_AID3 = "5A030000"
  105. PICC_REQUEST_KEY_CARD = "0A00"
  106. PICC_GET_CARD_UID = "FFCA000000"
  107. PICC_CARD_AUTH = "AF{:0<32.32}"
  108. PICC_GET_LAST_TRANSACTION_DATE = "BD03000000070000"
  109. PICC_GET_BALANCE = "6C00"
  110. PICC_DEBET_BALANCE = "DC00{:0<6.6}00"
  111. PICC_COMMIT_TRANSACTION = "C7"
  112. PICC_ABORT_TRANSACTION = "A7"
  113. PDU_GET_MORE_DATA = "00C00000{:0>2X}"
  114. PICC_WRITE_LOG = "3B01000000200000{:0<16.16}{:0<16.16}{:0<6.6}{:0<6.6}EB{:0<6.6}{:0<6.6}{:0<6.6}"
  115. PICC_WRITE_LAST_TRANSACTION = "3D03000000070000{:0<6.6}{:0<8.8}"
  116.  
  117. def __init__(self, logger=None, sam_connection=None, picc_connection=None, mid="1122334455667788",
  118. tid="aabbccddeeff0000", debug_mode=True):
  119. try:
  120. # get setting
  121. self._logger = logger
  122. self._mid = mid
  123. self._tid = tid
  124. self.initialize = False
  125.  
  126. # check sam and picc connection object
  127. if sam_connection is None or picc_connection is None:
  128. self._logger and self._logger.error("SAM and or PICC connection is unavailable")
  129. else:
  130. # assign to sam and picc interface
  131. self._reader_picc_connection = picc_connection
  132. self._reader_sam_connection = sam_connection
  133.  
  134. # add observer
  135. if debug_mode:
  136. self._reader_observer = ConsoleCardConnectionObserver()
  137. self._reader_picc_connection.addObserver(self._reader_observer)
  138. self._reader_sam_connection.addObserver(self._reader_observer)
  139.  
  140. # connect to picc only to check the card present or not
  141. self.card_open_connection()
  142. self.sam_open_connection()
  143.  
  144. self._logger and self._logger.debug("Initializing picc and samcard reader OK")
  145.  
  146. self.initialize = True
  147. except Exception as err:
  148. pass
  149. self._logger and self._logger.error(err)
  150.  
  151. def __enter__(self):
  152. return self
  153.  
  154. def __exit__(self, exc_type, exc_val, exc_tb):
  155. # self.close_all_connection()
  156. return True
  157.  
  158. def close_all_connection(self):
  159. try:
  160. try:
  161. self._reader_picc_connection.disconnect()
  162. except:
  163. pass
  164.  
  165. try:
  166. self._reader_sam_connection.disconnect()
  167. except:
  168. pass
  169. except Exception as err:
  170. pass
  171. self._logger and self._logger.error(err)
  172.  
  173. def card_close_connection(self):
  174. try:
  175. self._reader_picc_connection.disconnect()
  176. except Exception as err:
  177. pass
  178. self._logger and self._logger.error(err)
  179.  
  180. def card_open_connection(self):
  181. try:
  182. self._reader_picc_connection.connect(CardConnection.T1_protocol)
  183. return True
  184. except Exception as err:
  185. pass
  186. self._logger and self._logger.error(err)
  187. return False
  188.  
  189. def sam_close_connection(self):
  190. try:
  191. self._reader_sam_connection.disconnect()
  192. except Exception as err:
  193. pass
  194. self._logger and self._logger.error(err)
  195.  
  196. def sam_open_connection(self):
  197. try:
  198. self._reader_sam_connection.connect()
  199. return True
  200. except Exception as err:
  201. pass
  202. self._logger and self._logger.error(err)
  203. return False
  204.  
  205. def send_apdu(self, apdu_text=None, to_sam=True):
  206. try:
  207. if to_sam:
  208. self._logger and self._logger.debug("Transmit to SAMCARD = {}".format(apdu_text))
  209. data, sw1, sw2 = self._reader_sam_connection.transmit(toBytes(apdu_text))
  210. else:
  211. self._logger and self._logger.debug("Transmit to PICC = {}".format(apdu_text))
  212. data, sw1, sw2 = self._reader_picc_connection.transmit(toBytes(apdu_text))
  213.  
  214. self._logger and self._logger.debug("[SW1SW2] : DATA = [%02X%02X] : %s" % (sw1, sw2, toHexString(data)))
  215. except Exception as err:
  216. pass
  217. self._logger and self._logger.error(err)
  218. data = sw1 = sw2 = None
  219.  
  220. return data, sw1, sw2
  221.  
  222. def sam_select(self):
  223. try:
  224. _, sw1, sw2 = self.send_apdu(self.SAMCARD_SELECT)
  225. select_result = sw1 == 0x90 and sw2 == 0
  226. except Exception as err:
  227. pass
  228. self._logger and self._logger.error(err)
  229. select_result = False
  230. return select_result
  231.  
  232. def card_select_aid1(self):
  233. try:
  234. data, sw1, sw2 = self.send_apdu(self.PICC_SELECT_AID1, False)
  235. select_result = sw1 == 0x90 and sw2 == 0 and data[0] == 0
  236. except Exception as err:
  237. pass
  238. self._logger and self._logger.error(err)
  239. select_result = False
  240. return select_result
  241.  
  242. def card_get_number(self):
  243. try:
  244. data, sw1, sw2 = self.send_apdu(self.PICC_GET_CARD_NUMBER, False)
  245. return toHexString(data[4:12], PACK)
  246. except Exception as err:
  247. pass
  248. self._logger and self._logger.error(err)
  249. return None
  250.  
  251. def card_get_status(self):
  252. try:
  253. data, sw1, sw2 = self.send_apdu(self.PICC_GET_CARD_STATUS, False)
  254. return data[4:6] == [0x61, 0x61]
  255. except Exception as err:
  256. pass
  257. self._logger and self._logger.error(err)
  258. return False
  259.  
  260. def card_select_aid3(self):
  261. try:
  262. data, sw1, sw2 = self.send_apdu(self.PICC_SELECT_AID3, False)
  263. select_result = sw1 == 0x90 and sw2 == 0 and data[0] == 0
  264. except Exception as err:
  265. pass
  266. self._logger and self._logger.error(err)
  267. select_result = False
  268.  
  269. return select_result
  270.  
  271. def card_request_key_card(self):
  272. try:
  273. data, sw1, sw2 = self.send_apdu(self.PICC_REQUEST_KEY_CARD, False)
  274. card_key = data[1:] + [sw1, sw2]
  275. return toHexString(card_key, PACK)
  276. except Exception as err:
  277. pass
  278. self._logger and self._logger.error(err)
  279. return None
  280.  
  281. def card_get_uid(self):
  282. try:
  283. data, sw1, sw2 = self.send_apdu(self.PICC_GET_CARD_UID, False)
  284. return toHexString(data, PACK)
  285. except Exception as err:
  286. pass
  287. self._logger and self._logger.error(err)
  288. return None
  289.  
  290. def pdu_get_more_data(self, data_len=0, to_sam=True):
  291. try:
  292. return self.send_apdu(self.PDU_GET_MORE_DATA.format(data_len), to_sam)
  293. except Exception as err:
  294. pass
  295. self._logger and self._logger.error(err)
  296. return None
  297.  
  298. def sam_authenticate_key(self, card_number_in, card_uid_in, key_card_in):
  299. try:
  300. random_key = None
  301. data, sw1, sw2 = self.send_apdu(
  302. self.SAMCARD_AUTH_KEY.format(card_number=card_number_in, card_uid=card_uid_in, key_card=key_card_in))
  303. if sw1 == 0x61:
  304. data, sw1, sw2 = self.pdu_get_more_data(sw2)
  305. if sw1 == 0x90 and sw2 == 0x00:
  306. random_key = toHexString(data[-16:], PACK)
  307. else:
  308. random_key = None
  309. except Exception as err:
  310. pass
  311. self._logger and self._logger.error(err)
  312. random_key = None
  313.  
  314. return random_key
  315.  
  316. def sam_create_hash(self, card_number_in, card_uid_in, card_random_number_in, debet_value, proc_code=808117,
  317. ref_number=36, batch_num=3):
  318. try:
  319. pdu_txt = self.SAMCARD_CREATE_HASH.format(card_number_in,
  320. card_uid_in,
  321. card_random_number_in,
  322. toHexString(toASCIIBytes(card_number_in), PACK),
  323. toHexString(
  324. toASCIIBytes("{:0<10}".format(int(float(debet_value) * 100))),
  325. PACK),
  326. toHexString(
  327. toASCIIBytes("{:0<12}".format(time.strftime("%d%m%y"))),
  328. PACK),
  329. toHexString(
  330. toASCIIBytes("{:0<12}".format(time.strftime("%H%M%I"))),
  331. PACK),
  332. toHexString(toASCIIBytes("{:0>6d}".format(proc_code)), PACK),
  333. toHexString(toASCIIBytes("{:0>6d}".format(ref_number)), PACK),
  334. toHexString(toASCIIBytes("{:0>2d}".format(batch_num)), PACK)
  335. )
  336. # print(pdu_txt)
  337.  
  338. data, sw1, sw2 = self.send_apdu(pdu_txt)
  339. hash_value = None
  340. if sw1 == 0x61:
  341. data, sw1, sw2 = self.pdu_get_more_data(sw2)
  342. if sw1 == 0x90 and sw2 == 0x00:
  343. hash_value = toHexString(data, PACK)
  344. else:
  345. hash_value = None
  346.  
  347. except Exception as err:
  348. pass
  349. self._logger and self._logger.error(err)
  350. hash_value = None
  351.  
  352. return hash_value
  353.  
  354. def card_authenticate(self, random_key_in):
  355. try:
  356. card_random_number = None
  357. data, sw1, sw2 = self.send_apdu(self.PICC_CARD_AUTH.format(random_key_in), False)
  358. if data[0] == 0x00:
  359. card_random_number = toHexString(data[1:9] + [sw1, sw2], PACK)
  360. else:
  361. card_random_number = None
  362. except Exception as err:
  363. pass
  364. self._logger and self._logger.error(err)
  365. card_random_number = None
  366.  
  367. return card_random_number
  368.  
  369. def card_get_last_transaction_date(self):
  370. try:
  371. last_trans_data = None, None
  372. data, sw1, sw2 = self.send_apdu(self.PICC_GET_LAST_TRANSACTION_DATE, False)
  373. if data[0] != 0x00:
  374. last_trans_data = None, None
  375. else:
  376. last_trans_data = time.strptime("{:02X}{:02X}{:02X}".format(data[1], data[2], data[3]),
  377. "%y%m%d"), int.from_bytes(data[4:] + [sw1, sw2], 'big')
  378.  
  379. except Exception as err:
  380. pass
  381. self._logger and self._logger.error(err)
  382. last_trans_data = None, None
  383.  
  384. return last_trans_data
  385.  
  386. def card_get_balance(self):
  387. try:
  388. data, sw1, sw2 = self.send_apdu(self.PICC_GET_BALANCE, False)
  389. balance = -2
  390. if data[0] == 0x00:
  391. balance = int.from_bytes(data[1:] + [sw1, sw2], 'little')
  392. except Exception as err:
  393. pass
  394. self._logger and self._logger.error(err)
  395. balance = -1
  396.  
  397. return balance
  398.  
  399. def card_debet_balance(self, debet_value=0):
  400. try:
  401. data, sw1, sw2 = self.send_apdu(
  402. self.PICC_DEBET_BALANCE.format(binascii.hexlify((debet_value).to_bytes(3, 'little')).decode()), False)
  403. debet_status = data[0] == 0x00 and sw1 == 0x90 and sw2 == 0x00
  404. except Exception as err:
  405. pass
  406. self._logger and self._logger.error(err)
  407. debet_status = False
  408.  
  409. return debet_status
  410.  
  411. def card_commit_transaction(self):
  412. try:
  413. data, sw1, sw2 = self.send_apdu(self.PICC_COMMIT_TRANSACTION, False)
  414. commit_result = data[0] == 0x00 and sw1 == 0x90 and sw2 == 0x00
  415. except Exception as err:
  416. pass
  417. self._logger and self._logger.error(err)
  418. commit_result = False
  419.  
  420. return commit_result
  421.  
  422. def cardAbortTransaction(self):
  423. try:
  424. data, sw1, sw2 = self.send_apdu(self.PICC_ABORT_TRANSACTION, False)
  425. abort_result = data[0] == 0x00 and sw1 == 0x90 and sw2 == 0x00
  426. except Exception as err:
  427. pass
  428. self._logger and self._logger.error(err)
  429. abort_result = False
  430.  
  431. return abort_result
  432.  
  433. def card_write_log(self, debet_value=0, balance_before=0, balance_after=0, mid=None, tid=None):
  434. try:
  435. pdu = self.PICC_WRITE_LOG.format(
  436. mid and mid or self._mid,
  437. tid and tid or self._tid,
  438. time.strftime("%y%m%d"),
  439. time.strftime("%H%M%I"),
  440. binascii.hexlify(debet_value.to_bytes(3, 'little')).decode(),
  441. binascii.hexlify(balance_before.to_bytes(3, 'little')).decode(),
  442. binascii.hexlify(balance_after.to_bytes(3, 'little')).decode()
  443. )
  444. # print(pdu)
  445. data, sw1, sw2 = self.send_apdu(pdu, False)
  446. result = data[0] == 0x00 and sw1 == 0x90 and sw2 == 0x00
  447. except Exception as err:
  448. pass
  449. self._logger and self._logger.error(err)
  450. result = False
  451.  
  452. return result
  453.  
  454. def card_write_last_transaction(self, last_trans_date, last_akum_debet, debet_value=0):
  455. try:
  456. akum_debet_total = debet_value
  457. if last_trans_date.tm_mon == int(time.strftime("%m")):
  458. akum_debet_total += last_akum_debet
  459. data, sw1, sw2 = self.send_apdu(self.PICC_WRITE_LAST_TRANSACTION.format(
  460. time.strftime("%y%m%d"),
  461. binascii.hexlify((akum_debet_total).to_bytes(4, 'big')).decode()
  462. ), False)
  463. result = data[0] == 0x00 and sw1 == 0x90 and sw2 == 0x00
  464. except Exception as err:
  465. pass
  466. self._logger and self._logger.error(err)
  467. result = False
  468.  
  469. return result
  470.  
  471. def transaction_debet_card(self, debet_amount=0, mid=None, tid=None, proc_code=808117, ref_number=1,
  472. batch_number=1):
  473. global transaction_result
  474. try:
  475. transaction_result = {
  476. 'status': False,
  477. 'card_number': "",
  478. 'transaction_date': "0000-00-00",
  479. 'transaction_time': "00:00:00",
  480. 'balance': 0,
  481. 'amount': 0,
  482. 'ref_number': 0,
  483. 'batch_number': 0,
  484. 'mid': '',
  485. 'tid': '',
  486. 'hash': '00000000'
  487. }
  488.  
  489. # step 1
  490. transaction_result.update(
  491. {
  492. 'transaction_date': time.strftime("%Y-%m-%d"),
  493. 'transaction_time': time.strftime("%H:%M:%I"),
  494. 'amount': debet_amount,
  495. 'mid': mid and mid or self._mid,
  496. 'tid': tid and tid or self._tid,
  497. 'ref_number': ref_number,
  498. 'batch_number': batch_number
  499. }
  500. )
  501.  
  502. # open connection
  503. if self.card_open_connection():
  504. if self.sam_select():
  505. # step 2
  506. if self.card_select_aid1():
  507. # step 3
  508. card_number = self.card_get_number()
  509. transaction_result['card_number'] = card_number
  510. if card_number is not None:
  511. # step 4
  512. if self.card_get_status():
  513. # step 5
  514. if self.card_select_aid3():
  515. # step 6
  516. card_key = self.card_request_key_card()
  517. if card_key is not None:
  518. # step 7
  519. card_uid = self.card_get_uid()
  520. if card_uid is not None:
  521.  
  522. # step 8
  523. sam_random_key = self.sam_authenticate_key(card_number, card_uid, card_key)
  524. if sam_random_key is not None:
  525. # step 9
  526. card_random_number = self.card_authenticate(sam_random_key)
  527. if card_random_number is not None:
  528. # step 10
  529. last_trans_date, last_trans_akum_debet = self.card_get_last_transaction_date()
  530. if last_trans_date is not None and last_trans_akum_debet is not None:
  531. # step 11
  532. card_balance = self.card_get_balance()
  533. transaction_result['balance'] = card_balance
  534. if card_balance >= 0:
  535. # step 12
  536. if self.card_debet_balance(debet_amount):
  537. # step 13
  538. sam_hash = self.sam_create_hash(card_number, card_uid,
  539. card_random_number,
  540. debet_amount, proc_code,
  541. ref_number,
  542. batch_number)
  543. transaction_result['hash'] = sam_hash
  544. if sam_hash is not None:
  545. # step 14
  546. if self.card_write_log(debet_amount, card_balance,
  547. card_balance - debet_amount,
  548. transaction_result['mid'],
  549. transaction_result['tid']):
  550. # step 15
  551. if self.card_write_last_transaction(
  552. last_trans_date, last_trans_akum_debet,
  553. debet_amount):
  554. # step 16
  555. if self.card_commit_transaction():
  556. transaction_result['status'] = True
  557. else:
  558. self.cardAbortTransaction()
  559. else:
  560. self.cardAbortTransaction()
  561. else:
  562. self.cardAbortTransaction()
  563. else:
  564. self.cardAbortTransaction()
  565. else:
  566. self.cardAbortTransaction()
  567. # self.card_close_connection()
  568. except Exception as err:
  569. pass
  570. self._logger and self._logger.error(err)
  571. transaction_result['status'] = False
  572. # self.card_close_connection()
  573.  
  574. return transaction_result
  575.  
  576.  
  577. class BrizziCardObserver(CardObserver):
  578. """Card observer for brizzi
  579. """
  580.  
  581. # sam card
  582. sam_connection = None
  583. sam_uid = "3B6800000073C84013009000"
  584.  
  585. def update(self, observable, actions):
  586. """
  587. When card is insert or removed, it goes here
  588. :param observable:
  589. :param actions:
  590. """
  591. (addedcards, removedcards) = actions
  592. '''
  593. for card in addedcards:
  594. print(card.createConnection().getReader())
  595. print("+Inserted: ", toHexString(card.atr))
  596. for card in removedcards:
  597. print("-Removed: ", toHexString(card.atr))
  598. '''
  599.  
  600. # get sam connection
  601. for card in addedcards:
  602. atrx = toHexString(card.atr, PACK)
  603. LOGGER_MAIN.debug(atrx)
  604. if atrx == self.sam_uid:
  605. if self.sam_connection is None:
  606. self.sam_connection = card.createConnection()
  607. else:
  608. picc_connection = card.createConnection()
  609. # picc_connection.connect()
  610. # data, sw1, sw2 = picc_connection.transmit(toBytes("FF00480000"))
  611. # data, sw1, sw2 = picc_connection.transmit(toBytes("E0000028010F"))
  612. # firmware = toBytes("E000002900")
  613. # retx = picc_connection.control(SCARD_CTL_CODE(3500), firmware)
  614. # LOGGER_MAIN.debug(retx)
  615. with BrizziProcessor(sam_connection=self.sam_connection, picc_connection=picc_connection,
  616. debug_mode=False) as conn_obj:
  617. if conn_obj.initialize:
  618. resultx = conn_obj.transaction_debet_card(1)
  619. LOGGER_MAIN.debug(resultx)
  620. if resultx['status']:
  621. os.system("/usr/bin/aplay -N " + SOUND_FILE )
  622. GPIO_CONTROL_MAIN.buzzer_beep(1)
  623. GPIO_CONTROL_MAIN.gate_open()
  624. else:
  625. GPIO_CONTROL_MAIN.buzzer_beep(3)
  626. GPIO_CONTROL_MAIN.gate_close()
  627.  
  628.  
  629. def main():
  630. try:
  631. # initial screen
  632. LOGGER_MAIN.info("System ready....")
  633.  
  634. global GPIO_CONTROL_MAIN
  635. GPIO_CONTROL_MAIN = GPIOControl()
  636. LOGGER_MAIN.debug("GPIO init success? {}".format(GPIO_CONTROL_MAIN.initialize)
  637.  
  638. # card monitor
  639. cardmonitor = CardMonitor()
  640. cardobserver = BrizziCardObserver()
  641. cardmonitor.addObserver(cardobserver)
  642.  
  643. # eternal loop
  644. try:
  645. while True:
  646. time.sleep(1)
  647. except Exception as err:
  648. pass
  649.  
  650. # delete observer
  651. cardmonitor.deleteObserver(cardobserver)
  652.  
  653. import sys
  654.  
  655. if 'win32' == sys.platform:
  656. print('press Enter to continue')
  657. sys.stdin.read(1)
  658. except Exception as err:
  659. pass
  660.  
  661. GPIO_CONTROL_MAIN.gpio_cleanup()
  662.  
  663.  
  664. if __name__ == '__main__':
  665. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement