Search in sources :

Example 1 with BluetoothScanNotification

use of org.eclipse.smarthome.binding.bluetooth.notification.BluetoothScanNotification in project smarthome by eclipse.

the class BlueZBluetoothDevice method enableNotifications.

private void enableNotifications() {
    logger.debug("Enabling notifications for device '{}'", device.getAddress());
    device.enableRSSINotifications(n -> {
        rssi = (int) n;
        BluetoothScanNotification notification = new BluetoothScanNotification();
        notification.setRssi(n);
        notifyListeners(BluetoothEventType.SCAN_RECORD, notification);
    });
    device.enableManufacturerDataNotifications(n -> {
        for (Map.Entry<Short, byte[]> entry : n.entrySet()) {
            BluetoothScanNotification notification = new BluetoothScanNotification();
            byte[] data = new byte[entry.getValue().length + 2];
            data[0] = (byte) (entry.getKey() & 0xFF);
            data[1] = (byte) (entry.getKey() >>> 8);
            System.arraycopy(entry.getValue(), 0, data, 2, entry.getValue().length);
            if (logger.isDebugEnabled()) {
                logger.debug("Received manufacturer data for '{}': {}", address, HexUtils.bytesToHex(data, " "));
            }
            notification.setManufacturerData(data);
            notifyListeners(BluetoothEventType.SCAN_RECORD, notification);
        }
    });
    device.enableConnectedNotifications(connected -> {
        connectionState = connected ? ConnectionState.CONNECTED : ConnectionState.DISCONNECTED;
        logger.debug("Connection state of '{}' changed to {}", address, connectionState);
        notifyListeners(BluetoothEventType.CONNECTION_STATE, new BluetoothConnectionStatusNotification(connectionState));
    });
    device.enableServicesResolvedNotifications(resolved -> {
        logger.debug("Received services resolved event for '{}': {}", address, resolved);
        if (resolved) {
            refreshServices();
            notifyListeners(BluetoothEventType.SERVICES_DISCOVERED);
        }
    });
    device.enableServiceDataNotifications(data -> {
        if (logger.isDebugEnabled()) {
            logger.debug("Received service data for '{}':", address);
            for (Map.Entry<String, byte[]> entry : data.entrySet()) {
                logger.debug("{} : {}", entry.getKey(), HexUtils.bytesToHex(entry.getValue(), " "));
            }
        }
    });
}
Also used : BluetoothScanNotification(org.eclipse.smarthome.binding.bluetooth.notification.BluetoothScanNotification) BluetoothConnectionStatusNotification(org.eclipse.smarthome.binding.bluetooth.notification.BluetoothConnectionStatusNotification) Map(java.util.Map)

Example 2 with BluetoothScanNotification

use of org.eclipse.smarthome.binding.bluetooth.notification.BluetoothScanNotification in project smarthome by eclipse.

the class BlueGigaBluetoothDevice method bluegigaEventReceived.

