/examples/bb8joystick/bb8.py

https://github.com/undera/pylgbst · Python · 113 lines · 85 code · 23 blank · 5 comment · 2 complexity · 9359d4b6688a376bc9e368536a7192b1 MD5 · raw file

  1. import asyncio
  2. import time
  3. import spheropy
  4. # noinspection PyProtectedMember
  5. from spheropy.spheropy import _ClientCommandPacket, _DEVICE_ID_CORE, _DEVICE_ID_SPHERO
  6. class BLEInterfaceGattool(spheropy.BleInterface):
  7. def _find_adapter(self):
  8. adapter = spheropy.pygatt.GATTToolBackend()
  9. adapter.start()
  10. adapter_type = spheropy.BleInterface.BleAdapterType.PYGATT
  11. self._adapter = adapter
  12. self._adapter_type = adapter_type
  13. return True
  14. class _SpheroImproved(spheropy.Sphero):
  15. async def connect(self, search_name=None, address=None, port=None, bluetooth_interface=None, use_ble=False,
  16. num_retry_attempts=1):
  17. gattool = BLEInterfaceGattool(search_name)
  18. return await
  19. super().connect(search_name, address, port, gattool, use_ble, num_retry_attempts)
  20. async def sleep(self, sleeptime, reset_inactivity_timeout=True, response_timeout_in_seconds=None):
  21. # port from https://github.com/jchadwhite/SpheroBB8-python/blob/master/BB8_driver.py#L394
  22. command = _ClientCommandPacket(device_id=_DEVICE_ID_CORE,
  23. command_id=0x22,
  24. sequence_number=self._get_and_increment_command_sequence_number(),
  25. data=[(sleeptime >> 8), (sleeptime & 0xff), 0],
  26. wait_for_response=False,
  27. reset_inactivity_timeout=reset_inactivity_timeout)
  28. return await
  29. self._send_command(command, response_timeout_in_seconds)
  30. async def set_rotation_rate(self, rate, reset_inactivity_timeout=True, response_timeout_in_seconds=None):
  31. # port from https://github.com/jchadwhite/SpheroBB8-python/blob/master/BB8_driver.py
  32. command = _ClientCommandPacket(device_id=_DEVICE_ID_SPHERO,
  33. command_id=0x03,
  34. sequence_number=self._get_and_increment_command_sequence_number(),
  35. data=[rate],
  36. wait_for_response=False,
  37. reset_inactivity_timeout=reset_inactivity_timeout)
  38. return await
  39. self._send_command(command, response_timeout_in_seconds)
  40. class BB8(object):
  41. def __init__(self, name="BB-CC13"):
  42. self._heading = 0
  43. # marry sync with async https://www.aeracode.org/2018/02/19/python-async-simplified/
  44. self._loop = asyncio.new_event_loop()
  45. asyncio.set_event_loop(self._loop)
  46. print("Started to wake up BB-8...")
  47. self._sphero = _SpheroImproved()
  48. self._loop.run_until_complete(self._sphero.connect(num_retry_attempts=3, use_ble=True, search_name=name))
  49. self._loop.run_until_complete(self._sphero.set_stabilization(True))
  50. self._loop.run_until_complete(self._sphero.set_rotation_rate(1))
  51. self.color(0, 0xFF, 0)
  52. self.stabilize()
  53. print("BB-8 is ready for commands")
  54. def disconnect(self):
  55. print("BB8 enters sleep")
  56. self._loop.run_until_complete(self._sphero.sleep(0))
  57. self._sphero.disconnect()
  58. def color(self, red, green, blue):
  59. self._wait_loop()
  60. self._loop.run_until_complete(self._sphero.set_rgb_led(red, green, blue, wait_for_response=False))
  61. def heading(self, heading):
  62. self._wait_loop()
  63. heading = 359 - heading
  64. self._heading = heading
  65. # self._loop.run_until_complete(self._sphero.set_heading(359 - heading))
  66. self._loop.run_until_complete(self._sphero.roll(1, heading, spheropy.RollMode.IN_PLACE_ROTATE))
  67. def roll(self, speed=10, direction=0):
  68. self._wait_loop()
  69. direction += self._heading
  70. direction %= 360
  71. speed = int(255 * speed / 10)
  72. speed *= 0.75 # throttle down a bit
  73. self._loop.run_until_complete(self._sphero.roll(int(speed), direction))
  74. def stop(self):
  75. self._wait_loop()
  76. self._loop.run_until_complete(self._sphero.roll(0, 0))
  77. def stabilize(self):
  78. self._wait_loop()
  79. self._loop.run_until_complete(self._sphero.self_level())
  80. def _wait_loop(self):
  81. while self._loop.is_running():
  82. time.sleep(0.001)
  83. if __name__ == '__main__':
  84. bb8 = BB8()
  85. bb8.color(255, 0, 0)
  86. time.sleep(1)
  87. bb8.color(0, 255, 0)
  88. time.sleep(1)
  89. bb8.color(0, 0, 255)
  90. time.sleep(1)