def process_handover_request_message(self, records): self.ho_server_processing = True clear_raw_mode() print("\nHandoverServer - request received: " + str(records)) carrier = None hs = ndef.HandoverSelectRecord('1.4') sel = [hs] found = False for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue print("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": print("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: print("URI Identifier Code 'None' not seen") continue uri = carrier.data[1:].decode("utf-8") print("Received DPP URI: " + uri) data = wpas_get_nfc_uri(start_listen=False) print("Own URI (pre-processing): %s" % data) res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: print("DPP handover request processing failed") continue found = True self.received_carrier = carrier wpas = wpas_connect() if wpas is None: continue global own_id data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue print("Own URI (post-processing): %s" % data) uri = ndef.UriRecord(data) print("Own bootstrapping NFC URI record: " + str(uri)) info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None: print("No channel negotiated over NFC - use channel 1") freq = 2412 res = wpas.request("DPP_LISTEN %d" % freq) if "OK" not in res: print("Failed to start DPP listen") break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) print("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break summary("Sending handover select: " + str(sel)) self.success = True return sel
def beam(llc): snep_client = nfc.snep.SnepClient(llc) snep_client.put_records([ndef.UriRecord('http://nfcpy.org')])
def dpp_handover_client(llc): uri = wpas_get_nfc_uri(start_listen=False) uri = ndef.UriRecord(uri) print("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) hr = ndef.HandoverRequestRecord(version="1.4", crn=os.urandom(2)) hr.add_alternative_carrier('active', carrier.name) message = [hr, carrier] print("NFC Handover Request message for DPP: " + str(message)) client = nfc.handover.HandoverClient(llc) try: summary("Trying to initiate NFC connection handover") client.connect() summary("Connected for handover") except nfc.llcp.ConnectRefused: summary("Handover connection refused") client.close() return except Exception as e: summary("Other exception: " + str(e)) client.close() return summary("Sending handover request") if not client.send_records(message): summary("Failed to send handover request") client.close() return summary("Receiving handover response") message = client.recv_records(timeout=3.0) if message is None: summary("No response received") client.close() return print("Received message: " + str(message)) if len(message) < 1 or \ not isinstance(message[0], ndef.HandoverSelectRecord): summary("Response was not Hs - received: " + message.type) client.close() return print("Received message") print("alternative carriers: " + str(message[0].alternative_carriers)) for carrier in message: if isinstance(carrier, ndef.HandoverSelectRecord): continue print("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": if len(carrier.data) == 0 or carrier.data[0] != 0: print("URI Identifier Code 'None' not seen") continue print("DPP carrier type match - send to wpa_supplicant") uri = carrier.data[1:].decode("utf-8") print("DPP URI: " + uri) res = wpas_report_handover_sel(uri) if res is None or "FAIL" in res: summary("DPP handover report rejected") break success_report("DPP handover reported successfully (initiator)") print("peer_id=" + res) peer_id = int(res) # TODO: Single Configurator instance wpas = wpas_connect() if wpas is None: break res = wpas.request("DPP_CONFIGURATOR_ADD") if "FAIL" in res: print("Failed to initiate Configurator") break conf_id = int(res) global own_id print("Initiate DPP authentication") cmd = "DPP_AUTH_INIT peer=%d own=%d conf=sta-dpp configurator=%d" % (peer_id, own_id, conf_id) res = wpas.request(cmd) if "FAIL" in res: print("Failed to initiate DPP authentication") break print("Remove peer") client.close() print("Done with handover") global only_one if only_one: print("only_one -> stop loop") global continue_loop continue_loop = False global no_wait if no_wait: print("Trying to exit..") global terminate_now terminate_now = True print("Returning from dpp_handover_client")
def process_handover_request_message(self, records): handover = self.handover self.ho_server_processing = True global in_raw_mode was_in_raw_mode = in_raw_mode clear_raw_mode() if was_in_raw_mode: print("\n") summary("HandoverServer - request received: " + str(records)) for carrier in records: if not isinstance(carrier, ndef.HandoverRequestRecord): continue if carrier.collision_resolution_number: handover.peer_crn = carrier.collision_resolution_number summary("peer_crn: %d" % handover.peer_crn) if handover.my_crn is None and handover.my_crn_ready: summary("Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values") for i in range(10): if handover.my_crn is not None: break time.sleep(0.01) if handover.my_crn is not None: summary("my_crn: %d" % handover.my_crn) if handover.my_crn is not None and handover.peer_crn is not None: if handover.my_crn == handover.peer_crn: summary("Same crn used - automatic collision resolution failed") # TODO: Should generate a new Handover Request message return '' if ((handover.my_crn & 1) == (handover.peer_crn & 1) and \ handover.my_crn > handover.peer_crn) or \ ((handover.my_crn & 1) != (handover.peer_crn & 1) and \ handover.my_crn < handover.peer_crn): summary("I'm the Handover Selector Device") handover.i_m_selector = True else: summary("Peer is the Handover Selector device") summary("Ignore the received request.") return '' hs = ndef.HandoverSelectRecord('1.4') sel = [hs] found = False for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: summary("URI Identifier Code 'None' not seen", color=C_RED) continue uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) global test_uri, test_alt_uri if test_uri: summary("TEST MODE: Using specified URI") data = test_sel_uri if test_sel_uri else test_uri elif handover.alt_proposal and handover.altchanlist: summary("Use alternative channel list while processing alternative proposal from peer") data = wpas_get_nfc_uri(start_listen=False, chan_override=handover.altchanlist, pick_channel=True) else: data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) summary("Own URI (pre-processing): %s" % data) if test_uri: summary("TEST MODE: Fake processing") res = "OK" data += " [%s]" % uri else: res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: summary("DPP handover request processing failed", color=C_RED) if handover.altchanlist: data = wpas_get_nfc_uri(start_listen=False, chan_override=handover.altchanlist) summary("Own URI (try another channel list): %s" % data) continue if test_alt_uri: summary("TEST MODE: Reject initial proposal") continue found = True if not test_uri: wpas = wpas_connect() if wpas is None: continue global own_id data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue summary("Own URI (post-processing): %s" % data) handover.my_uri = data handover.peer_uri = uri uri = ndef.UriRecord(data) summary("Own bootstrapping NFC URI record: " + str(uri)) if not test_uri: info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None or freq == 0: summary("No channel negotiated over NFC - use channel 6") freq = 2437 else: summary("Negotiated channel: %d MHz" % freq) if not dpp_start_listen(wpas, freq): break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) summary("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") handover.terminate_on_hs_send_completion = True self.success = True handover.hs_sent = True handover.i_m_selector = True elif handover.no_alt_proposal: summary("Do not try alternative proposal anymore - handover failed", color=C_RED) handover.hs_sent = True else: summary("Try to initiate with alternative parameters") handover.try_own = True handover.hs_sent = False handover.no_alt_proposal = True if handover.client_thread: handover.start_client_alt = True else: handover.client_thread = threading.Thread(target=llcp_worker, args=(self.llc, True)) handover.client_thread.start() return sel
def set_uri_record(self, data): return ndef.UriRecord(data)
def beam_user(llc): snep_client = nfc.snep.SnepClient(llc) snep_client.put_records( [ndef.UriRecord("time://free?param1=test$param2=test2")])
def run_dpp_handover_client(handover, alt=False): chan_override = None if alt: chan_override = handover.altchanlist handover.alt_proposal_used = True global test_uri, test_alt_uri if test_uri: summary("TEST MODE: Using specified URI (alt=%s)" % str(alt)) uri = test_alt_uri if alt else test_uri else: uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override) if uri is None: summary("Cannot start handover client - no bootstrap URI available", color=C_RED) return handover.my_uri = uri uri = ndef.UriRecord(uri) summary("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) global test_crn if test_crn: prev, = struct.unpack('>H', test_crn) summary("TEST MODE: Use specified crn %d" % prev) crn = test_crn test_crn = struct.pack('>H', prev + 0x10) else: crn = os.urandom(2) hr = ndef.HandoverRequestRecord(version="1.4", crn=crn) hr.add_alternative_carrier('active', carrier.name) message = [hr, carrier] summary("NFC Handover Request message for DPP: " + str(message)) if handover.peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") return if handover.client: summary("Use already started handover client") client = handover.client else: summary("Start handover client") client = HandoverClient(handover, handover.llc) try: summary("Trying to initiate NFC connection handover") client.connect() summary("Connected for handover") except nfc.llcp.ConnectRefused: summary("Handover connection refused") client.close() return except Exception as e: summary("Other exception: " + str(e)) client.close() return handover.client = client if handover.peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") return summary("Sending handover request") handover.my_crn_ready = True if not client.send_records(message): handover.my_crn_ready = False summary("Failed to send handover request", color=C_RED) run_client_alt(handover, alt) return handover.my_crn, = struct.unpack('>H', crn) summary("Receiving handover response") try: start = time.time() message = client.recv_records(timeout=3.0) end = time.time() summary("Received {} record(s) in {} seconds".format(len(message) if message is not None else -1, end - start)) except Exception as e: # This is fine if we are the handover selector if handover.hs_sent: summary("Client receive failed as expected since I'm the handover server: %s" % str(e)) elif handover.alt_proposal_used and not alt: summary("Client received failed for initial proposal as expected since alternative proposal was also used: %s" % str(e)) else: summary("Client receive failed: %s" % str(e), color=C_RED) message = None if message is None: if handover.hs_sent: summary("No response received as expected since I'm the handover server") elif handover.alt_proposal_used and not alt: summary("No response received for initial proposal as expected since alternative proposal was also used") elif handover.try_own and not alt: summary("No response received for initial proposal as expected since alternative proposal will also be sent") else: summary("No response received", color=C_RED) run_client_alt(handover, alt) return summary("Received message: " + str(message)) if len(message) < 1 or \ not isinstance(message[0], ndef.HandoverSelectRecord): summary("Response was not Hs - received: " + message.type) return summary("Received handover select message") summary("alternative carriers: " + str(message[0].alternative_carriers)) if handover.i_m_selector: summary("Ignore the received select since I'm the handover selector") run_client_alt(handover, alt) return if handover.alt_proposal_used and not alt: summary("Ignore received handover select for the initial proposal since alternative proposal was sent") client.close() return dpp_found = False for carrier in message: if isinstance(carrier, ndef.HandoverSelectRecord): continue summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": if len(carrier.data) == 0 or carrier.data[0] != 0: summary("URI Identifier Code 'None' not seen", color=C_RED) continue summary("DPP carrier type match - send to wpa_supplicant") dpp_found = True uri = carrier.data[1:].decode("utf-8") summary("DPP URI: " + uri) handover.peer_uri = uri if test_uri: summary("TEST MODE: Fake processing") break res = wpas_report_handover_sel(uri) if res is None or "FAIL" in res: summary("DPP handover report rejected", color=C_RED) break success_report("DPP handover reported successfully (initiator)") summary("peer_id=" + res) peer_id = int(res) wpas = wpas_connect() if wpas is None: break global enrollee_only global config_params if enrollee_only: extra = " role=enrollee" elif config_params: extra = " role=configurator " + config_params else: # TODO: Single Configurator instance res = wpas.request("DPP_CONFIGURATOR_ADD") if "FAIL" in res: summary("Failed to initiate Configurator", color=C_RED) break conf_id = int(res) extra = " conf=sta-dpp configurator=%d" % conf_id global own_id summary("Initiate DPP authentication") cmd = "DPP_AUTH_INIT peer=%d own=%d" % (peer_id, own_id) cmd += extra res = wpas.request(cmd) if "FAIL" in res: summary("Failed to initiate DPP authentication", color=C_RED) break if not dpp_found and handover.no_alt_proposal: summary("DPP carrier not seen in response - do not allow alternative proposal anymore") elif not dpp_found: summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") handover.alt_proposal = True handover.my_crn_ready = False handover.my_crn = None handover.peer_crn = None handover.hs_sent = False summary("Returning from dpp_handover_client") return summary("Remove peer") handover.close() summary("Done with handover") global only_one if only_one: print("only_one -> stop loop") global continue_loop continue_loop = False global no_wait if no_wait or only_one: summary("Trying to exit..") global terminate_now terminate_now = True summary("Returning from dpp_handover_client")
def send_ndef_message(self, llc): if self.URLparser(): sp = ndef.UriRecord(self.data) else: sp = ndef.TextRecord(self.data) nfc.snep.SnepClient(llc).put_records([sp])
def process_handover_request_message(self, records): self.ho_server_processing = True global in_raw_mode was_in_raw_mode = in_raw_mode clear_raw_mode() if was_in_raw_mode: print("\n") summary("HandoverServer - request received: " + str(records)) global my_crn, peer_crn, my_crn_ready for carrier in records: if not isinstance(carrier, ndef.HandoverRequestRecord): continue if carrier.collision_resolution_number: peer_crn = carrier.collision_resolution_number summary("peer_crn: %d" % peer_crn) if my_crn is None and my_crn_ready: summary( "Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values" ) for i in range(10): if my_crn is not None: break time.sleep(0.01) if my_crn is not None: summary("my_crn: %d" % my_crn) if my_crn is not None and peer_crn is not None: if my_crn == peer_crn: summary( "Same crn used - automatic collision resolution failed") # TODO: Should generate a new Handover Request message return '' if ((my_crn & 1) == (peer_crn & 1) and my_crn > peer_crn) or \ ((my_crn & 1) != (peer_crn & 1) and my_crn < peer_crn): summary("I'm the Handover Selector Device") pass else: summary("Peer is the Handover Selector device") summary("Ignore the received request.") return '' hs = ndef.HandoverSelectRecord('1.4') sel = [hs] found = False for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: summary("URI Identifier Code 'None' not seen", color=C_RED) continue uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) global test_uri, test_alt_uri if test_uri: summary("TEST MODE: Using specified URI") data = test_sel_uri if test_sel_uri else test_uri else: data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) summary("Own URI (pre-processing): %s" % data) if test_uri: summary("TEST MODE: Fake processing") res = "OK" else: res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: summary("DPP handover request processing failed", color=C_RED) global altchanlist if altchanlist: data = wpas_get_nfc_uri(start_listen=False, chan_override=altchanlist) summary("Own URI (try another channel list): %s" % data) continue if test_alt_uri: summary("TEST MODE: Reject initial proposal") continue found = True if not test_uri: wpas = wpas_connect() if wpas is None: continue global own_id data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue summary("Own URI (post-processing): %s" % data) uri = ndef.UriRecord(data) summary("Own bootstrapping NFC URI record: " + str(uri)) if not test_uri: info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None or freq == 0: summary( "No channel negotiated over NFC - use channel 6") freq = 2437 else: summary("Negotiated channel: %d MHz" % freq) if get_status_field(wpas, "bssid[0]"): summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: summary( "Enable beaconing to have radio ready for RX") wpas.request("DISABLE") wpas.request("SET start_disabled 0") wpas.request("ENABLE") cmd = "DPP_LISTEN %d" % freq global enrollee_only global configurator_only if enrollee_only: cmd += " role=enrollee" elif configurator_only: cmd += " role=configurator" summary(cmd) res = wpas.request(cmd) if "OK" not in res: summary("Failed to start DPP listen", color=C_RED) break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) summary("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break global hs_sent, no_alt_proposal summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") self.success = True hs_sent = True elif no_alt_proposal: summary( "Do not try alternative proposal anymore - handover failed", color=C_RED) hs_sent = True else: summary("Try to initiate with alternative parameters") self.try_own = True hs_sent = False no_alt_proposal = True threading.Thread(target=llcp_worker, args=(self.llc, True)).start() return sel
import nfc import ndef import time tags = set() rec = ndef.UriRecord("https://google.com") def on_connect(tag): tag_id = str(tag).split('ID=')[1] if tag_id is None: print("Tag cannot be formatted (not supported).") elif tag_id is not None: print("RFID UI is", tag_id) time.sleep(1.5) else: tag.ndef.records = [rec] if __name__ == "__main__": clf = nfc.ContactlessFrontend() if not clf.open('usb'): raise RuntimeError("Failed to open NFC device.") while True: config = {'interval': 0.90, 'on-connect': on_connect} ret = clf.connect(rdwr=config) if ret is None:
if target is None: sleep(2) # don't burn the CPU continue # tag = nfc.tag.activate(clf, target) print(tag) # How to write URI via NFCpy documentation https://nfcpy.readthedocs.io/en/latest/topics/get-started.html#read-and-write-tags # uri, title = 'spotify:album:65zhpgwMMRxncpa7zHckQ6','Sunday Service' # tag.ndef.records = [ndef.SmartposterRecord(uri, title)] # How to write URI via ndeflib documentation https://ndeflib.readthedocs.io/en/stable/records/uri.html tag_uri = 'spotify:album:65zhpgwMMRxncpa7zHckQ6' tag.ndef.records = [ndef.UriRecord(tag_uri)] # Finally the contactless frontend should be closed. clf.close() # except: # print("An error occurred or there was no tag") # # # BlinkStick # # from blinkstick import blinkstick # # led = blinkstick.find_first(): # # led.set_color(name="red")
(('tel:1234', ), "NDEF Uri Record ID '' Resource 'tel:1234'"), ] def test_uri_to_iri_conversion(): record = ndef.UriRecord() # no netloc -> no conversion record.uri = u"tel:1234" assert record.iri == u"tel:1234" # with netloc -> conversion record.uri = u"http://www.xn--hy-viaa5g.com/%7Euser/index.html" assert record.iri == u"http://www.hääyö.com/~user/index.html" uri_messages = [ ('D1010a55036e666370792e6f7267', [ndef.UriRecord('http://nfcpy.org')]), ('91010a55036e666370792e6f7267 51010a55046e666370792e6f7267', [ndef.UriRecord('http://nfcpy.org'), ndef.UriRecord('https://nfcpy.org')]), ('D101115500736d74703a2f2f6e666370792e6f7267', [ndef.UriRecord('smtp://nfcpy.org')]), ] @pytest.mark.parametrize("encoded, message", uri_messages) def test_message_decode(encoded, message): octets = bytes(bytearray.fromhex(encoded)) print(list(ndef.message_decoder(octets))) assert list(ndef.message_decoder(octets)) == message
def add_default_records(self, records=[], tag_id=None): """ Return default records to write to a tag """ _default_records = None if tag_id: if tag_id in self.tags: if self.tags[tag_id].get('default_records'): _default_records = self.tags[tag_id]['default_records'] if _default_records is None and self.default_records is not None: _default_records = self.default_records if _default_records is None: _txt_mudpi = ndef.TextRecord("MudPi") if _txt_mudpi not in records: records.insert(0, _txt_mudpi) _uri_mudpi = ndef.UriRecord("https://mudpi.app/docs/extension-nfc") if _uri_mudpi not in records: records.insert(1, _uri_mudpi) _txt_count_label = ndef.TextRecord("Matthew 15:13") if _txt_count_label not in records: records.insert(2, _txt_count_label) else: if isinstance(_default_records, list): for default_record in _default_records: _record = None if default_record.get('type', '').lower() == 'text': if default_record.get('data'): _record = ndef.TextRecord(default_record['data']) elif default_record.get('type', '').lower() == 'uri': if default_record.get('data'): _record = ndef.UriRecord(default_record['data']) if _record: if _record not in records: if default_record.get('position') is not None: try: _position = int(default_record['position']) records.insert(_position, _record) except Exception: records.append(_record) else: records.append(_record) _has_count = False _has_uid = False _to_remove = [] for r in records: if r.type == TYPE_TEXT: if r.text.startswith('count:'): if not _has_count: _has_count = True else: # count already found, remove duplicate _to_remove.append(r) elif r.text.startswith('uid:'): if not _has_uid: _has_uid = True else: # uid already found, remove duplicate _to_remove.append(r) elif r.text.startswith('last_scan:'): if self.tracking: # remove it to replace with updated data _to_remove.append(r) if _to_remove: for record in _to_remove: records.remove(record) if not _has_uid: self.last_uid = uid = str(uuid4()) records.append(ndef.TextRecord(f"uid:{uid}")) if self.tracking: if not _has_count: records.append(ndef.TextRecord("count:0")) records.append( ndef.TextRecord( f"last_scan:{datetime.datetime.now().replace(microsecond=0).strftime('%Y-%m-%d %H:%M:%S')}" )) return records
NFC cards and tags. """ import nfc import ndef import time import datetime import threading from uuid import uuid4 from mudpi.workers import Worker from mudpi.extensions import BaseExtension from mudpi.logger.Logger import Logger, LOG_LEVEL from mudpi.constants import FONT_RESET, FONT_CYAN NAMESPACE = 'nfc' TYPE_TEXT = ndef.TextRecord().type TYPE_URI = ndef.UriRecord().type class Extension(BaseExtension): namespace = NAMESPACE update_interval = 0.5 def init(self, config): """ Setup the readers for nfc """ self.config = config self.readers = {} self.tags = self.mudpi.cache.setdefault(NAMESPACE, {}).setdefault('tags', {}) if not isinstance(config, list): config = [config]