@Override
public void bluegigaEventReceived(BlueGigaResponse event) {
    if (event instanceof BlueGigaScanResponseEvent) {
        BlueGigaScanResponseEvent scanEvent = (BlueGigaScanResponseEvent) event;
        // Check if this is addressed to this device
        if (!address.equals(new BluetoothAddress(scanEvent.getSender()))) {
            return;
        }
        // Set device properties
        rssi = scanEvent.getRssi();
        addressType = scanEvent.getAddressType();
        byte[] manufacturerData = null;
        // If the packet contains data, then process it and add anything relevant to the device...
        if (scanEvent.getData() != null) {
            EirPacket eir = new EirPacket(scanEvent.getData());
            for (EirDataType record : eir.getRecords().keySet()) {
                switch(record) {
                    case EIR_FLAGS:
                        break;
                    case EIR_MANUFACTURER_SPECIFIC:
                        manufacturerData = (byte[]) eir.getRecord(EirDataType.EIR_MANUFACTURER_SPECIFIC);
                        if (manufacturerData.length > 2) {
                            int id = manufacturerData[0] + (manufacturerData[1] << 8);
                            manufacturer = id;
                        }
                        break;
                    case EIR_NAME_LONG:
                    case EIR_NAME_SHORT:
                        name = (String) eir.getRecord(record);
                        break;
                    case EIR_SLAVEINTERVALRANGE:
                        break;
                    case EIR_SVC_DATA_UUID128:
                        break;
                    case EIR_SVC_DATA_UUID16:
                        break;
                    case EIR_SVC_DATA_UUID32:
                        break;
                    case EIR_SVC_UUID128_INCOMPLETE:
                    case EIR_SVC_UUID16_COMPLETE:
                    case EIR_SVC_UUID16_INCOMPLETE:
                    case EIR_SVC_UUID32_COMPLETE:
                    case EIR_SVC_UUID32_INCOMPLETE:
                    case EIR_SVC_UUID128_COMPLETE:
                        // addServices((List<UUID>) eir.getRecord(record));
                        break;
                    case EIR_TXPOWER:
                        txPower = (int) eir.getRecord(EirDataType.EIR_TXPOWER);
                        break;
                    default:
                        break;
                }
            }
        }
        if (connectionState == ConnectionState.DISCOVERING) {
            // We want to wait for an advertisement and a scan response before we call this discovered.
            // The intention is to gather a reasonable amount of data about the device given devices send
            // different data in different packets...
            // Note that this is possible a bit arbitrary and may be refined later.
            scanResponses.add(scanEvent.getPacketType());
            if ((scanResponses.contains(ScanResponseType.CONNECTABLE_ADVERTISEMENT) || scanResponses.contains(ScanResponseType.DISCOVERABLE_ADVERTISEMENT) || scanResponses.contains(ScanResponseType.NON_CONNECTABLE_ADVERTISEMENT)) && scanResponses.contains(ScanResponseType.SCAN_RESPONSE)) {
                // Set our state to disconnected
                connectionState = ConnectionState.DISCONNECTED;
                connection = -1;
                // But notify listeners that the state is now DISCOVERED
                notifyListeners(BluetoothEventType.CONNECTION_STATE, new BluetoothConnectionStatusNotification(ConnectionState.DISCOVERED));
                // Notify the bridge - for inbox notifications
                bgHandler.deviceDiscovered(this);
            }
        }
        // Notify listeners of all scan records - for RSSI, beacon processing (etc)
        BluetoothScanNotification scanNotification = new BluetoothScanNotification();
        scanNotification.setRssi(scanEvent.getRssi());
        switch(scanEvent.getPacketType()) {
            case CONNECTABLE_ADVERTISEMENT:
            case DISCOVERABLE_ADVERTISEMENT:
            case NON_CONNECTABLE_ADVERTISEMENT:
                scanNotification.setBeaconType(BluetoothBeaconType.BEACON_ADVERTISEMENT);
                break;
            case SCAN_RESPONSE:
                scanNotification.setBeaconType(BluetoothBeaconType.BEACON_SCANRESPONSE);
                break;
            default:
                break;
        }
        if (manufacturerData != null) {
            scanNotification.setManufacturerData(manufacturerData);
        }
        notifyListeners(BluetoothEventType.SCAN_RECORD, scanNotification);
        return;
    }
    if (event instanceof BlueGigaGroupFoundEvent) {
        // A Service has been discovered
        BlueGigaGroupFoundEvent serviceEvent = (BlueGigaGroupFoundEvent) event;
        // If this is not our connection handle then ignore.
        if (connection != serviceEvent.getConnection()) {
            return;
        }
        logger.trace("BlueGiga Group: {} svcs={}", this, supportedServices);
        BluetoothService service = new BluetoothService(serviceEvent.getUuid(), true, serviceEvent.getStart(), serviceEvent.getEnd());
        addService(service);
        return;
    }
    if (event instanceof BlueGigaFindInformationFoundEvent) {
        // A Characteristic has been discovered
        BlueGigaFindInformationFoundEvent infoEvent = (BlueGigaFindInformationFoundEvent) event;
        // If this is not our connection handle then ignore.
        if (connection != infoEvent.getConnection()) {
            return;
        }
        logger.trace("BlueGiga FindInfo: {} svcs={}", this, supportedServices);
        BluetoothCharacteristic characteristic = new BluetoothCharacteristic(infoEvent.getUuid(), infoEvent.getChrHandle());
        BluetoothService service = getServiceByHandle(characteristic.getHandle());
        if (service == null) {
            logger.debug("BlueGiga: Unable to find service for handle {}", characteristic.getHandle());
            return;
        }
        characteristic.setService(service);
        service.addCharacteristic(characteristic);
        return;
    }
    if (event instanceof BlueGigaProcedureCompletedEvent) {
        BlueGigaProcedureCompletedEvent completedEvent = (BlueGigaProcedureCompletedEvent) event;
        // If this is not our connection handle then ignore.
        if (connection != completedEvent.getConnection()) {
            return;
        }
        if (procedureProgress == null) {
            logger.debug("BlueGiga procedure completed but procedure is null with connection {}, address {}", connection, address);
            return;
        }
        // The current procedure is now complete - move on...
        switch(procedureProgress) {
            case GET_SERVICES:
                // We've downloaded all services, now get the characteristics
                procedureProgress = BlueGigaProcedure.GET_CHARACTERISTICS;
                bgHandler.bgFindCharacteristics(connection);
                break;
            case GET_CHARACTERISTICS:
                // We've downloaded all characteristics
                procedureProgress = BlueGigaProcedure.NONE;
                notifyListeners(BluetoothEventType.SERVICES_DISCOVERED);
                break;
            case CHARACTERISTIC_READ:
                // The read failed
                notifyListeners(BluetoothEventType.CHARACTERISTIC_READ_COMPLETE, procedureCharacteristic, BluetoothCompletionStatus.ERROR);
                procedureProgress = BlueGigaProcedure.NONE;
                procedureCharacteristic = null;
                break;
            case CHARACTERISTIC_WRITE:
                // The write completed - failure or success
                BluetoothCompletionStatus result = completedEvent.getResult() == BgApiResponse.SUCCESS ? BluetoothCompletionStatus.SUCCESS : BluetoothCompletionStatus.ERROR;
                notifyListeners(BluetoothEventType.CHARACTERISTIC_WRITE_COMPLETE, procedureCharacteristic, result);
                procedureProgress = BlueGigaProcedure.NONE;
                procedureCharacteristic = null;
                break;
            default:
                break;
        }
        return;
    }
    if (event instanceof BlueGigaConnectionStatusEvent) {
        BlueGigaConnectionStatusEvent connectionEvent = (BlueGigaConnectionStatusEvent) event;
        // Check if this is addressed to this device
        if (!address.equals(new BluetoothAddress(connectionEvent.getAddress()))) {
            return;
        }
        // If we're connected, then remember the connection handle
        if (connectionEvent.getFlags().contains(ConnectionStatusFlag.CONNECTION_CONNECTED)) {
            connectionState = ConnectionState.CONNECTED;
            connection = connectionEvent.getConnection();
        }
        if (connectionEvent.getFlags().contains(ConnectionStatusFlag.CONNECTION_CONNECTED)) {
            notifyListeners(BluetoothEventType.CONNECTION_STATE, new BluetoothConnectionStatusNotification(connectionState));
        }
        return;
    }
    if (event instanceof BlueGigaDisconnectedEvent) {
        BlueGigaDisconnectedEvent disconnectedEvent = (BlueGigaDisconnectedEvent) event;
        // If this is not our connection handle then ignore.
        if (connection != disconnectedEvent.getConnection()) {
            return;
        }
        connectionState = ConnectionState.DISCONNECTED;
        connection = -1;
        notifyListeners(BluetoothEventType.CONNECTION_STATE, new BluetoothConnectionStatusNotification(connectionState));
        return;
    }
    if (event instanceof BlueGigaAttributeValueEvent) {
        // A read request has completed - update the characteristic
        BlueGigaAttributeValueEvent valueEvent = (BlueGigaAttributeValueEvent) event;
        BluetoothCharacteristic characteristic = getCharacteristicByHandle(valueEvent.getAttHandle());
        if (characteristic == null) {
            logger.debug("BlueGiga didn't find characteristic for event {}", event);
        } else {
            // If this is the characteristic we were reading, then send a read completion
            if (procedureProgress == BlueGigaProcedure.CHARACTERISTIC_READ && procedureCharacteristic != null && procedureCharacteristic.getHandle() == valueEvent.getAttHandle()) {
                procedureProgress = BlueGigaProcedure.NONE;
                procedureCharacteristic = null;
                notifyListeners(BluetoothEventType.CHARACTERISTIC_READ_COMPLETE, characteristic, BluetoothCompletionStatus.SUCCESS);
            }
            // Notify the user of the updated value
            notifyListeners(BluetoothEventType.CHARACTERISTIC_UPDATED, procedureCharacteristic);
        }
    }
}
Also used : BlueGigaFindInformationFoundEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaFindInformationFoundEvent) BluetoothAddress(org.eclipse.smarthome.binding.bluetooth.BluetoothAddress) BluetoothCharacteristic(org.eclipse.smarthome.binding.bluetooth.BluetoothCharacteristic) BluetoothConnectionStatusNotification(org.eclipse.smarthome.binding.bluetooth.notification.BluetoothConnectionStatusNotification) BluetoothCompletionStatus(org.eclipse.smarthome.binding.bluetooth.BluetoothCompletionStatus) EirDataType(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.eir.EirDataType) EirPacket(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.eir.EirPacket) BlueGigaProcedureCompletedEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaProcedureCompletedEvent) BluetoothService(org.eclipse.smarthome.binding.bluetooth.BluetoothService) BluetoothScanNotification(org.eclipse.smarthome.binding.bluetooth.notification.BluetoothScanNotification) BlueGigaGroupFoundEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaGroupFoundEvent) BlueGigaAttributeValueEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaAttributeValueEvent) BlueGigaDisconnectedEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.connection.BlueGigaDisconnectedEvent) BlueGigaConnectionStatusEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.connection.BlueGigaConnectionStatusEvent) BlueGigaScanResponseEvent(org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.gap.BlueGigaScanResponseEvent)

