Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.4 KiB

4 years ago
  1. #!/usr/bin/env python3
  2. """
  3. A python script to get battery level from Bluetooth headsets
  4. """
  5. # License: GPL-3.0
  6. # Author: @TheWeirdDev
  7. # 29 Sept 2019
  8. import errno
  9. import bluetooth
  10. import sys
  11. def send(sock, message):
  12. sock.send(b"\r\n" + message + b"\r\n")
  13. def getATCommand(sock, line, device):
  14. blevel = -1
  15. if b"BRSF" in line:
  16. send(sock, b"+BRSF: 1024")
  17. send(sock, b"OK")
  18. elif b"CIND=" in line:
  19. send(sock, b"+CIND: (\"battchg\",(0-5))")
  20. send(sock, b"OK")
  21. elif b"CIND?" in line:
  22. send(sock, b"+CIND: 5")
  23. send(sock, b"OK")
  24. elif b"BIND=?" in line:
  25. # Announce that we support the battery level HF indicator
  26. # https://www.bluetooth.com/specifications/assigned-numbers/hands-free-profile/
  27. send(sock, b"+BIND: (2)")
  28. send(sock, b"OK")
  29. elif b"BIND?" in line:
  30. # Enable battery level HF indicator
  31. send(sock, b"+BIND: 2,1")
  32. send(sock, b"OK")
  33. elif b"XAPL=" in line:
  34. send(sock, b"+XAPL: iPhone,7")
  35. send(sock, b"OK")
  36. elif b"IPHONEACCEV" in line:
  37. parts = line.strip().split(b',')[1:]
  38. if len(parts) > 1 and (len(parts) % 2) == 0:
  39. parts = iter(parts)
  40. params = dict(zip(parts, parts))
  41. if b'1' in params:
  42. blevel = (int(params[b'1']) + 1) * 10
  43. elif b"BIEV=" in line:
  44. params = line.strip().split(b"=")[1].split(b",")
  45. if params[0] == b"2":
  46. blevel = int(params[1])
  47. else:
  48. send(sock, b"OK")
  49. if blevel != -1:
  50. print(f"Battery level for {device} is {blevel}%")
  51. return False
  52. return True
  53. def main():
  54. if (len(sys.argv) < 2):
  55. print("Usage: bl_battery.py <BT_MAC_ADDRESS_1>[.PORT] ...")
  56. print(" Port number is optional (default = 4)")
  57. exit()
  58. else:
  59. for device in sys.argv[1:]:
  60. i = device.find('.')
  61. if i == -1:
  62. port = 4
  63. else:
  64. port = int(device[i+1:])
  65. device = device[:i]
  66. try:
  67. s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
  68. s.connect((device, port))
  69. while getATCommand(s, s.recv(128), device):
  70. pass
  71. s.close()
  72. except OSError as e:
  73. print(f"{device} is offline", e)
  74. if __name__ == "__main__":
  75. main()