/* * * Copyright (c) 2020-2023 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace chip::DeviceLayer::Internal; /////////// Listing adapters implementation ////////// extern "C" void * pychip_ble_adapter_list_new() { return static_cast(new AdapterIterator()); } extern "C" void pychip_ble_adapter_list_delete(void * adapterIterator) { delete static_cast(adapterIterator); } extern "C" bool pychip_ble_adapter_list_next(void * adapterIterator) { return static_cast(adapterIterator)->Next(); } extern "C" uint32_t pychip_ble_adapter_list_get_index(void * adapterIterator) { return static_cast(adapterIterator)->GetIndex(); } extern "C" const char * pychip_ble_adapter_list_get_address(void * adapterIterator) { return static_cast(adapterIterator)->GetAddress(); } extern "C" const char * pychip_ble_adapter_list_get_alias(void * adapterIterator) { return static_cast(adapterIterator)->GetAlias(); } extern "C" const char * pychip_ble_adapter_list_get_name(void * adapterIterator) { return static_cast(adapterIterator)->GetName(); } extern "C" bool pychip_ble_adapter_list_is_powered(void * adapterIterator) { return static_cast(adapterIterator)->IsPowered(); } extern "C" void * pychip_ble_adapter_list_get_raw_adapter(void * adapterIterator) { return static_cast(adapterIterator)->GetAdapter(); } /////////// CHIP Device scanner implementation ////////// namespace { // To avoid python compatibility issues on inc/dec references, // code assumes an abstract type and leaves it up to python to keep track of // reference counts struct PyObject; class ScannerDelegateImpl : public ChipDeviceScannerDelegate { public: using DeviceScannedCallback = void (*)(PyObject * context, const char * address, uint16_t discriminator, uint16_t vendorId, uint16_t productId); using ScanCompleteCallback = void (*)(PyObject * context); using ScanErrorCallback = void (*)(PyObject * context, CHIP_ERROR::StorageType error); ScannerDelegateImpl(PyObject * context, DeviceScannedCallback scanCallback, ScanCompleteCallback completeCallback, ScanErrorCallback errorCallback) : mContext(context), mScanCallback(scanCallback), mCompleteCallback(completeCallback), mErrorCallback(errorCallback) {} CHIP_ERROR ScannerInit(BluezAdapter1 * adapter) { ReturnErrorOnFailure(mBluezObjectManager.Init()); return mScanner.Init(adapter, this); } void ScannerShutdown() { mBluezObjectManager.Shutdown(); } CHIP_ERROR ScannerStartScan(chip::System::Clock::Timeout timeout) { CHIP_ERROR err = mScanner.StartScan(); VerifyOrReturnError(err == CHIP_NO_ERROR, err); err = chip::DeviceLayer::SystemLayer().StartTimer(timeout, HandleScannerTimer, this); VerifyOrReturnError(err == CHIP_NO_ERROR, err, mScanner.StopScan()); return CHIP_NO_ERROR; } CHIP_ERROR ScannerStopScan() { chip::DeviceLayer::SystemLayer().CancelTimer(HandleScannerTimer, this); return mScanner.StopScan(); } static void HandleScannerTimer(chip::System::Layer *, void * appState) { auto * delegate = static_cast(appState); delegate->OnScanError(CHIP_ERROR_TIMEOUT); delegate->mScanner.StopScan(); } void OnDeviceScanned(BluezDevice1 & device, const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override { if (mScanCallback) { mScanCallback(mContext, bluez_device1_get_address(&device), info.GetDeviceDiscriminator(), info.GetProductId(), info.GetVendorId()); } } void OnScanComplete() override { if (mCompleteCallback) { mCompleteCallback(mContext); } } void OnScanError(CHIP_ERROR error) override { if (mErrorCallback) { mErrorCallback(mContext, error.AsInteger()); } } private: BluezObjectManager mBluezObjectManager; ChipDeviceScanner mScanner{ mBluezObjectManager }; PyObject * const mContext; const DeviceScannedCallback mScanCallback; const ScanCompleteCallback mCompleteCallback; const ScanErrorCallback mErrorCallback; }; } // namespace extern "C" void * pychip_ble_scanner_start(PyObject * context, void * adapter, uint32_t timeoutMs, ScannerDelegateImpl::DeviceScannedCallback scanCallback, ScannerDelegateImpl::ScanCompleteCallback completeCallback, ScannerDelegateImpl::ScanErrorCallback errorCallback) { std::unique_ptr delegate = std::make_unique(context, scanCallback, completeCallback, errorCallback); CHIP_ERROR err = delegate->ScannerInit(static_cast(adapter)); VerifyOrReturnError(err == CHIP_NO_ERROR, nullptr); chip::DeviceLayer::PlatformMgr().LockChipStack(); err = delegate->ScannerStartScan(chip::System::Clock::Milliseconds32(timeoutMs)); chip::DeviceLayer::PlatformMgr().UnlockChipStack(); VerifyOrReturnError(err == CHIP_NO_ERROR, nullptr); return delegate.release(); } extern "C" void pychip_ble_scanner_delete(void * scanner) { auto * delegate = static_cast(scanner); chip::DeviceLayer::StackLock lock; // Make sure that the scanner is stopped before deleting the delegate. delegate->ScannerStopScan(); delegate->ScannerShutdown(); delete delegate; }