1# Copyright 2024 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# ----------------------------------------------------------------------------- 16# Imports 17# ----------------------------------------------------------------------------- 18import asyncio 19import logging 20import sys 21import os 22 23from bumble.core import AdvertisingData 24from bumble.device import Device 25from bumble import att 26from bumble.profiles.hap import ( 27 HearingAccessService, 28 HearingAidFeatures, 29 HearingAidType, 30 PresetSynchronizationSupport, 31 IndependentPresets, 32 DynamicPresets, 33 WritablePresetsSupport, 34 PresetRecord, 35) 36 37from bumble.transport import open_transport_or_link 38 39server_features = HearingAidFeatures( 40 HearingAidType.MONAURAL_HEARING_AID, 41 PresetSynchronizationSupport.PRESET_SYNCHRONIZATION_IS_NOT_SUPPORTED, 42 IndependentPresets.IDENTICAL_PRESET_RECORD, 43 DynamicPresets.PRESET_RECORDS_DOES_NOT_CHANGE, 44 WritablePresetsSupport.WRITABLE_PRESET_RECORDS_SUPPORTED, 45) 46 47foo_preset = PresetRecord(1, "foo preset") 48bar_preset = PresetRecord(50, "bar preset") 49foobar_preset = PresetRecord(5, "foobar preset") 50 51 52# ----------------------------------------------------------------------------- 53async def main() -> None: 54 if len(sys.argv) < 3: 55 print('Usage: run_hap_server.py <config-file> <transport-spec-for-device>') 56 print('example: run_hap_server.py device1.json pty:hci_pty') 57 return 58 59 print('<<< connecting to HCI...') 60 async with await open_transport_or_link(sys.argv[2]) as hci_transport: 61 print('<<< connected') 62 63 device = Device.from_config_file_with_hci( 64 sys.argv[1], hci_transport.source, hci_transport.sink 65 ) 66 67 await device.power_on() 68 69 hap = HearingAccessService( 70 device, server_features, [foo_preset, bar_preset, foobar_preset] 71 ) 72 device.add_service(hap) 73 74 advertising_data = bytes( 75 AdvertisingData( 76 [ 77 ( 78 AdvertisingData.COMPLETE_LOCAL_NAME, 79 bytes('Bumble HearingAccessService', 'utf-8'), 80 ), 81 ( 82 AdvertisingData.FLAGS, 83 bytes( 84 [ 85 AdvertisingData.LE_GENERAL_DISCOVERABLE_MODE_FLAG 86 | AdvertisingData.BR_EDR_HOST_FLAG 87 | AdvertisingData.BR_EDR_CONTROLLER_FLAG 88 ] 89 ), 90 ), 91 ( 92 AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS, 93 bytes(HearingAccessService.UUID), 94 ), 95 ] 96 ) 97 ) 98 99 await device.create_advertising_set( 100 advertising_data=advertising_data, 101 auto_restart=True, 102 ) 103 104 105# ----------------------------------------------------------------------------- 106logging.basicConfig(level=os.environ.get('BUMBLE_LOGLEVEL', 'DEBUG').upper()) 107asyncio.run(main()) 108