Merge lp:~sanyok-og/nfcpy/dev-dbus into lp:nfcpy
- dev-dbus
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stephen Tiedemann | Approve | ||
Review via email: mp+45138@code.launchpad.net |
Commit message
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 | + |