Arman Uguray | 77486dc | 2013-10-09 21:40:40 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | import cmd |
| 8 | import dbus |
| 9 | import dbus.exceptions |
| 10 | import dbus.mainloop.glib |
| 11 | import gobject |
| 12 | import threading |
| 13 | |
| 14 | from functools import wraps |
| 15 | |
| 16 | |
| 17 | DBUS_ERROR = 'org.freedesktop.DBus.Error' |
| 18 | NEARD_PATH = '/org/neard/' |
| 19 | PROMPT = 'NFC> ' |
| 20 | |
| 21 | class NfcClientException(Exception): |
| 22 | """Exception class for exceptions thrown by NfcClient.""" |
| 23 | |
| 24 | |
| 25 | def print_message(message, newlines=2): |
| 26 | """ |
| 27 | Prints the given message with extra wrapping newline characters. |
| 28 | |
| 29 | @param message: Message to print. |
| 30 | @param newlines: Integer, specifying the number of '\n' characters that |
| 31 | should be padded at the beginning and end of |message| before |
| 32 | being passed to "print". |
| 33 | |
| 34 | """ |
| 35 | padding = newlines * '\n' |
| 36 | message = padding + message + padding |
| 37 | print message |
| 38 | |
| 39 | |
| 40 | def handle_errors(func): |
| 41 | """ |
| 42 | Decorator for handling exceptions that are commonly raised by many of the |
| 43 | methods in NfcClient. |
| 44 | |
| 45 | @param func: The function this decorator is wrapping. |
| 46 | |
| 47 | """ |
| 48 | @wraps(func) |
| 49 | def _error_handler(*args): |
| 50 | try: |
| 51 | return func(*args) |
| 52 | except dbus.exceptions.DBusException as e: |
| 53 | if e.get_dbus_name() == DBUS_ERROR + '.ServiceUnknown': |
| 54 | print_message('neard may have crashed or disappeared. ' |
| 55 | 'Check if neard is running and run "initialize" ' |
| 56 | 'from this shell.') |
| 57 | return |
| 58 | if e.get_dbus_name() == DBUS_ERROR + '.UnknownObject': |
| 59 | print_message('Could not find object.') |
| 60 | return |
| 61 | print_message(str(e)) |
| 62 | except Exception as e: |
| 63 | print_message(str(e)) |
| 64 | return _error_handler |
| 65 | |
| 66 | |
| 67 | class NfcClient(object): |
| 68 | """ |
| 69 | neard D-Bus client |
| 70 | |
| 71 | """ |
| 72 | NEARD_SERVICE_NAME = 'org.neard' |
| 73 | IMANAGER = NEARD_SERVICE_NAME + '.Manager' |
| 74 | IADAPTER = NEARD_SERVICE_NAME + '.Adapter' |
| 75 | ITAG = NEARD_SERVICE_NAME + '.Tag' |
| 76 | IRECORD = NEARD_SERVICE_NAME + '.Record' |
| 77 | IDEVICE = NEARD_SERVICE_NAME + '.Device' |
| 78 | |
| 79 | def __init__(self): |
| 80 | self._mainloop = None |
| 81 | self._mainloop_thread = None |
| 82 | self._adapters = {} |
| 83 | self._adapter_property_handler_matches = {} |
| 84 | |
| 85 | def begin(self): |
| 86 | """ |
| 87 | Starts the D-Bus client. |
| 88 | |
| 89 | """ |
| 90 | # Here we run a GLib MainLoop in its own thread, so that the client can |
| 91 | # listen to D-Bus signals while keeping the console interactive. |
| 92 | self._dbusmainloop = dbus.mainloop.glib.DBusGMainLoop( |
| 93 | set_as_default=True) |
| 94 | dbus.mainloop.glib.threads_init() |
| 95 | gobject.threads_init() |
| 96 | |
| 97 | def _mainloop_thread_func(): |
| 98 | self._mainloop = gobject.MainLoop() |
| 99 | context = self._mainloop.get_context() |
| 100 | self._run_loop = True |
| 101 | while self._run_loop: |
| 102 | context.iteration(True) |
| 103 | self._mainloop_thread = threading.Thread(None, _mainloop_thread_func) |
| 104 | self._mainloop_thread.start() |
| 105 | |
| 106 | self._bus = dbus.SystemBus() |
| 107 | self.setup_manager() |
| 108 | |
| 109 | def end(self): |
| 110 | """ |
| 111 | Stops the D-Bus client. |
| 112 | |
| 113 | """ |
| 114 | self._run_loop = False |
| 115 | self._mainloop.quit() |
| 116 | self._mainloop_thread.join() |
| 117 | |
| 118 | def restart(self): |
| 119 | """Reinitializes the NFC client.""" |
| 120 | self.setup_manager() |
| 121 | |
| 122 | @handle_errors |
| 123 | def _get_manager_proxy(self): |
| 124 | return dbus.Interface( |
| 125 | self._bus.get_object(self.NEARD_SERVICE_NAME, '/'), |
| 126 | self.IMANAGER) |
| 127 | |
| 128 | @handle_errors |
| 129 | def _get_adapter_proxy(self, adapter): |
| 130 | return dbus.Interface( |
| 131 | self._bus.get_object(self.NEARD_SERVICE_NAME, adapter), |
| 132 | self.IADAPTER) |
| 133 | |
| 134 | def _get_cached_adapter_proxy(self, adapter): |
| 135 | adapter_proxy = self._adapters.get(adapter, None) |
| 136 | if not adapter_proxy: |
| 137 | raise NfcClientException('Adapter "' + adapter + '" not found.') |
| 138 | return adapter_proxy |
| 139 | |
| 140 | |
| 141 | @handle_errors |
| 142 | def _get_tag_proxy(self, tag): |
| 143 | return dbus.Interface( |
| 144 | self._bus.get_object(self.NEARD_SERVICE_NAME, tag), |
| 145 | self.ITAG) |
| 146 | |
| 147 | @handle_errors |
| 148 | def _get_device_proxy(self, device): |
| 149 | return dbus.Interface( |
| 150 | self._bus.get_object(self.NEARD_SERVICE_NAME, device), |
| 151 | self.IDEVICE) |
| 152 | |
| 153 | @handle_errors |
| 154 | def _get_record_proxy(self, record): |
| 155 | return dbus.Interface( |
| 156 | self._bus.get_object(self.NEARD_SERVICE_NAME, record), |
| 157 | self.IRECORD) |
| 158 | |
| 159 | @handle_errors |
| 160 | def _get_adapter_properties(self, adapter): |
| 161 | adapter_proxy = self._get_cached_adapter_proxy(adapter) |
| 162 | return adapter_proxy.GetProperties() |
| 163 | |
| 164 | def _get_adapters(self): |
| 165 | props = self._manager.GetProperties() |
| 166 | return props.get('Adapters', None) |
| 167 | |
| 168 | def setup_manager(self): |
| 169 | """ |
| 170 | Creates a manager proxy and subscribes to adapter signals. This method |
| 171 | will also initialize proxies for adapters if any are available. |
| 172 | |
| 173 | """ |
| 174 | # Create the manager proxy. |
| 175 | self._adapters.clear() |
| 176 | self._manager = self._get_manager_proxy() |
| 177 | if not self._manager: |
| 178 | print_message('Failed to create a proxy to the Manager interface.') |
| 179 | return |
| 180 | |
| 181 | # Listen to the adapter added and removed signals. |
| 182 | self._manager.connect_to_signal( |
| 183 | 'AdapterAdded', |
| 184 | lambda adapter: self.register_adapter(str(adapter))) |
| 185 | self._manager.connect_to_signal( |
| 186 | 'AdapterRemoved', |
| 187 | lambda adapter: self.unregister_adapter(str(adapter))) |
| 188 | |
| 189 | # See if there are any adapters and create proxies for each. |
| 190 | adapters = self._get_adapters() |
| 191 | if adapters: |
| 192 | for adapter in adapters: |
| 193 | self.register_adapter(adapter) |
| 194 | |
| 195 | def register_adapter(self, adapter): |
| 196 | """ |
| 197 | Registers an adapter proxy with the given object path and subscribes to |
| 198 | adapter signals. |
| 199 | |
| 200 | @param adapter: string, containing the adapter's D-Bus object path. |
| 201 | |
| 202 | """ |
| 203 | print_message('Added adapter: ' + adapter) |
| 204 | adapter_proxy = self._get_adapter_proxy(adapter) |
| 205 | self._adapters[adapter] = adapter_proxy |
| 206 | |
| 207 | # Tag found/lost currently don't get fired. Monitor property changes |
| 208 | # instead. |
| 209 | if self._adapter_property_handler_matches.get(adapter, None) is None: |
| 210 | self._adapter_property_handler_matches[adapter] = ( |
| 211 | adapter_proxy.connect_to_signal( |
| 212 | 'PropertyChanged', |
| 213 | (lambda name, value: |
| 214 | self._adapter_property_changed_signal( |
| 215 | adapter, name, value)))) |
| 216 | |
| 217 | def unregister_adapter(self, adapter): |
| 218 | """ |
| 219 | Removes the adapter proxy for the given object path from the internal |
| 220 | cache of adapters. |
| 221 | |
| 222 | @param adapter: string, containing the adapter's D-Bus object path. |
| 223 | |
| 224 | """ |
| 225 | print_message('Removed adapter: ' + adapter) |
| 226 | match = self._adapter_property_handler_matches.get(adapter, None) |
| 227 | if match is not None: |
| 228 | match.remove() |
| 229 | self._adapter_property_handler_matches.pop(adapter) |
| 230 | self._adapters.pop(adapter) |
| 231 | |
| 232 | def _adapter_property_changed_signal(self, adapter, name, value): |
| 233 | if name == 'Tags' or name == 'Devices': |
| 234 | print_message('Found ' + name + ': ' + |
| 235 | self._dbus_array_to_string(value)) |
Arman Uguray | 77486dc | 2013-10-09 21:40:40 -0700 | [diff] [blame] | 236 | |
| 237 | @handle_errors |
| 238 | def show_adapters(self): |
| 239 | """ |
| 240 | Prints the D-Bus object paths of all adapters that are available. |
| 241 | |
| 242 | """ |
| 243 | adapters = self._get_adapters() |
| 244 | if not adapters: |
| 245 | print_message('No adapters found.') |
| 246 | return |
| 247 | for adapter in adapters: |
| 248 | print_message(' ' + str(adapter), newlines=0) |
| 249 | print |
| 250 | |
| 251 | def _dbus_array_to_string(self, array): |
| 252 | string = '[ ' |
| 253 | for value in array: |
| 254 | string += ' ' + str(value) + ', ' |
| 255 | string += ' ]' |
| 256 | return string |
| 257 | |
| 258 | def print_adapter_status(self, adapter): |
| 259 | """ |
| 260 | Prints the properties of the given adapter. |
| 261 | |
| 262 | @param adapter: string, containing the adapter's D-Bus object path. |
| 263 | |
| 264 | """ |
| 265 | props = self._get_adapter_properties(adapter) |
| 266 | if not props: |
| 267 | return |
| 268 | print_message('Status ' + adapter + ': ', newlines=0) |
| 269 | for key, value in props.iteritems(): |
| 270 | if type(value) == dbus.Array: |
| 271 | value = self._dbus_array_to_string(value) |
| 272 | else: |
| 273 | value = str(value) |
| 274 | print_message(' ' + key + ' = ' + value, newlines=0) |
| 275 | print |
| 276 | |
| 277 | @handle_errors |
| 278 | def set_powered(self, adapter, powered): |
| 279 | """ |
| 280 | Enables or disables the adapter. |
| 281 | |
| 282 | @param adapter: string, containing the adapter's D-Bus object path. |
| 283 | @param powered: boolean that dictates whether the adapter will be |
| 284 | enabled or disabled. |
| 285 | |
| 286 | """ |
| 287 | adapter_proxy = self._get_cached_adapter_proxy(adapter) |
| 288 | if not adapter_proxy: |
| 289 | return |
| 290 | adapter_proxy.SetProperty('Powered', powered) |
| 291 | |
| 292 | @handle_errors |
| 293 | def start_polling(self, adapter): |
| 294 | """ |
| 295 | Starts polling for nearby tags and devices in "Initiator" mode. |
| 296 | |
| 297 | @param adapter: string, containing the adapter's D-Bus object path. |
| 298 | |
| 299 | """ |
| 300 | adapter_proxy = self._get_cached_adapter_proxy(adapter) |
| 301 | adapter_proxy.StartPollLoop('Initiator') |
| 302 | print_message('Started polling.') |
| 303 | |
| 304 | @handle_errors |
| 305 | def stop_polling(self, adapter): |
| 306 | """ |
| 307 | Stops polling for nearby tags and devices. |
| 308 | |
| 309 | @param adapter: string, containing the adapter's D-Bus object path. |
| 310 | |
| 311 | """ |
| 312 | adapter_proxy = self._get_cached_adapter_proxy(adapter) |
| 313 | adapter_proxy.StopPollLoop() |
| 314 | self._polling_stopped = True |
| 315 | print_message('Stopped polling.') |
| 316 | |
| 317 | @handle_errors |
| 318 | def show_tag_data(self, tag): |
| 319 | """ |
| 320 | Prints the properties of the given tag, as well as the contents of any |
| 321 | records associated with it. |
| 322 | |
| 323 | @param tag: string, containing the tag's D-Bus object path. |
| 324 | |
| 325 | """ |
| 326 | tag_proxy = self._get_tag_proxy(tag) |
| 327 | if not tag_proxy: |
| 328 | print_message('Tag "' + tag + '" not found.') |
| 329 | return |
| 330 | props = tag_proxy.GetProperties() |
| 331 | print_message('Tag ' + tag + ': ', newlines=1) |
| 332 | for key, value in props.iteritems(): |
| 333 | if key != 'Records': |
| 334 | print_message(' ' + key + ' = ' + str(value), newlines=0) |
| 335 | records = props['Records'] |
| 336 | if not records: |
| 337 | return |
| 338 | print_message('Records: ', newlines=1) |
| 339 | for record in records: |
| 340 | self.show_record_data(str(record)) |
| 341 | print |
| 342 | |
| 343 | @handle_errors |
| 344 | def show_device_data(self, device): |
| 345 | """ |
| 346 | Prints the properties of the given device, as well as the contents of |
| 347 | any records associated with it. |
| 348 | |
| 349 | @param device: string, containing the device's D-Bus object path. |
| 350 | |
| 351 | """ |
| 352 | device_proxy = self._get_device_proxy(device) |
| 353 | if not device_proxy: |
| 354 | print_message('Device "' + device + '" not found.') |
| 355 | return |
| 356 | records = device_proxy.GetProperties()['Records'] |
| 357 | if not records: |
| 358 | print_message('No records on device.') |
| 359 | return |
| 360 | print_message('Records: ', newlines=1) |
| 361 | for record in records: |
| 362 | self.show_record_data(str(record)) |
| 363 | print |
| 364 | |
| 365 | @handle_errors |
| 366 | def show_record_data(self, record): |
| 367 | """ |
| 368 | Prints the contents of the given record. |
| 369 | |
| 370 | @param record: string, containing the record's D-Bus object path. |
| 371 | |
| 372 | """ |
| 373 | record_proxy = self._get_record_proxy(record) |
| 374 | if not record_proxy: |
| 375 | print_message('Record "' + record + '" not found.') |
| 376 | return |
| 377 | props = record_proxy.GetProperties() |
| 378 | print_message('Record ' + record + ': ', newlines=1) |
| 379 | for key, value in props.iteritems(): |
| 380 | print ' ' + key + ' = ' + value |
| 381 | print |
| 382 | |
| 383 | def _create_record_data(self, record_type, params): |
| 384 | if record_type == 'Text': |
| 385 | possible_keys = [ 'Encoding', 'Language', 'Representation' ] |
| 386 | tag_data = { 'Type': 'Text' } |
| 387 | elif record_type == 'URI': |
| 388 | possible_keys = [ 'URI' ] |
| 389 | tag_data = { 'Type': 'URI' } |
| 390 | else: |
| 391 | print_message('Writing record type "' + record_type + |
| 392 | '" currently not supported.') |
| 393 | return None |
| 394 | for key, value in params.iteritems(): |
| 395 | if key in possible_keys: |
| 396 | tag_data[key] = value |
| 397 | return tag_data |
| 398 | |
| 399 | @handle_errors |
| 400 | def write_tag(self, tag, record_type, params): |
| 401 | """ |
| 402 | Writes an NDEF record to the given tag. |
| 403 | |
| 404 | @param tag: string, containing the tag's D-Bus object path. |
| 405 | @param record_type: The type of the record, e.g. Text or URI. |
| 406 | @param params: dictionary, containing the parameters of the NDEF. |
| 407 | |
| 408 | """ |
| 409 | tag_data = self._create_record_data(record_type, params) |
| 410 | if not tag_data: |
| 411 | return |
| 412 | tag_proxy = self._get_tag_proxy(tag) |
| 413 | if not tag_proxy: |
| 414 | print_message('Tag "' + tag + '" not found.') |
| 415 | return |
| 416 | tag_proxy.Write(tag_data) |
| 417 | print_message('Tag written!') |
| 418 | |
| 419 | @handle_errors |
| 420 | def push_to_device(self, device, record_type, params): |
| 421 | """ |
| 422 | Pushes an NDEF record to the given device. |
| 423 | |
| 424 | @param device: string, containing the device's D-Bus object path. |
| 425 | @param record_type: The type of the record, e.g. Text or URI. |
| 426 | @param params: dictionary, containing the parameters of the NDEF. |
| 427 | |
| 428 | """ |
| 429 | record_data = self._create_record_data(record_type, params) |
| 430 | if not record_data: |
| 431 | return |
| 432 | device_proxy = self._get_device_proxy(device) |
| 433 | if not device_proxy: |
| 434 | print_message('Device "' + device + '" not found.') |
| 435 | return |
| 436 | device_proxy.Push(record_data) |
| 437 | print_message('NDEF pushed to device!') |
| 438 | |
| 439 | |
| 440 | class NfcConsole(cmd.Cmd): |
| 441 | """ |
| 442 | Interactive console to interact with the NFC daemon. |
| 443 | |
| 444 | """ |
| 445 | def __init__(self): |
| 446 | cmd.Cmd.__init__(self) |
| 447 | self.prompt = PROMPT |
| 448 | |
| 449 | def begin(self): |
| 450 | """ |
| 451 | Starts the interactive shell. |
| 452 | |
| 453 | """ |
| 454 | print_message('NFC console! Run "help" for a list of commands.', |
| 455 | newlines=1) |
| 456 | self._nfc_client = NfcClient() |
| 457 | self._nfc_client.begin() |
| 458 | self.cmdloop() |
| 459 | |
| 460 | def can_exit(self): |
| 461 | """Override""" |
| 462 | return True |
| 463 | |
| 464 | def do_initialize(self, args): |
| 465 | """Handles "initialize".""" |
| 466 | if args: |
| 467 | print_message('Command "initialize" expects no arguments.') |
| 468 | return |
| 469 | self._nfc_client.restart() |
| 470 | |
| 471 | def help_initialize(self): |
| 472 | """Prints the help message for "initialize".""" |
| 473 | print_message('Initializes the neard D-Bus client. This can be ' |
| 474 | 'run many times to restart the client in case of ' |
| 475 | 'neard failures or crashes.') |
| 476 | |
| 477 | def do_adapters(self, args): |
| 478 | """Handles "adapters".""" |
| 479 | if args: |
| 480 | print_message('Command "adapters" expects no arguments.') |
| 481 | return |
| 482 | self._nfc_client.show_adapters() |
| 483 | |
| 484 | def help_adapters(self): |
| 485 | """Prints the help message for "adapters".""" |
| 486 | print_message('Displays the D-Bus object paths of the available ' |
| 487 | 'adapter objects.') |
| 488 | |
| 489 | def do_adapter_status(self, args): |
| 490 | """Handles "adapter_status".""" |
| 491 | args = args.strip().split(' ') |
| 492 | if len(args) != 1 or not args[0]: |
| 493 | print_message('Usage: adapter_status <adapter>') |
| 494 | return |
| 495 | self._nfc_client.print_adapter_status(NEARD_PATH + args[0]) |
| 496 | |
| 497 | def help_adapter_status(self): |
| 498 | """Prints the help message for "adapter_status".""" |
| 499 | print_message('Returns the properties of the given NFC adapter.\n\n' |
| 500 | ' Ex: "adapter_status nfc0"') |
| 501 | |
| 502 | def do_enable_adapter(self, args): |
| 503 | """Handles "enable_adapter".""" |
| 504 | args = args.strip().split(' ') |
| 505 | if len(args) != 1 or not args[0]: |
| 506 | print_message('Usage: enable_adapter <adapter>') |
| 507 | return |
| 508 | self._nfc_client.set_powered(NEARD_PATH + args[0], True) |
| 509 | |
| 510 | def help_enable_adapter(self): |
| 511 | """Prints the help message for "enable_adapter".""" |
| 512 | print_message('Powers up the adapter. Ex: "enable_adapter nfc0"') |
| 513 | |
| 514 | def do_disable_adapter(self, args): |
| 515 | """Handles "disable_adapter".""" |
| 516 | args = args.strip().split(' ') |
| 517 | if len(args) != 1 or not args[0]: |
| 518 | print_message('Usage: disable_adapter <adapter>') |
| 519 | return |
| 520 | self._nfc_client.set_powered(NEARD_PATH + args[0], False) |
| 521 | |
| 522 | def help_disable_adapter(self): |
| 523 | """Prints the help message for "disable_adapter".""" |
| 524 | print_message('Powers down the adapter. Ex: "disable_adapter nfc0"') |
| 525 | |
| 526 | def do_start_poll(self, args): |
| 527 | """Handles "start_poll".""" |
| 528 | args = args.strip().split(' ') |
| 529 | if len(args) != 1 or not args[0]: |
| 530 | print_message('Usage: start_poll <adapter>') |
| 531 | return |
| 532 | self._nfc_client.start_polling(NEARD_PATH + args[0]) |
| 533 | |
| 534 | def help_start_poll(self): |
| 535 | """Prints the help message for "start_poll".""" |
| 536 | print_message('Initiates a poll loop.\n\n Ex: "start_poll nfc0"') |
| 537 | |
| 538 | def do_stop_poll(self, args): |
| 539 | """Handles "stop_poll".""" |
| 540 | args = args.split(' ') |
| 541 | if len(args) != 1 or not args[0]: |
| 542 | print_message('Usage: stop_poll <adapter>') |
| 543 | return |
| 544 | self._nfc_client.stop_polling(NEARD_PATH + args[0]) |
| 545 | |
| 546 | def help_stop_poll(self): |
| 547 | """Prints the help message for "stop_poll".""" |
| 548 | print_message('Stops a poll loop.\n\n Ex: "stop_poll nfc0"') |
| 549 | |
| 550 | def do_read_tag(self, args): |
| 551 | """Handles "read_tag".""" |
| 552 | args = args.strip().split(' ') |
| 553 | if len(args) != 1 or not args[0]: |
| 554 | print_message('Usage read_tag <tag>') |
| 555 | return |
| 556 | self._nfc_client.show_tag_data(NEARD_PATH + args[0]) |
| 557 | |
| 558 | def help_read_tag(self): |
| 559 | """Prints the help message for "read_tag".""" |
| 560 | print_message('Reads the contents of a tag. Ex: read_tag nfc0/tag0') |
| 561 | |
| 562 | def _parse_record_args(self, record_type, args): |
| 563 | if record_type == 'Text': |
| 564 | if len(args) < 5: |
| 565 | print_message('Usage: write_tag <tag> Text <encoding> ' |
| 566 | '<language> <representation>') |
| 567 | return None |
| 568 | if args[2] not in [ 'UTF-8', 'UTF-16' ]: |
| 569 | print_message('Encoding must be one of "UTF-8" or "UTF-16".') |
| 570 | return None |
| 571 | return { |
| 572 | 'Encoding': args[2], |
| 573 | 'Language': args[3], |
| 574 | 'Representation': ' '.join(args[4:]) |
| 575 | } |
| 576 | if record_type == 'URI': |
| 577 | if len(args) != 3: |
| 578 | print_message('Usage: write_tag <tag> URI <uri>') |
| 579 | return None |
| 580 | return { |
| 581 | 'URI': args[2] |
| 582 | } |
| 583 | print_message('Only types "Text" and "URI" are supported by this ' |
| 584 | 'script.') |
| 585 | return None |
| 586 | |
| 587 | def do_write_tag(self, args): |
| 588 | """Handles "write_tag".""" |
| 589 | args = args.strip().split(' ') |
| 590 | if len(args) < 3: |
| 591 | print_message('Usage: write_tag <tag> [params]') |
| 592 | return |
| 593 | record_type = args[1] |
| 594 | params = self._parse_record_args(record_type, args) |
| 595 | if not params: |
| 596 | return |
| 597 | self._nfc_client.write_tag(NEARD_PATH + args[0], |
| 598 | record_type, params) |
| 599 | |
| 600 | def help_write_tag(self): |
| 601 | """Prints the help message for "write_tag".""" |
| 602 | print_message('Writes the given data to a tag. Usage:\n' |
| 603 | ' write_tag <tag> Text <encoding> <language> ' |
| 604 | '<representation>\n write_tag <tag> URI <uri>') |
| 605 | |
| 606 | def do_read_device(self, args): |
| 607 | """Handles "read_device".""" |
| 608 | args = args.strip().split(' ') |
| 609 | if len(args) != 1 or not args[0]: |
| 610 | print_message('Usage read_device <device>') |
| 611 | return |
| 612 | self._nfc_client.show_device_data(NEARD_PATH + args[0]) |
| 613 | |
| 614 | def help_read_device(self): |
| 615 | """Prints the help message for "read_device".""" |
| 616 | print_message('Reads the contents of a device. Ex: read_device ' |
| 617 | 'nfc0/device0') |
| 618 | |
| 619 | def do_push_to_device(self, args): |
| 620 | """Handles "push_to_device".""" |
| 621 | args = args.strip().split(' ') |
| 622 | if len(args) < 3: |
| 623 | print_message('Usage: push_to_device <device> [params]') |
| 624 | return |
| 625 | record_type = args[1] |
| 626 | params = self._parse_record_args(record_type, args) |
| 627 | if not params: |
| 628 | return |
| 629 | self._nfc_client.push_to_device(NEARD_PATH + args[0], |
| 630 | record_type, params) |
| 631 | |
| 632 | def help_push_to_device(self): |
| 633 | """Prints the help message for "push_to_device".""" |
| 634 | print_message('Pushes the given data to a device. Usage:\n' |
| 635 | ' push_to_device <device> Text <encoding> <language> ' |
| 636 | '<representation>\n push_to_device <device> URI <uri>') |
| 637 | |
| 638 | def do_exit(self, args): |
| 639 | """ |
| 640 | Handles the 'exit' command. |
| 641 | |
| 642 | @param args: Arguments to the command. Unused. |
| 643 | |
| 644 | """ |
| 645 | if args: |
| 646 | print_message('Command "exit" expects no arguments.') |
| 647 | return |
| 648 | resp = raw_input('Are you sure? (yes/no): ') |
| 649 | if resp == 'yes': |
| 650 | print_message('Goodbye!') |
| 651 | self._nfc_client.end() |
| 652 | return True |
| 653 | if resp != 'no': |
| 654 | print_message('Did not understand: ' + resp) |
| 655 | return False |
| 656 | |
| 657 | def help_exit(self): |
| 658 | """Handles the 'help exit' command.""" |
| 659 | print_message('Exits the console.') |
| 660 | |
| 661 | do_EOF = do_exit |
| 662 | help_EOF = help_exit |
| 663 | |
| 664 | |
| 665 | def main(): |
| 666 | """Main function.""" |
| 667 | NfcConsole().begin() |
| 668 | |
| 669 | |
| 670 | if __name__ == '__main__': |
| 671 | main() |