Aggregations

BluetoothConnectionStatusNotification (org.eclipse.smarthome.binding.bluetooth.notification.BluetoothConnectionStatusNotification)2 BluetoothScanNotification (org.eclipse.smarthome.binding.bluetooth.notification.BluetoothScanNotification)2 Map (java.util.Map)1 BluetoothAddress (org.eclipse.smarthome.binding.bluetooth.BluetoothAddress)1 BluetoothCharacteristic (org.eclipse.smarthome.binding.bluetooth.BluetoothCharacteristic)1 BluetoothCompletionStatus (org.eclipse.smarthome.binding.bluetooth.BluetoothCompletionStatus)1 BluetoothService (org.eclipse.smarthome.binding.bluetooth.BluetoothService)1 BlueGigaAttributeValueEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaAttributeValueEvent)1 BlueGigaFindInformationFoundEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaFindInformationFoundEvent)1 BlueGigaGroupFoundEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaGroupFoundEvent)1 BlueGigaProcedureCompletedEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.attributeclient.BlueGigaProcedureCompletedEvent)1 BlueGigaConnectionStatusEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.connection.BlueGigaConnectionStatusEvent)1 BlueGigaDisconnectedEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.connection.BlueGigaDisconnectedEvent)1 BlueGigaScanResponseEvent (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.command.gap.BlueGigaScanResponseEvent)1 EirDataType (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.eir.EirDataType)1 EirPacket (org.eclipse.smarthome.binding.bluetooth.bluegiga.internal.eir.EirPacket)1