/btprox.py

https://github.com/decibyte/btprox
Python | 86 lines | 59 code | 9 blank | 18 comment | 23 complexity | 3c8068957f6524aca313b7678c547a7a MD5 | raw file
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import bluetooth
  4. import config
  5. # Dictionary of devices in range and their names
  6. devices_in_range = {}
  7. # Dictionary of devices that seem to be away (for how many scans), but should not be regarded as
  8. # out of sight yet.
  9. devices_not_seen = {}
  10. # A helper for loading plugins (as seen on: http://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname).
  11. def get_class(kls):
  12. parts = kls.split('.')
  13. module = ".".join(parts[:-1])
  14. m = __import__( module )
  15. for comp in parts[1:]:
  16. m = getattr(m, comp)
  17. return m
  18. # Load plugins.
  19. plugins = []
  20. for (name, options, devices) in config.plugins:
  21. plugins.append({
  22. 'name' : name,
  23. 'object' : get_class(name)(options),
  24. 'devices' : devices,
  25. })
  26. # Scan for devices and update the list of devices and names.
  27. def scan():
  28. # Get devices in range.
  29. devices = bluetooth.discover_devices()
  30. # Loop through devices in range.
  31. for d in devices:
  32. if not d in devices_in_range.keys():
  33. # Add new device to list of devices in range.
  34. devices_in_range[d] = bluetooth.lookup_name(d)
  35. if d in config.known_devices.values():
  36. print 'known device %s (%s) in range.' % (d, devices_in_range[d],)
  37. else:
  38. print '%s (%s) in range.' % (d, devices_in_range[d],)
  39. # Tell plugins about this new device.
  40. for p in plugins:
  41. if d in p['devices']:
  42. p['object'].in_range(d, devices_in_range[d])
  43. else:
  44. print '%s still in range.' % d
  45. # Loop through devices known to be in range and remove those that should be regarded as not in range.
  46. to_remove = []
  47. for d in devices_in_range:
  48. if not d in devices:
  49. # Update device away scan count.
  50. if devices_not_seen.has_key(d):
  51. devices_not_seen[d] += 1
  52. else:
  53. devices_not_seen[d] = 1
  54. # Remove device if away scan count is too high now.
  55. if devices_not_seen[d] >= config.away_after:
  56. to_remove.append(d)
  57. if d in config.known_devices.values():
  58. print 'known device %s (%s) no longer in range.' % (d, devices_in_range[d],)
  59. else:
  60. print '%s (%s) no longer in range.' % (d, devices_in_range[d],)
  61. # Tell plugins about this missing device.
  62. for p in plugins:
  63. if d in p['devices']:
  64. p['object'].out_of_range(d, devices_in_range[d])
  65. else:
  66. print '%s seems to be away, missing for %i of %i scans.' % (d, devices_not_seen[d], config.away_after,)
  67. # Device IS in range. Reset the away scan counter.
  68. else:
  69. if devices_not_seen.has_key(d):
  70. del devices_not_seen[d]
  71. for d in to_remove:
  72. del devices_not_seen[d]
  73. del devices_in_range[d]
  74. # Start the loop
  75. while True:
  76. print '*' * 72
  77. scan()