def test_fail_decode_invalid_message_relax(encoded, errmsg): stream = BytesIO(bytearray.fromhex(encoded)) with pytest.raises(ndef.DecodeError) as excinfo: list(ndef.message_decoder(stream, errors='relax')) assert errmsg in str(excinfo.value) stream = BytesIO(bytearray.fromhex('900000' + encoded)) with pytest.raises(ndef.DecodeError) as excinfo: list(ndef.message_decoder(stream, errors='relax')) assert errmsg in str(excinfo.value)
def recv_records(self, timeout=None): msg = self.recv_octets(timeout) if msg is None: return None records = list(ndef.message_decoder(msg, 'relax')) if records and records[0].type == 'urn:nfc:wkt:Hs': summary("Handover client received message '{0}'".format(records[0].type)) return list(ndef.message_decoder(msg, 'relax')) summary("Handover client received invalid message: %s" + binascii.hexlify(msg)) return None
def recv_records(self, timeout=None): """Receive a handover select message from the remote server.""" octets = self.recv_octets(timeout) records = list(ndef.message_decoder(octets, 'relax')) if octets else [] if records and records[0].type == "urn:nfc:wkt:Hs": log.debug("received '{0}' message".format(records[0].type)) return list(ndef.message_decoder(octets, 'relax')) else: log.error("received invalid message %s", binascii.hexlify(octets)) return []
def write(writedata): payload = writedata payload = payload[:NDEF_MAX_LENGTH - 10] if len(payload) >= NDEF_MAX_LENGTH - 10 else payload bPayload = list(payload.encode("utf-8")) header = [0xD1] if 0x03 + len(bPayload) <= 0xFF else [0xC1] records = header + [0x01] + ( list(bytearray.fromhex(f"{0x03+len(bPayload):08X}")) if header[0] == 0xC1 else [0x03 + len(bPayload)]) + [0x54, 0x02, 0x6b, 0x72] writemessage = records + list(payload.encode("utf-8")) arr = (c_uint8 * len(writemessage))(*writemessage) data = reader.WriteTag(1, arr, len(writemessage)) print(" ".join([f'{a:02X}' for a in data.simpleTagInfo[0].aUid])) ndefMessage = "".join( [f'{a:02X}' for a in data.simpleTagInfo[0].aNdefMessage]) try: message = list(ndef.message_decoder(bytearray.fromhex(ndefMessage))) for m in message: if hasattr(m, "text"): print(m.text) else: print("NDEF content is NULL") except ndef.DecodeError: print("No NDEF content detected") return data.simpleTagInfo[0].aUid
def serve(self, socket): peer_sap = socket.getpeername() log.info("serving handover client on remote sap {0}".format(peer_sap)) send_miu = socket.getsockopt(nfc.llcp.SO_SNDMIU) try: while socket.poll("recv"): request = bytearray() while socket.poll("recv"): request += socket.recv() if len(request) == 0: continue # need some data try: list(ndef.message_decoder(request, 'strict', {})) except ndef.DecodeError: continue # need more data response = self._process_request_data(request) for offset in range(0, len(response), send_miu): fragment = response[offset:offset + send_miu] if not socket.send(fragment): return # connection closed except nfc.llcp.Error as error: (log.debug if error.errno == errno.EPIPE else log.error)(error) finally: socket.close() log.debug("handover serve thread terminated")
def reader(): code = "" detected = False try: # Select tag uid = mifare.select() # Read NDEF data ndef_data = mifare.read_ndef() # Parse NDEF data ndef_records = list(ndef.message_decoder(ndef_data)) print(ndef_records) stringa = str(ndef_records[0]) code = code_finder(stringa, 5) if code != "": detected = True print(code) current_time = time.strftime("%d-%m-%Y %H:%M:%S", time.gmtime()) print(current_time) if code not in registro: registro[code] = current_time except nxppy.SelectError: # SelectError is raised if no card is in the field. pass print(registro) return detected
def records(self): """Read or write a list of NDEF Records. .. versionadded:: 0.12 This attribute is a convinience wrapper for decoding and encoding of the NDEF message data :attr:`octets`. It uses the `ndeflib <https://ndeflib.readthedocs.io>`_ module to return the list of :class:`ndef.Record` instances decoded from the NDEF message data or set the message data from a list of records. :: from ndef import TextRecord if tag.ndef is not None: for record in tag.ndef.records: print(record) try: tag.ndef.records = [TextRecord('Hello World')] except nfc.tag.TagCommandError as err: print("NDEF write failed: " + str(err)) Decoding is performed with a relaxed error handling strategy that ignores minor errors in the NDEF data. The `ndeflib <https://ndeflib.readthedocs.io>`_ does also support 'strict' and 'ignore' error handling which may be used like so:: from ndef import message_decoder, message_encoder records = message_decoder(tag.ndef.octets, errors='strict') tag.ndef.octets = b''.join(message_encoder(records)) """ return list(message_decoder(self.octets, errors='relax'))
def main(): # Instantiate reader mifare = nxppy.Mifare() # dict with presence signed in registro = {} while True: try: # Select tag uid = mifare.select() # Read NDEF data ndef_data = mifare.read_ndef() # Parse NDEF data ndef_records = list(ndef.message_decoder(ndef_data)) print(ndef_records) stringa = str(ndef_records[0]) code = code_finder(stringa, 5) print(code) current_time = time.strftime("%d-%m-%Y %H:%M:%S", time.gmtime()) print(current_time) if code not in registro: registro[code] = current_time except nxppy.SelectError: # SelectError is raised if no card is in the field. pass print(registro) time.sleep(3)
def __init__(self): parser = argparse.ArgumentParser( usage='%(prog)s [OPTION]... [CARRIER]...', formatter_class=argparse.RawDescriptionHelpFormatter, description=description) parser.add_argument( "carriers", metavar="CARRIER", nargs="*", type=argparse.FileType('rb'), help="supported carrier") parser.add_argument( "--select", metavar="NUM", type=int, default=1, help="select up to NUM carriers (default: %(default)s))") parser.add_argument( "--delay", type=int, metavar="INT", help="delay the response for INT milliseconds") def miu(string): value = int(string) if value < 128 or value > 2176: msg = "invalid choice: %d (choose from 128 to 2176)" % value raise argparse.ArgumentTypeError(msg) return value parser.add_argument( "--recv-miu", type=miu, metavar="INT", default=128, help="data link connection receive miu (default: %(default)s)") def buf(string): value = int(string) if value < 0 or value > 15: msg = "invalid choice: %d (choose from 0 to 15)" % value raise argparse.ArgumentTypeError(msg) return value parser.add_argument( "--recv-buf", type=buf, metavar="INT", default=2, help="data link connection receive window (default: %(default)s)") super(TestProgram, self).__init__( parser, groups="llcp dbg clf iop") if sum([1 for f in self.options.carriers if f.name == "<stdin>"]) > 1: log.error("only one carrier file may be read from stdin") raise SystemExit(1) self.options.selectable = [] for index, carrier in enumerate(self.options.carriers): data = carrier.read() try: data = binascii.unhexlify(data) except (binascii.Error, TypeError): pass records = list(ndef.message_decoder(data)) records[0].name = 'carrier-{}'.format(index) log.info("add carrier: {}".format(records[0])) self.options.selectable.append(records) self.select_carrier_lock = threading.Lock() self.handover_service = None self.snep_service = None
def test_handover_initiate_record_attributes(): record = HandoverInitiateRecord() record.add_alternative_carrier('active', 'wifi', 'a1', 'a2') record.add_alternative_carrier('inactive', 'bt31', 'a3') record.unknown_records.append(Record('text/plain', 'txt', 'Hello')) octets = b''.join(message_encoder([record])) record = list(message_decoder(octets))[0] assert isinstance(record, HandoverInitiateRecord) assert record.type == 'urn:nfc:wkt:Hi' assert record.name == '' assert record.hexversion == 0x13 assert record.version_info == (1, 3) assert record.version_string == "1.3" assert len(record.alternative_carriers) == 2 assert len(record.alternative_carriers[0].auxiliary_data_reference) == 2 assert len(record.alternative_carriers[1].auxiliary_data_reference) == 1 assert record.alternative_carriers[0].carrier_power_state == 'active' assert record.alternative_carriers[0].carrier_data_reference == 'wifi' assert record.alternative_carriers[0].auxiliary_data_reference[0] == 'a1' assert record.alternative_carriers[0].auxiliary_data_reference[1] == 'a2' assert record.alternative_carriers[1].carrier_power_state == 'inactive' assert record.alternative_carriers[1].carrier_data_reference == 'bt31' assert record.alternative_carriers[1].auxiliary_data_reference[0] == 'a3' assert len(record.unknown_records) == 1 assert record.unknown_records[0].type == 'text/plain' assert record.unknown_records[0].name == 'txt' assert record.unknown_records[0].data == b'Hello'
def recv_octets(self, timeout=None): start = time.time() msg = bytearray() while True: poll_timeout = 0.1 if timeout is None or timeout > 0.1 else timeout if not self.socket.poll('recv', poll_timeout): if timeout: timeout -= time.time() - start if timeout <= 0: return None start = time.time() continue try: r = self.socket.recv() if r is None: return None msg += r except TypeError: return b'' try: list(ndef.message_decoder(msg, 'strict', {})) return bytes(msg) except ndef.DecodeError: if timeout: timeout -= time.time() - start if timeout <= 0: return None start = time.time() continue return None
def test_decode(self, octets): octets = bytearray.fromhex(octets) record = next(ndef.message_decoder(octets)) assert isinstance(record, eval(self.cls)) assert record.type == 'application/vnd.bluetooth.le.oob' assert record.device_address.addr == '01:02:03:04:05:06' assert len(record.items()) == 2 assert record.get(0xFF) == b'ab'
def parse_records(octets): records = list(ndef.message_decoder(octets)) if records[0].type != "urn:nfc:wkt:U": raise Exception("Only URI records are supported. Was: " + str(records[0])) elif not records[0].uri.startswith("https://open.spotify.com"): raise Exception("Currently, only spotify links are supported. Was: " + str(records[0])) else: return records
def load_file(f, decode_errors): fn = getattr(f, 'name', '<stdin>') try: records = list(ndef.message_decoder(f.read(), decode_errors)) info("loaded %d record(s) from %s" % (len(records), fn)) return records except ndef.DecodeError as error: dmsg(str(error)) errmsg = "%s does not contain a valid NDEF message." % fn raise click.ClickException(errmsg)
def process_snep_request(self, request_data): assert isinstance(request_data, bytearray) log.debug("<<< %s", binascii.hexlify(request_data).decode()) try: if request_data[1] == 1 and len(request_data) >= 10: acceptable_length = struct.unpack(">L", request_data[6:10])[0] octets = request_data[10:] records = list(ndef.message_decoder(octets, known_types={})) response = self.process_get_request(records) if isinstance(response, int): response_code = response response_data = b'' else: response_code = 0x81 # nfc.snep.Success response_data = b''.join(ndef.message_encoder(response)) if len(response_data) > acceptable_length: response_code = 0xC1 # nfc.snep.ExcessData response_data = b'' elif request_data[1] == 2: octets = request_data[6:] records = list(ndef.message_decoder(octets, known_types={})) response_code = self.process_put_request(records) response_data = b'' else: log.debug("bad request (0x{:02x})".format(request_data[1])) response_code = 0xC2 # nfc.snep.BadRequest response_data = b'' except ndef.DecodeError as error: log.error(repr(error)) response_code = 0xC2 # nfc.snep.BadRequest response_data = b'' except ndef.EncodeError as error: log.error(repr(error)) response_code = 0xC0 # nfc.snep.NotFound response_data = b'' header = struct.pack(">BBL", 0x10, response_code, len(response_data)) response_data = header + response_data log.debug(">>> %s", binascii.hexlify(response_data).decode()) return response_data
def run_recv_send_action(args, llc, message): log.info('translate ndef message {}'.format(message[0].type)) if isinstance(args.translations, filetype): stream = io.BytesIO(args.translations.read()) args.translations = list() while True: try: msg_recv = list(ndef.message_decoder(stream, known_records={})) msg_send = list(ndef.message_decoder(stream, known_records={})) args.translations.append((msg_recv, msg_send)) log.info('added translation {} => {}'.format( msg_recv, msg_send)) except ndef.DecodeError: break for msg_recv, msg_send in args.translations: if message == msg_recv: log.info('rcvd beam {}'.format(msg_recv)) log.info('send beam {}'.format(msg_send)) nfc.snep.SnepClient(llc).put_records(msg_send) break
def test_00(self, llc): """Read NDEF data to send from file 'beam.ndef'""" try: data = open("beam.ndef", "rb").read() except IOError: return try: snep = nfc.snep.SnepClient(llc, max_ndef_msg_recv_size=1024) snep.put_records(ndef.message_decoder(data)) finally: snep.close()
async def readCard(): token = 'ERROR' returnCode = subprocess.call([nfcToolsPath, 'r', fileName]) if (returnCode == 0): with open(fileName, 'rb') as f: dump = f.read() if (hex(dump[12]) == '0xe1'): length = dump[17] message = dump[18:(18 + length)] #print(message) for record in ndef.message_decoder(message): if (record.type == 'urn:nfc:wkt:T'): token = record.text return token
def run_send_ndef_action(args, llc): if isinstance(args.ndef, filetype): octets = io.BytesIO(args.ndef.read()) args.selected = -1 args.ndef = list() records = list(ndef.message_decoder(octets, known_types={})) while records: args.ndef.append(records) records = list(ndef.message_decoder(octets, known_types={})) if args.select == "first": args.selected = 0 elif args.select == "last": args.selected = len(args.ndef) - 1 elif args.select == "next": args.selected = args.selected + 1 elif args.select == "cycle": args.selected = (args.selected + 1) % len(args.ndef) elif args.select == "random": args.selected = random.choice(range(len(args.ndef))) if 0 <= args.selected < len(args.ndef): log.info("send {}".format(args.ndef[args.selected])) send_message(args, llc, args.ndef[args.selected])
def scan_card(): """Return the uid and NDEF card as a response for jsonify and Flask API.""" # Instantiate reader mifare = nxppy.Mifare() try: # Select tag uid = mifare.select() # Print card UIDs as they are detected if len(uid) == 8: try: # mifare classic not implemented in nxppy # can detect uid # requirement to authenticate for read / write access return {"uid":uid, "text":"", "status":"success"} except nxppy.ReadError: return {"error": "cannot read data"} if len(uid) == 14: try: # Read NDEF data ndef_data = mifare.read_ndef() # print(ndef_data) # Parse NDEF data ndef_records = list(ndef.message_decoder(ndef_data)) record = ndef_records[0] return {"uid":uid, "text":record.text, "status":"success"} except nxppy.ReadError: return {"error": "cannot read ndef_data"} except nxppy.SelectError: # SelectError is raised if no card is in the field. return {"error": "card not found"}
def load_tag(self, tag): try: self.options.data except AttributeError: try: self.options.data = self.options.input.buffer.read() except AttributeError: self.options.data = self.options.input.read() try: self.options.data = binascii.unhexlify(self.options.data) except binascii.Error: pass if tag.ndef is None: print("This is not an NDEF Tag.") return if not tag.ndef.is_writeable: print("This Tag is not writeable.") return if self.options.data == tag.ndef.octets: print("The Tag already contains the message to write.") return if len(self.options.data) > tag.ndef.capacity: print("The new message exceeds the Tag's capacity.") return if tag.ndef.length > 0: print("Old NDEF Message:") for i, record in enumerate(tag.ndef.records): print("record", i + 1) print(" type =", repr(record.type)) print(" name =", repr(record.name)) print(" data =", repr(record.data)) tag.ndef.records = list(ndef.message_decoder(self.options.data)) if tag.ndef.length > 0: print("New NDEF Message:") for i, record in enumerate(tag.ndef.records): print("record", i + 1) print(" type =", repr(record.type)) print(" name =", repr(record.name)) print(" data =", repr(record.data))
def _process_request_data(self, octets): log.debug("<<< %s", binascii.hexlify(octets).decode()) try: records = list(ndef.message_decoder(octets, 'relax')) except ndef.DecodeError as error: log.error(repr(error)) return b'' if records[0].type == 'urn:nfc:wkt:Hr': records = self.process_handover_request_message(records) else: log.error("received unknown request message") records = [] octets = b''.join(ndef.message_encoder(records)) log.debug(">>> %s", binascii.hexlify(octets).decode()) return octets
def decode_message(response): """creates a list of records that is found on the card, expects a response in the form of a byte array that can be interpreted as ndef format""" # print(f"input response = {response}") octets = response # print(f"octets = {octets}") decoder = ndef.message_decoder(octets) # print(f"decoder = {decoder}") message = list(decoder) # print(f"message = {message}") for _ in decoder: next(decoder) return message
def decode_message_text(payload): """ If you expect only a text returned from the payload returns all the text records found, ignoring other records """ print(f"NDEF payload received: {payload}") decoder = ndef.message_decoder(payload) array_of_records = list(decoder) print(f"NDEF records extracted: {array_of_records}") message = [] for record in array_of_records: message += [record.text] print(f"Messages found: {message}") return message
def decode_message(payload): """ Returns all types of records found in the payload """ print(f"NDEF payload received: {payload}") decoder = ndef.message_decoder(payload) array_of_records = list(decoder) print(f"NDEF records extracted: {array_of_records}") message = [] for record in array_of_records: print(f"record type is {record.type}") # message += [record.text] print(f"Array of records found: {array_of_records}") return message
def serve(self, socket): peer_sap = socket.getpeername() summary("Serving handover client on remote sap {0}".format(peer_sap)) send_miu = socket.getsockopt(nfc.llcp.SO_SNDMIU) try: while socket.poll("recv"): req = bytearray() while socket.poll("recv"): r = socket.recv() if r is None: return None summary("Received %d octets" % len(r)) req += r if len(req) == 0: continue try: list(ndef.message_decoder(req, 'strict', {})) except ndef.DecodeError: continue summary("Full message received") resp = self._process_request_data(req) if resp is None or len(resp) == 0: summary("No handover select to send out - wait for a possible alternative handover request") handover.alt_proposal = True req = bytearray() continue for offset in range(0, len(resp), send_miu): if not socket.send(resp[offset:offset + send_miu]): summary("Failed to send handover select - connection closed") return summary("Sent out full handover select") if handover.terminate_on_hs_send_completion: handover.delayed_exit() except nfc.llcp.Error as e: global terminate_now summary("HandoverServer exception: %s" % e, color=None if e.errno == errno.EPIPE or terminate_now else C_RED) finally: socket.close() summary("Handover serve thread exiting")
def recv_octets(self, timeout=None): octets = bytearray() started = time.time() while self.socket.poll("recv", timeout): try: octets += self.socket.recv() except TypeError: log.debug("data link connection closed") return b'' # recv() returned None try: list(ndef.message_decoder(octets, 'strict', {})) log.debug("<<< %s", binascii.hexlify(octets).decode()) return bytes(octets) except ndef.DecodeError: log.debug("message is incomplete (%d byte)", len(octets)) if timeout: timeout -= time.time() - started started = time.time() log.debug("%.3f seconds left to timeout", timeout) continue # incomplete message
def load_tag(self, tag, path): try: f = open(path, 'rb') except Exception: print_error("file not found") else: with f: data = f.read() if tag.ndef is None: print("This is not an NDEF Tag.") return if not tag.ndef.is_writeable: print("This Tag is not writeable.") return if data == tag.ndef.octets: print("The Tag already contains the message to write.") return if len(data) > tag.ndef.capacity: print("The new message exceeds the Tag's capacity.") return if tag.ndef.length > 0: print("Old NDEF Message:") for i, record in enumerate(tag.ndef.records): print("record", i + 1) print(" type =", repr(record.type)) print(" name =", repr(record.name)) print(" data =", repr(record.data)) tag.ndef.records = list(ndef.message_decoder(data)) if tag.ndef.length > 0: print("New NDEF Message:") for i, record in enumerate(tag.ndef.records): print("record", i + 1) print(" type =", repr(record.type)) print(" name =", repr(record.name)) print(" data =", repr(record.data))
def get_records(self, records=None, timeout=1.0): """Get NDEF message records from a SNEP Server. .. versionadded:: 0.13 The :class:`ndef.Record` list given by *records* is encoded as the request message octets input to :meth:`get_octets`. The return value is an :class:`ndef.Record` list decoded from the response message octets returned by :meth:`get_octets`. Same as:: import ndef send_octets = ndef.message_encoder(records) rcvd_octets = snep_client.get_octets(send_octets, timeout) records = list(ndef.message_decoder(rcvd_octets)) """ octets = b''.join(ndef.message_encoder(records)) if records else None octets = self.get_octets(octets, timeout) if octets and len(octets) >= 3: return list(ndef.message_decoder(octets))
def cmd(ctx, message, **kwargs): """The *payload* command either changes the current last record's data (NDEF Record PAYLOAD) or, if the current message does not have any records, creates a record with the given record data. The changed record is verified to successfully encode and decode unless disabled with -x. The data string may contain hexadecimal bytes using '\\xNN' notation where each N is a nibble from [0-F]. \b Examples: ndeftool payload 'Hello World' typename 'text/plain' print ndeftool payload '\\x02enHello World' typename 'urn:nfc:wkt:T' print -l """ dmsg(__name__ + ' ' + str(kwargs)) dmsg(repr(kwargs['data'])) if not message: message = [ndef.Record('unknown')] record_type = message[-1].type record_name = message[-1].name record_data = eval(repr(kwargs['data'].encode()).replace('\\\\', '\\')) record = ndef.Record(record_type, record_name, record_data) if not kwargs['no_check']: octets = b''.join(ndef.message_encoder([record])) errors = ctx.meta['decode-errors'] try: record = next(ndef.message_decoder(octets, errors)) except ndef.DecodeError as error: raise click.ClickException(str(error)) message[-1] = record return message
def test_decode_fail(self, octets, errstr): octets = bytearray.fromhex(octets) with pytest.raises(ndef.DecodeError) as excinfo: next(ndef.message_decoder(octets)) assert str(excinfo.value) == self.cls + ' ' + errstr
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 test_message_decode_fail(encoded, errstr): octets = bytes(bytearray.fromhex(encoded)) with pytest.raises(ndef.DecodeError) as excinfo: print(list(ndef.message_decoder(octets))) assert str(excinfo.value) == "ndef.smartposter." + errstr