|
| 1 | +from dbus_next.service import ServiceInterface, method, dbus_property, PropertyAccess |
| 2 | + |
| 3 | +import asyncio |
| 4 | +import random |
| 5 | + |
| 6 | + |
| 7 | +class Device1(ServiceInterface): |
| 8 | + def __init__(self, bus, parent_path, mac_address="00:00:00:00:00:00"): |
| 9 | + self.bus = bus |
| 10 | + self.path = f"{parent_path}/dev_{'_'.join(mac_address.split(':'))}" |
| 11 | + super().__init__("org.bluez.Device1") |
| 12 | + self._exported = False |
| 13 | + self._connected = False |
| 14 | + self._services_resolved = False |
| 15 | + self._rssi = -128 |
| 16 | + self._address = mac_address |
| 17 | + self._name = f"dev_{'_'.join(mac_address.split(':'))}" |
| 18 | + self._services = [] |
| 19 | + |
| 20 | + self.__task_scanning_active = False |
| 21 | + self.__task_connected_active = False |
| 22 | + |
| 23 | + async def export(self): |
| 24 | + if not self._exported: |
| 25 | + await asyncio.sleep(random.uniform(0.5, 1.5)) |
| 26 | + self.bus.export(f"/org/bluez/{self.path}", self) |
| 27 | + self._exported = True |
| 28 | + |
| 29 | + def add_service(self, service): |
| 30 | + self._services.append(service) |
| 31 | + |
| 32 | + def run_connected_task(self): |
| 33 | + pass |
| 34 | + |
| 35 | + async def task_scanning_start(self): |
| 36 | + await self.export() |
| 37 | + self.__task_scanning_active = True |
| 38 | + asyncio.ensure_future(self._task_scanning_run()) |
| 39 | + |
| 40 | + def task_scanning_stop(self): |
| 41 | + self.__task_scanning_active = False |
| 42 | + |
| 43 | + def task_connected_start(self): |
| 44 | + self.__task_connected_active = True |
| 45 | + asyncio.ensure_future(self._task_connected_run()) |
| 46 | + |
| 47 | + def task_connected_stop(self): |
| 48 | + self.__task_connected_active = False |
| 49 | + |
| 50 | + async def _task_scanning_run(self): |
| 51 | + await asyncio.sleep(random.uniform(0.02, 0.2)) |
| 52 | + # Execute scanning tasks |
| 53 | + await self._update_rssi(random.uniform(-90, -60)) |
| 54 | + if self.__task_scanning_active: |
| 55 | + asyncio.ensure_future(self._task_scanning_run()) |
| 56 | + |
| 57 | + async def _task_connected_run(self): |
| 58 | + await asyncio.sleep(0.015) |
| 59 | + # Execute connected tasks |
| 60 | + self.run_connected_task() |
| 61 | + if self.__task_connected_active: |
| 62 | + asyncio.ensure_future(self._task_connected_run()) |
| 63 | + |
| 64 | + @method() |
| 65 | + async def Connect(self): |
| 66 | + print("Connect") |
| 67 | + await self._update_connected(True) |
| 68 | + for service in self._services: |
| 69 | + service.export() |
| 70 | + await self._update_services_resolved(True) |
| 71 | + self.task_connected_start() |
| 72 | + return |
| 73 | + |
| 74 | + @method() |
| 75 | + async def Disconnect(self): |
| 76 | + print("Disconnect") |
| 77 | + await self._update_services_resolved(False) |
| 78 | + self.task_connected_stop() |
| 79 | + await self._update_connected(False) |
| 80 | + return |
| 81 | + |
| 82 | + @dbus_property(access=PropertyAccess.READ) |
| 83 | + def Connected(self) -> "b": |
| 84 | + return self._connected |
| 85 | + |
| 86 | + @dbus_property(access=PropertyAccess.READ) |
| 87 | + def ServicesResolved(self) -> "b": |
| 88 | + return self._services_resolved |
| 89 | + |
| 90 | + @dbus_property(access=PropertyAccess.READ) |
| 91 | + def RSSI(self) -> "n": |
| 92 | + return self._rssi |
| 93 | + |
| 94 | + @dbus_property(access=PropertyAccess.READ) |
| 95 | + def Name(self) -> "s": |
| 96 | + return self._name |
| 97 | + |
| 98 | + async def _update_connected(self, new_value: bool): |
| 99 | + await asyncio.sleep(random.uniform(0.5, 1.5)) |
| 100 | + self._connected = new_value |
| 101 | + property_changed = {"Connected": self._connected} |
| 102 | + self.emit_properties_changed(property_changed) |
| 103 | + print(f"Property changed: {property_changed}") |
| 104 | + |
| 105 | + async def _update_services_resolved(self, new_value: bool): |
| 106 | + await asyncio.sleep(random.uniform(0.0, 0.5)) |
| 107 | + self._services_resolved = new_value |
| 108 | + property_changed = {"ServicesResolved": self._services_resolved} |
| 109 | + self.emit_properties_changed(property_changed) |
| 110 | + print(f"Property changed: {property_changed}") |
| 111 | + |
| 112 | + async def _update_rssi(self, new_value: int): |
| 113 | + self._rssi = int(new_value) |
| 114 | + property_changed = {"RSSI": self._rssi} |
| 115 | + self.emit_properties_changed(property_changed) |
0 commit comments