Merge lp:~sanyok-og/nfcpy/dev-dbus into lp:nfcpy

Proposed by Alexander Knaub
Status: Merged
Merged at revision: 33
Proposed branch: lp:~sanyok-og/nfcpy/dev-dbus
Merge into: lp:nfcpy
Diff against target: 874 lines (+859/-0)
3 files modified
examples/dbus_examples/dbus_readerwriter.py (+328/-0)
examples/dbus_examples/read_tag.py (+235/-0)
examples/dbus_examples/tagtool.py (+296/-0)
To merge this branch: bzr merge lp:~sanyok-og/nfcpy/dev-dbus
Reviewer Review Type Date Requested Status
Stephen Tiedemann Approve
Review via email: mp+45138@code.launchpad.net

Description of the change

Added a D-Bus server and 2 clients to the examples.
D-Bus configuration is described in the comments inside.

To post a comment you must log in.
Revision history for this message
Stephen Tiedemann (stephen-tiedemann) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'examples/dbus_examples'
2=== added file 'examples/dbus_examples/dbus_readerwriter.py'
3--- examples/dbus_examples/dbus_readerwriter.py 1970-01-01 00:00:00 +0000
4+++ examples/dbus_examples/dbus_readerwriter.py 2011-01-04 16:28:41 +0000
5@@ -0,0 +1,328 @@
6+# -----------------------------------------------------------------------------
7+# Copyright 2010, 2011 Alexander Knaub <sanyok.og@googlemail.com>
8+#
9+# Licensed under the EUPL, Version 1.1 or - as soon they
10+# will be approved by the European Commission - subsequent
11+# versions of the EUPL (the "Licence");
12+# You may not use this work except in compliance with the
13+# Licence.
14+# You may obtain a copy of the Licence at:
15+#
16+# http://ec.europa.eu/idabc/eupl
17+#
18+# Unless required by applicable law or agreed to in
19+# writing, software distributed under the Licence is
20+# distributed on an "AS IS" basis,
21+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
22+# express or implied.
23+# See the Licence for the specific language governing
24+# permissions and limitations under the Licence.
25+# -----------------------------------------------------------------------------
26+
27+
28+# Usage Notes start -----------------------------------------------------------
29+# This file implements the basic NFC Type3Tag-operations and offers an
30+# interface via D-Bus.
31+# This interface includes methods to write NDEF-Data to a tag (WriteNDEF) and
32+# format a tag (FormatTag).
33+# Also it contains D-Bus-Signals to inform the listeners about newly read
34+# tag (TagInfo) and the message contained in this tag (NDEFMessage) in form
35+# of byte arrays.
36+#
37+# Before starting to use this module, you have to configure your system D-Bus:
38+# 1) Create a file with the name like "org.nfcpy.Tagreader.conf" with
39+# following content:
40+#
41+# <?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
42+# <!DOCTYPE busconfig PUBLIC
43+# "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
44+# "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
45+# <busconfig>
46+# <servicedir>/usr/share/dbus-1/system-services/</servicedir>
47+# <policy context="default">
48+# <!-- Root can connect to system bus -->
49+# <allow user="root"/>
50+#
51+# <!-- Holes are punched here for
52+# name ownership and sending method calls -->
53+# <allow own="org.nfcpy.TagReader"/>
54+# <allow send_type="method_call"/>
55+# </policy>
56+# </busconfig>
57+#
58+# 2) Place this file in the folder "/etc/dbus-1/system.d/". Note that you
59+# will need root rights for this. You can use the following command:
60+# sudo cp org.nfcpy.Tagreader.conf /etc/dbus-1/system.d/org.nfcpy.Tagreader.conf
61+#
62+# 3) Reboot your computer to start D-Bus with new configuration.
63+#
64+# Usage Notes end--------------------------------------------------------------
65+import logging
66+log = logging.getLogger("nfcpy.reader")
67+import time
68+import gobject
69+import pickle
70+from threading import Thread
71+import dbus.service
72+import dbus.mainloop.glib
73+#nfc package is 2 levels higher in the file system:
74+import sys, os
75+_above_folder = os.path.split(sys.path[0])[0]
76+sys.path.insert(1, os.path.split(_above_folder)[0])
77+import nfc.dev
78+from nfc.ndef.Message import Message
79+
80+BUS_NAME = "org.nfcpy.TagReader"
81+
82+def tt3_format(tag):
83+ log.debug("Formatting...")
84+ def determine_block_count(tag):
85+ block = 0
86+ try:
87+ while True:
88+ data = tag.read([block], 9)
89+ block += 1
90+ except Exception:
91+ if tag.pmm[0:2] == "\x00\xF0":
92+ block -= 1 # last block on FeliCa Lite is unusable
93+ return block
94+
95+ def determine_block_read_count(tag, block_count):
96+ try:
97+ for i in range(block_count):
98+ tag.read(range(i+1))
99+ except Exception: return i
100+
101+ def determine_block_write_count(tag, block_count):
102+ try:
103+ for i in range(block_count):
104+ data = ((i+1)*16) * "\x00"
105+ tag.write(data, range(i+1))
106+ except Exception: return i
107+
108+ block_count = determine_block_count(tag)
109+ log.debug("tag has %d user data blocks" % block_count)
110+
111+ nbr = determine_block_read_count(tag, block_count)
112+ log.debug("%d block(s) can be read at once" % nbr)
113+
114+ nbw = determine_block_write_count(tag, block_count)
115+ log.debug("%d block(s) can be written at once" % nbw)
116+
117+ nmaxb_msb = (block_count - 1) / 256
118+ nmaxb_lsb = (block_count - 1) % 256
119+ attr = [0x10, nbr, nbw, nmaxb_msb, nmaxb_lsb,
120+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
121+ csum = sum(attr[0:14])
122+ attr[14] = csum / 256
123+ attr[15] = csum % 256
124+
125+ log.debug("writing attribute data block:")
126+ print " ".join(["%02x" % x for x in attr])
127+
128+ attr = ''.join([chr(b) for b in attr])
129+ tag.write(attr, [0])
130+ log.debug("Successful")
131+
132+class TagReader(dbus.service.Object):
133+ def __init__(self, bus, mainloop, path="/nfcpy/tagreader"):
134+ log.debug("READER: Create Reader/Writer object...")
135+ self.running = False
136+ dbus.service.Object.__init__(self, conn=bus, object_path=path)
137+ if bus.name_has_owner(BUS_NAME):
138+ # Another instance exists. Inform user and exit.
139+ owner = bus.get_name_owner(BUS_NAME)
140+ log.warning("READER: Another instance is running. You can access "
141+ + "or exit it via DBus by the name 'org.nfcpy.TagReader'"
142+ + "or by the unique name " + owner + ".")
143+ return
144+ log.debug("READER: Request Service name")
145+ req_responce = bus.request_name(BUS_NAME,
146+ dbus.bus.NAME_FLAG_DO_NOT_QUEUE)
147+ # debugging:
148+ if req_responce == dbus.bus.REQUEST_NAME_REPLY_EXISTS:
149+ log.debug("READER: reply: exists. %s" % req_responce)
150+ elif req_responce == dbus.bus.REQUEST_NAME_REPLY_PRIMARY_OWNER:
151+ log.debug("READER: reply: primary owner. %s" % req_responce)
152+
153+ self._mainloop = mainloop
154+ self._message = None
155+ self._last_tag = dict()
156+ self._exit_reading = False
157+ self._pause_reading = False
158+ self._last_idm = None
159+ self._clf = None
160+ read_thread = Thread(target=self.read_loop, name="ReadThread")
161+ read_thread.start()
162+ self.running = True
163+
164+ @property
165+ def running(self):
166+ return self._running
167+
168+ @running.setter
169+ def running(self, value):
170+ self._running = value
171+
172+ @dbus.service.signal(dbus_interface='org.nfcpy.TagReader',
173+ signature='ay') # byte-array, subclass of str
174+ def NDEFMessage(self, new_message_string):
175+ log.debug("READER: Emit message!")
176+ if new_message_string:
177+ return new_message_string
178+ else:
179+ return ""
180+
181+ @dbus.service.signal(dbus_interface='org.nfcpy.TagReader',
182+ signature='ay') # byte-array, subclass of str
183+ def TagInfo(self, tag_str):
184+ log.debug("READER: Emit Tag Info!")
185+# return new_message_string
186+
187+ @dbus.service.method('org.nfcpy.TagReader', in_signature="",
188+ out_signature="")
189+ def Exit(self):
190+ log.info("READER: exiting...")
191+ self._exit_reading = True
192+ log.debug("READER: release connection to" + str(self.connection))
193+ self.connection.release_name(BUS_NAME)
194+ log.debug("READER: Stop the mainloop")
195+ self._mainloop.quit()
196+ log.debug("READER: End program")
197+
198+ @dbus.service.method('org.nfcpy.TagReader', in_signature="ay",
199+ out_signature="", byte_arrays=True)
200+ def WriteNDEF(self, message_string):
201+ log.info("WRITER: Writting...")
202+ self._pause_reading = True
203+ self._message = Message(str(message_string))
204+ log.info("WRITER: Write message with type " + self._message.type)
205+ if not self._clf:
206+ try:
207+ self._clf = nfc.ContactlessFrontend(probe=nfc.dev.__all__)
208+ except LookupError:
209+ log.warning("WRITER: Reader/Writer not found. Exiting")
210+ self.Exit()
211+ tag = None
212+ while not tag:
213+ tag = self._clf.poll(general_bytes = None)
214+
215+ if tag:
216+ log.debug("WRITER: found tag with IDm " + tag.idm)
217+ tag.ndef.message = self._message.tostring()
218+ log.debug("WRITER: Writing successfully finished.")
219+ else:
220+ log.info("WRITER: No tag found...")
221+ self._pause_reading = False
222+ return
223+
224+ @dbus.service.method('org.nfcpy.TagReader', in_signature="",
225+ out_signature="b")
226+ def FormatTag(self):
227+ self._pause_reading = True
228+ if not self._clf:
229+ try:
230+ self._clf = nfc.ContactlessFrontend(probe=nfc.dev.__all__)
231+ except LookupError:
232+ log.warning("WRITER: Reader/Writer not found. Exiting")
233+ self.Exit()
234+
235+ tag = None
236+ while not tag:
237+ try:
238+ tag = self._clf.poll(general_bytes = None)
239+ except KeyboardInterrupt:
240+ log.warning("WRITER: Aborted by user. Exit formatting...")
241+ return False
242+ log.info("Tag found: " + str(tag))
243+ if tag:
244+ log.info(str(tag))
245+ if isinstance(tag, nfc.Type3Tag):
246+ tt3_format(tag)
247+ success = True
248+ else:
249+ print "unable to format {0}".format(str(tag))
250+ self._pause_reading = False
251+ success = False
252+ else:
253+ print "No tag"
254+ self._pause_reading = False
255+ return success
256+
257+ def read_loop(self):
258+ log.debug("READER: start new reading loop...")
259+ if not self._clf:
260+ try:
261+ self._clf = nfc.ContactlessFrontend(probe=nfc.dev.__all__)
262+ log.debug("READER: CLF found: " + str(self._clf))
263+ except LookupError:
264+ log.warning("READER: Reader device not found. Exiting")
265+ self.Exit()
266+ return
267+ try:
268+ log.debug("READER: Now start reading")
269+ while not self._exit_reading:
270+ if not self._pause_reading:
271+ tag = self._clf.poll(general_bytes = None)
272+ else:
273+ tag = None
274+ if not tag:
275+ time.sleep(0.5)
276+ continue
277+ if isinstance(tag, nfc.Type3Tag):
278+ log.debug("READER: New tag found: " + str(tag))
279+ last_tag = {'idm': tag.idm,
280+ 'pmm': tag.pmm}
281+ if tag.ndef is not None:
282+ log.debug("READER: NDEF is present")
283+ self._last_idm = tag.idm
284+ last_tag['version'] = tag.ndef.version
285+ last_tag['writeable'] = tag.ndef.writeable
286+ last_tag['capacity'] = tag.ndef.capacity
287+ last_tag['size'] = len(tag.ndef.message)
288+
289+ self._message = Message(tag.ndef.message)
290+ log.debug("READER: NDEF Message detected: ")
291+ log.debug("READER: type=%s"
292+ % self._message.type)
293+ if last_tag['size']:
294+ log.debug("READER: size: %d" % last_tag['size'])
295+ self.NDEFMessage(tag.ndef.message) # emit
296+ self.TagInfo(pickle.dumps(last_tag))
297+
298+ while tag.is_present:
299+ time.sleep(1)
300+ log.debug("READER: Tag removed")
301+
302+ except IOError:
303+ log.warning("READER: IO Error occured. restarting...")
304+ read_thread = Thread(target=self.read_loop, name="ReadThread")
305+ read_thread.start()
306+
307+
308+if __name__ == "__main__":
309+ logging.basicConfig(level=logging.INFO, format='%(message)s')
310+ logging.getLogger("nfc").setLevel(logging.INFO)
311+ log.setLevel(logging.DEBUG)
312+
313+ # enable threads besides the mainloop
314+ gobject.threads_init()
315+ dbus.mainloop.glib.threads_init()
316+ log.debug("Threading initialised")
317+ # initialise TagReader:
318+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
319+ bus = dbus.SystemBus() #SystemBus()
320+ loop = gobject.MainLoop()
321+ reader = TagReader(bus, loop)
322+ if reader.running:
323+ log.debug("Reader object created")
324+ try:
325+ log.debug("Starting...")
326+ loop.run()
327+ except KeyboardInterrupt:
328+ log.info("READER: Aborted by user!")
329+ reader.Exit()
330+ else:
331+ log.debug("READER: Initialisation failed. Exiting...")
332+
333+
334
335=== added file 'examples/dbus_examples/read_tag.py'
336--- examples/dbus_examples/read_tag.py 1970-01-01 00:00:00 +0000
337+++ examples/dbus_examples/read_tag.py 2011-01-04 16:28:41 +0000
338@@ -0,0 +1,235 @@
339+# -----------------------------------------------------------------------------
340+# Copyright 2011 Alexander Knaub <sanyok.og@googlemail.com>
341+#
342+# Licensed under the EUPL, Version 1.1 or - as soon they
343+# will be approved by the European Commission - subsequent
344+# versions of the EUPL (the "Licence");
345+# You may not use this work except in compliance with the
346+# Licence.
347+# You may obtain a copy of the Licence at:
348+#
349+# http://ec.europa.eu/idabc/eupl
350+#
351+# Unless required by applicable law or agreed to in
352+# writing, software distributed under the Licence is
353+# distributed on an "AS IS" basis,
354+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
355+# express or implied.
356+# See the Licence for the specific language governing
357+# permissions and limitations under the Licence.
358+# -----------------------------------------------------------------------------
359+
360+import logging
361+log = logging.getLogger()
362+
363+import os
364+import sys
365+import time
366+import string
367+import pickle
368+import gobject
369+import dbus.mainloop.glib
370+
371+sys.path.insert(1, os.path.split(sys.path[0])[0])
372+import nfc.ndef
373+from nfc.ndef.SmartPoster import SmartPosterRecord
374+from nfc.ndef.ConnectionHandover import HandoverSelectMessage
375+from nfc.ndef.WiFiSimpleConfig import WiFiConfigData, WiFiPasswordData
376+from nfc.ndef.BluetoothEasyPairing import BluetoothConfigData
377+
378+BUS_NAME = "org.nfcpy.TagReader"
379+
380+def make_printable(data):
381+ printable = string.digits + string.letters + string.punctuation + ' '
382+ return ''.join([c if c in printable else '.' for c in data])
383+
384+def format_data(data):
385+ s = []
386+ for i in range(0, len(data), 16):
387+ s.append(" %04x: " % i)
388+ s[-1] += ' '.join(["%02x" % ord(c) for c in data[i:i+16]]) + ' '
389+ s[-1] += (8 + 16*3 - len(s[-1])) * ' '
390+ s[-1] += make_printable(data[i:i+16])
391+ return '\n'.join(s)
392+
393+def print_smartposter(message):
394+ print "Smart Poster"
395+ sp = SmartPosterRecord(message[0])
396+ for lang in sorted(sp.title):
397+ print " title[%s] = %s" % (lang, sp.title[lang])
398+ print " resource = %s" % sp.uri
399+ print " action = %s" % sp.action
400+ if len(message) > 1:
401+ print "Further Records"
402+ for index, record in enumerate(message):
403+ if index == 0: continue
404+ record.data = make_printable(record.data)
405+ print " [%d] type = %s" %(index, record.type)
406+ print " [%d] name = %s" %(index, record.name)
407+ print " [%d] data = %s" %(index, record.data)
408+
409+def print_handover_select(message):
410+ print "Connection Handover Select Message"
411+ number_suffix = ('st', 'nd', 'rd', 'th')
412+ message = HandoverSelectMessage(message)
413+ for i, carrier in enumerate(message.carriers):
414+ carrier_type = carrier['carrier-type']
415+ if carrier_type == "application/vnd.wfa.wsc":
416+ carrier_name = "Wi-Fi (Simple Config)"
417+ elif carrier_type == "application/vnd.bluetooth.ep.oob":
418+ carrier_name = "Bluetooth (Easy Pairing)"
419+ else:
420+ carrier_name = carrier_type
421+ print " %d%s carrier" % (i+1, number_suffix[min(i,3)]),
422+ print "is %s" % carrier_name
423+ print " power = %s" % carrier['power-state']
424+ config_data = carrier['config-data']
425+ if carrier_type == "application/vnd.wfa.wsc":
426+ cfg = WiFiConfigData.fromstring(config_data)
427+ print " version = %d.%d" % cfg.version
428+ print " network = %s" % cfg.ssid
429+ print " password = %s" % cfg.network_key
430+ print " macaddr = %s" % cfg.mac_address
431+ print " security = %s / %s" % \
432+ (cfg.authentication, cfg.encryption)
433+ elif carrier_type == "application/vnd.bluetooth.ep.oob":
434+ cfg = BluetoothConfigData.fromstring(config_data)
435+ print " bdaddr = %s" % cfg.device_address
436+ print " class = %s" % cfg.class_of_device.encode("hex")
437+ print " sp hash = %s" % cfg.simple_pairing_hash
438+ print " sp rand = %s" % cfg.simple_pairing_randomizer
439+ print " longname = %s" % cfg.long_name
440+ print " partname = %s" % cfg.short_name
441+ else:
442+ print carrier
443+
444+def print_wifi_token(message):
445+ try:
446+ data = WiFiPasswordData.fromstring(message[0].data)
447+ print " Wi-Fi Password Token"
448+ print " version = %d.%d" % data.version
449+ print " PK Hash = %s" % data.public_key_hash.encode("hex")
450+ print " DevPwdID = %s" % data.device_password_id
451+ print " Password = %s" % data.device_password.encode("hex")
452+ for key, val in data.other_attributes:
453+ print " 0x%04x = %s" % (key, val.encode("hex"))
454+ return
455+ except ValueError:
456+ pass
457+ try:
458+ data = WiFiConfigData.fromstring(message[0].data)
459+ print " Wi-Fi Configuration Token"
460+ print " version = %d.%d" % data.version
461+ print " network = %s" % data.ssid
462+ print " password = %s" % data.network_key
463+ print " macaddr = %s" % data.mac_address
464+ print " security = %s / %s" % \
465+ (data.authentication, data.encryption)
466+ return
467+ except ValueError:
468+ pass
469+
470+class ReaderClient:
471+ def __init__(self, mainloop, reader):
472+ self._loop = mainloop
473+ self._message = None
474+ self._reader = reader
475+
476+ def save_ndef(self, ndef_msg_string):
477+ print "Received %d Bytes: %s" % (len(ndef_msg_string), ndef_msg_string)
478+ if len(ndef_msg_string):
479+ self._message = nfc.ndef.Message(str(ndef_msg_string))
480+ else:
481+ print "Empty message received!"
482+
483+ def show_ndef(self):
484+ if self._message.type == "urn:nfc:wkt:Sp":
485+ print_smartposter(self._message)
486+
487+ elif self._message.type == "urn:nfc:wkt:Hs":
488+ print_handover_select(self._message)
489+
490+ elif self._message.type == "application/vnd.wfa.wsc":
491+ print_wifi_token(self._message)
492+
493+ else:
494+ print "Unknown Message"
495+ for index, record in enumerate(self._message):
496+ record.data = make_printable(record.data)
497+ print " [%d] record type = %s" %(index, record.type)
498+ print " [%d] record name = %s" %(index, record.name)
499+ print " [%d] record data = %s" %(index, record.data)
500+
501+ def show_tag(self, tag_str):
502+ self._tag_info = pickle.loads(tag_str)
503+ print "NDEF container present"
504+ print " version = %s" % self._tag_info['version']
505+ print " writeable = %s" % ("no", "yes")[self._tag_info['writeable']]
506+ print " capacity = %d byte" % self._tag_info['capacity']
507+ print " data size = %d byte" % self._tag_info['size']
508+ if self._message:
509+ self.show_ndef()
510+ else:
511+ print "No message",
512+ time.sleep(0.5)
513+ if self._message:
514+ print "received yet. Waiting..."
515+ self.show_ndef()
516+ else:
517+ print "available."
518+ self._loop.quit()
519+
520+def main():
521+
522+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
523+ bus = dbus.SystemBus()
524+ object = bus.get_object(BUS_NAME, "/nfcpy/tagreader")
525+ loop = gobject.MainLoop()
526+ client = ReaderClient(mainloop=loop, reader=object)
527+ object.connect_to_signal(signal_name="NDEFMessage",
528+ handler_function=client.save_ndef,
529+ dbus_interface='org.nfcpy.TagReader',
530+ byte_arrays=True)
531+ object.connect_to_signal(signal_name="TagInfo",
532+ handler_function=client.show_tag,
533+ dbus_interface='org.nfcpy.TagReader',
534+ byte_arrays=True)
535+ try:
536+ loop.run()
537+ except KeyboardInterrupt:
538+ print "Exiting..."
539+ loop.quit()
540+
541+if __name__ == '__main__':
542+ from optparse import OptionParser
543+
544+ parser = OptionParser()
545+ parser.add_option("-q", default=True,
546+ action="store_false", dest="verbose",
547+ help="be quiet, only print errors")
548+ parser.add_option("-d", default=False,
549+ action="store_true", dest="debug",
550+ help="print debug messages")
551+ parser.add_option("-f", type="string",
552+ action="store", dest="logfile",
553+ help="write log messages to LOGFILE")
554+
555+ global options
556+ options, args = parser.parse_args()
557+
558+ verbosity = logging.INFO if options.verbose else logging.ERROR
559+ verbosity = logging.DEBUG if options.debug else verbosity
560+ logging.basicConfig(level=verbosity, format='%(message)s')
561+
562+ if options.logfile:
563+ logfile_format = '%(asctime)s %(levelname)-5s [%(name)s] %(message)s'
564+ logfile = logging.FileHandler(options.logfile, "w")
565+ logfile.setFormatter(logging.Formatter(logfile_format))
566+ logfile.setLevel(logging.DEBUG)
567+ logging.getLogger('').addHandler(logfile)
568+
569+ try:
570+ main()
571+ except KeyboardInterrupt:
572+ pass
573+
574
575=== added file 'examples/dbus_examples/tagtool.py'
576--- examples/dbus_examples/tagtool.py 1970-01-01 00:00:00 +0000
577+++ examples/dbus_examples/tagtool.py 2011-01-04 16:28:41 +0000
578@@ -0,0 +1,296 @@
579+# -----------------------------------------------------------------------------
580+# Copyright 2011 Alexander Knaub <sanyok.og@googlemail.com>
581+#
582+# Licensed under the EUPL, Version 1.1 or - as soon they
583+# will be approved by the European Commission - subsequent
584+# versions of the EUPL (the "Licence");
585+# You may not use this work except in compliance with the
586+# Licence.
587+# You may obtain a copy of the Licence at:
588+#
589+# http://ec.europa.eu/idabc/eupl
590+#
591+# Unless required by applicable law or agreed to in
592+# writing, software distributed under the Licence is
593+# distributed on an "AS IS" basis,
594+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
595+# express or implied.
596+# See the Licence for the specific language governing
597+# permissions and limitations under the Licence.
598+# -----------------------------------------------------------------------------
599+
600+import logging
601+log = logging.getLogger()
602+
603+import os
604+import sys
605+import time
606+import string
607+import pickle
608+import gobject
609+import dbus.mainloop.glib
610+
611+sys.path.insert(1, os.path.split(sys.path[0])[0])
612+import nfc
613+import nfc.ndef
614+
615+BUS_NAME = "org.nfcpy.TagReader"
616+
617+def make_printable(data):
618+ printable = string.digits + string.letters + string.punctuation + ' '
619+ return ''.join([c if c in printable else '.' for c in data])
620+
621+def format_data(data):
622+ s = []
623+ for i in range(0, len(data), 16):
624+ s.append(" %04x: " % i)
625+ s[-1] += ' '.join(["%02x" % ord(c) for c in data[i:i+16]]) + ' '
626+ s[-1] += (8 + 16*3 - len(s[-1])) * ' '
627+ s[-1] += make_printable(data[i:i+16])
628+ return '\n'.join(s)
629+
630+
631+class ReaderWriterClient:
632+ def __init__(self, mainloop, reader):
633+ self._loop = mainloop
634+ self._message = None
635+ self._reader = reader
636+ self._loopmode = False
637+ self._binary = False
638+ self._copying = False
639+
640+
641+ @property
642+ def loopmode(self):
643+ log.debug("returning loopmode = " + str(self._loopmode))
644+ return self._loopmode
645+
646+ @loopmode.setter
647+ def loopmode(self, value):
648+ log.debug("set loopmode to " + str(value))
649+ self._loopmode = bool(value)
650+
651+
652+ def set_binary(self, value):
653+ self._binary = value
654+
655+
656+ def save_ndef(self, ndef_msg_string):
657+ if len(ndef_msg_string):
658+ self._message = nfc.ndef.Message(str(ndef_msg_string))
659+ else:
660+ log.info("Empty message received!")
661+
662+ def show_ndef(self): # , ndef_msg_string
663+ print format_data(self._message.tostring())
664+ print "NDEF records:"
665+ for index, record in enumerate(self._message):
666+ record.data = make_printable(record.data)
667+ print " [%d] type = %s" %(index, record.type)
668+ print " [%d] name = %s" %(index, record.name)
669+ print " [%d] data = %s" %(index, record.data)
670+
671+ def show_tag(self, tag_str):
672+ self._tag_info = pickle.loads(tag_str)
673+
674+ tt3_card_map = {
675+ "\x00\xF0": "FeliCa Lite RC-S965",
676+ "\x01\xE0": "FeliCa Plug RC-S801/RC-S802",
677+ "\x01\x20": "FeliCa Card RC-S976F [212/424kbps]",
678+ "\x03\x01": "FeliCa Card RC-S860 [212kbps, 4KB FEPROM]",
679+ }
680+ print " " + tt3_card_map.get(self._tag_info.get('pmm')[0:2],
681+ "unknown card type")
682+ if self._tag_info.get('capacity', 0):
683+ print "NDEF content"
684+ print " version = %s" % self._tag_info['version']
685+ print " writeable = %s" % ("no", "yes")[self._tag_info['writeable']]
686+ print " capacity = %d byte" % self._tag_info['capacity']
687+ print " data size = %d byte" % self._tag_info['size']
688+ print "NDEF container present"
689+ # show content:
690+ if self._tag_info['size']:
691+ if self._message:
692+ self.show_ndef()
693+ else:
694+ print "No message",
695+ time.sleep(0.5)
696+ if self._message:
697+ print "received yet. Waiting..."
698+ self.show_ndef()
699+ else:
700+ print "could be received."
701+
702+ else:
703+ print "No message available"
704+ if not self.loopmode:
705+ self._loop.quit()
706+
707+ def copy_tag(self, ndef_msg_string):
708+ self._message = nfc.ndef.Message(str(ndef_msg_string))
709+ log.info("copied {0} byte <= tag".format(len(ndef_msg_string)))
710+
711+ raw_input("Place the destination tag on the reader "
712+ + "and press ENTER.")
713+ msg_string = self._message.tostring()
714+ self._reader.WriteNDEF(dbus.ByteArray(msg_string))
715+ log.info("copied {0} byte => tag".format(len(msg_string)))
716+ if self.loopmode:
717+ time.sleep(1)
718+ else:
719+ self._loop.quit()
720+
721+ def dump_tag(self, ndef_msg_string):
722+ data = ndef_msg_string
723+ if not self._binary:
724+ data = data.encode("hex")
725+ print data
726+ if not self.loopmode:
727+ self._loop.quit()
728+
729+ def load_tag(self):
730+ print "Enter Data"
731+ if not self._binary:
732+ data = sys.stdin.readlines()
733+ data = ''.join([l.strip() for l in data])
734+ data = data.decode("hex")
735+ else:
736+ data = sys.stdin.read()
737+ print "You entered " + data
738+ self._reader.WriteNDEF(dbus.ByteArray(data))
739+ log.info("Data written to the tag")
740+ if not options.loopmode:
741+ self._loop.quit()
742+
743+ def format_tag(self):
744+ cont = raw_input("This will delete all data on the tag. "
745+ + "Continue? Y/N ")
746+
747+ if cont not in "yY":
748+ return
749+ # call method on reader object:
750+ self._format_running = True
751+ while True:
752+ success = self._reader.FormatTag()
753+ # include this parameters for async. call:
754+ # reply_handler=self.format_reply_handler,
755+ # error_handler=self.format_error_handler
756+ if success:
757+ print "Formatting successful"
758+ else:
759+ print "Formatting failed"
760+ if not self.loopmode:
761+ print "No loop. exiting"
762+ break
763+ else:
764+ print "go on in 1 sec."
765+ time.sleep(1)
766+
767+ # This method is needed if formatting method of the reader object is
768+ # called asynchronous (non-blocking)
769+ def format_reply_handler(self, success):
770+ if success:
771+ log.info("Formatting successful")
772+ else:
773+ log.info("Formatting failed")
774+ self._format_running = False
775+ if not self._loopmode:
776+ self._loop.quit()
777+
778+ # This method is needed if formatting method of the reader object is
779+ # called asynchronous (non-blocking)
780+ def format_error_handler(self, error):
781+ log.warning("Error occured: " + str(error))
782+ self._format_running = False
783+ self._loop.quit()
784+
785+
786+def main():
787+ log.debug("starting...")
788+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
789+ bus = dbus.SystemBus()
790+ object = bus.get_object(BUS_NAME, "/nfcpy/tagreader")
791+ loop = gobject.MainLoop()
792+ client = ReaderWriterClient(mainloop=loop, reader=object)
793+ client.loopmode = options.loopmode
794+ log.debug("loopmode set to " + str(client.loopmode))
795+ if options.command == "show":
796+ # Connect reader's signals to the show methods
797+ object.connect_to_signal(signal_name="NDEFMessage",
798+ handler_function=client.save_ndef,
799+ dbus_interface='org.nfcpy.TagReader',
800+ byte_arrays=True)
801+ object.connect_to_signal(signal_name="TagInfo",
802+ handler_function=client.show_tag,
803+ dbus_interface='org.nfcpy.TagReader',
804+ byte_arrays=True)
805+ loop.run()
806+
807+ elif options.command == "format":
808+ # Reader/writer method will be called by client
809+ client.format_tag()
810+ elif options.command == "copy":
811+ object.connect_to_signal(signal_name="NDEFMessage",
812+ handler_function=client.copy_tag,
813+ dbus_interface='org.nfcpy.TagReader',
814+ byte_arrays=True)
815+ loop.run()
816+ elif options.command == "dump":
817+ client.set_binary(options.binary)
818+ object.connect_to_signal(signal_name="NDEFMessage",
819+ handler_function=client.dump_tag,
820+ dbus_interface='org.nfcpy.TagReader',
821+ byte_arrays=True)
822+ loop.run()
823+ elif options.command == "load":
824+ client.set_binary(options.binary)
825+ client.load_tag()
826+ else:
827+ log.error("unknown command '{0}'".format(options.command))
828+
829+if __name__ == '__main__':
830+ from optparse import OptionParser, OptionGroup
831+
832+ usage = ["Usage: %prog [options] command\n",
833+ "Commands:",
834+ " show - pretty print NDEF data",
835+ " dump - print NDEF data to stdout",
836+ " load - load NDEF data from stdin",
837+ " copy - copy NDEF data between tags",
838+ " format - format NDEF partition on tag"]
839+
840+ parser = OptionParser('\n'.join(usage), version="%prog 0.1")
841+ parser.add_option("-l", default=False,
842+ action="store_true", dest="loopmode",
843+ help="run command in loop mode")
844+ parser.add_option("-b", default=False,
845+ action="store_true", dest="binary",
846+ help="use binary format for dump/load")
847+ parser.add_option("-q", default=True,
848+ action="store_false", dest="verbose",
849+ help="be quiet, only print errors")
850+ parser.add_option("-d", default=False,
851+ action="store_true", dest="debug",
852+ help="print debug messages")
853+ parser.add_option("-f", type="string",
854+ action="store", dest="logfile",
855+ help="write log messages to LOGFILE")
856+
857+ global options
858+ options, args = parser.parse_args()
859+ if len(args) > 0: options.command = args[0]
860+ else: options.command = "print"
861+
862+ verbosity = logging.INFO if options.verbose else logging.ERROR
863+ verbosity = logging.DEBUG if options.debug else verbosity
864+ logging.basicConfig(level=verbosity, format='%(message)s')
865+
866+ if options.logfile:
867+ logfile_format = '%(asctime)s %(levelname)-5s [%(name)s] %(message)s'
868+ logfile = logging.FileHandler(options.logfile, "w")
869+ logfile.setFormatter(logging.Formatter(logfile_format))
870+ logfile.setLevel(logging.DEBUG)
871+ logging.getLogger('').addHandler(logfile)
872+
873+ main()
874+

Subscribers

People subscribed via source and target branches