Search in sources :

Example 1 with BluetoothGattCharacteristic

use of android.bluetooth.BluetoothGattCharacteristic in project nikeplus-fuelband-se-reversed by evilsocket.

the class BLEIoQueue method next.

private void next() {
    BLEIoOperation op = _ops.poll();
    if (op == null) {
        Logger.d("No I/O operations to execute.");
        return;
    }
    _current = op;
    boolean ok = false;
    BluetoothGattDescriptor desc = op.get_descriptor();
    BluetoothGattCharacteristic charact = op.get_characteristic();
    byte[] data = op.get_data();
    if (op.get_type() == Type.NOTIFY_START) {
        ok = _gatt.setCharacteristicNotification(charact, true);
        if (ok) {
            desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            ok = _gatt.writeDescriptor(desc);
        }
    } else if (op.get_type() == Type.WRITE_DESCRIPTOR) {
        desc.setValue(data);
        ok = _gatt.writeDescriptor(desc);
    } else if (op.get_type() == Type.WRITE_CHARACTERISTICS) {
        charact.setValue(data);
        Packet p = new Packet(charact.getValue());
        Logger.d(">> " + p.toString());
        ok = _gatt.writeCharacteristic(charact);
    } else if (op.get_type() == Type.READ_CHARACTERISTICS) {
        ok = _gatt.readCharacteristic(charact);
    } else {
        Logger.e("Unhandled Operation");
    }
    if (ok == false) {
        Logger.e("Operation failed, fetching next ...");
        next();
    }
}
Also used : BluetoothGattDescriptor(android.bluetooth.BluetoothGattDescriptor) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic)

Example 2 with BluetoothGattCharacteristic

use of android.bluetooth.BluetoothGattCharacteristic in project nikeplus-fuelband-se-reversed by evilsocket.

the class MainActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Logger.setLogView(this, (TextView) findViewById(R.id.log_view));
    _btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    _btAdapter = _btManager.getAdapter();
    if (_btAdapter.isEnabled() == false) {
        Logger.w("Bluetooth is disabled.");
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
    }
    _leScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            if (_scanning == false)
                return;
            try {
                /*
					 * Parse device advertisment data.
					 */
                final Bundle advData = AdvertisementData.parse(scanRecord);
                /*
					 * Is this a nike device?
					 */
                if (Arrays.equals(advData.getByteArray("COMPANYCODE"), NIKE_COMPANY_CODE)) {
                    Logger.i("FOUND NIKE DEVICE [" + device + "]");
                    dumpDeviceAdvData(advData);
                    _scanning = false;
                    _btAdapter.stopLeScan(_leScanCallback);
                    Logger.i("Connecting to GATT server ...");
                    _ioqueue = new BLEIoQueue(new BLEIoQueue.QueueCallbacks() {

                        private BluetoothGattService _CopperheadService = null;

                        private BluetoothGattCharacteristic _CommandChannel = null;

                        private BluetoothGattCharacteristic _ResponseChannel = null;

                        // add a raw packet to the queue
                        private void addPacket(BLEIoQueue queue, byte[] data, BLEIoOperation.OnResponseCallback callback) {
                            BLEIoOperation op = new BLEIoOperation(BLEIoOperation.Type.WRITE_CHARACTERISTICS, "Sending command.", callback);
                            op.set_data(data);
                            op.set_characteristic(_CommandChannel);
                            queue.add(op);
                        }

                        private void addPacket(BLEIoQueue queue, String s, BLEIoOperation.OnResponseCallback callback) {
                            byte[] buffer = new byte[s.length() / 2];
                            for (int i = 0, j = 0; i < s.length(); i += 2, ++j) {
                                buffer[j] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
                            }
                            addPacket(queue, buffer, callback);
                        }

                        // create the needed packet to request a specific setting from the device
                        private void requestSetting(BLEIoQueue queue, int code) {
                            CopperheadPacket oppacket = new CopperheadPacket(5);
                            oppacket.setOpcode((byte) 10);
                            ByteBuffer b = oppacket.getPayloadBuffer();
                            b.put((byte) 1);
                            b.put((byte) code);
                            Packet p = Packet.wrap(oppacket);
                            p.setProtocolLayer(CommandResponseOperation.ProtocolLayer.COMMAND);
                            p.setPacketCount(0);
                            p.setPacketIndex(0);
                            p.setSequenceNumber(1);
                            addPacket(queue, p.getBuffer(), new BLEIoOperation.OnResponseCallback() {

                                @Override
                                public void onData(Packet config) {
                                    byte[] raw = config.getBuffer();
                                    try {
                                        Utils.processGetSettingsResponse(raw);
                                    } catch (Exception e) {
                                        Logger.e(e.toString());
                                    }
                                }
                            });
                        }

                        @Override
                        public void onServicesDiscovered(BLEIoQueue queue, BluetoothGatt gatt, int status) {
                            dumpServices(gatt);
                            _CopperheadService = gatt.getService(COPPERHEAD_SERVICE_UUID);
                            if (_CopperheadService == null) {
                                Logger.e("No Copperhead service found.");
                                return;
                            }
                            /*
						    	 * Get command and response channels.
						    	 */
                            _CommandChannel = _CopperheadService.getCharacteristic(COPPERHEAD_CMD_UUID);
                            _ResponseChannel = _CopperheadService.getCharacteristic(COPPERHEAD_RSP_UUID);
                            if (_CommandChannel == null) {
                                Logger.e("Could not find COPPERHEAD_CMD_UUID");
                                return;
                            } else if (_ResponseChannel == null) {
                                Logger.e("Could not find COPPERHEAD_RSP_UUID");
                                return;
                            }
                            /*
						    	 * Enable the response channel to receive incoming data notifications.
						    	 */
                            BluetoothGattDescriptor rsp_config_desc = _ResponseChannel.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
                            if (rsp_config_desc == null) {
                                Logger.e("RSP has no client config.");
                                return;
                            }
                            BLEIoOperation notify = new BLEIoOperation(BLEIoOperation.Type.NOTIFY_START, "Enable response channel notifications.");
                            notify.set_characteristic(_ResponseChannel);
                            notify.set_descriptor(rsp_config_desc);
                            queue.add(notify);
                            final BLEIoQueue fq = queue;
                            Packet auth = new Packet(19);
                            /*
						    	 * Send the "START AUTH" packet -> 0x90 0x01 0x01 0x00 .....
						    	 */
                            auth.setProtocolLayer(CommandResponseOperation.ProtocolLayer.SESSION);
                            auth.setPacketCount(0);
                            auth.setPacketIndex(0);
                            auth.setSequenceNumber(1);
                            auth.setCommandBytes((byte) 1, (byte) 1);
                            addPacket(queue, auth.getBuffer(), new BLEIoOperation.OnResponseCallback() {

                                @Override
                                public void onData(Packet challenge_packet) {
                                    Logger.d("<< " + challenge_packet.toString());
                                    ByteBuffer buffer = challenge_packet.getBuffered(ByteOrder.LITTLE_ENDIAN);
                                    // remove op code and length
                                    int opcode = buffer.get();
                                    int length = buffer.get();
                                    switch(buffer.get()) {
                                        case 0x41:
                                            Logger.i("Received authentication challenge");
                                            /*
												 * Get 16 bytes of AUTH nonce
												 */
                                            byte[] nonce = new byte[16];
                                            buffer.get(nonce);
                                            if ((nonce == null) || (nonce.length != 16)) {
                                                Logger.e("Missing or invalid authentication challenge nonce");
                                            } else {
                                                CopperheadCRC32 crc = new CopperheadCRC32();
                                                byte[] auth_token = Utils.hexToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
                                                Logger.d("NONCE: " + Utils.bytesToHex(nonce));
                                                /*
													 * Create the response packet: 0xb0 0x03 0x02 [2 BYTES OF CRC] 0x00 ...
													 */
                                                Packet resp_packet = new Packet(19);
                                                resp_packet.setProtocolLayer(CommandResponseOperation.ProtocolLayer.SESSION);
                                                resp_packet.setPacketCount(0);
                                                resp_packet.setPacketIndex(0);
                                                resp_packet.setSequenceNumber(challenge_packet.getSequenceNumber() + 1);
                                                ByteBuffer response = ByteBuffer.allocate(18);
                                                response.put((byte) 0x03);
                                                response.put((byte) 0x02);
                                                crc.update(nonce);
                                                crc.update(auth_token);
                                                short sum = (short) ((0xFFFF & crc.getValue()) ^ (0xFFFF & crc.getValue() >>> 16));
                                                response.putShort(sum);
                                                resp_packet.setPayload(response.array());
                                                addPacket(fq, resp_packet.getBuffer(), new BLEIoOperation.OnResponseCallback() {

                                                    @Override
                                                    public void onData(Packet challenge_response) {
                                                        Logger.d("<< " + challenge_response.toString());
                                                        ByteBuffer buffer = challenge_response.getBuffered(ByteOrder.LITTLE_ENDIAN);
                                                        // remove op code and length
                                                        int opcode = buffer.get();
                                                        int length = buffer.get();
                                                        /*
															 * Get the authentication reply code.
															 */
                                                        int reply = buffer.get();
                                                        if (reply == 0x42) {
                                                            Logger.i("Succesfully authenticated.");
                                                            // Request some settings
                                                            requestSetting(fq, Utils.getSettingCode("BAND_COLOR"));
                                                            requestSetting(fq, Utils.getSettingCode("FUEL"));
                                                            requestSetting(fq, Utils.getSettingCode("FIRST_NAME"));
                                                            requestSetting(fq, Utils.getSettingCode("SERIAL_NUMBER"));
                                                        } else {
                                                            Logger.e("Authentication failure, reply: " + reply);
                                                        }
                                                    }
                                                });
                                            }
                                            break;
                                        default:
                                            Logger.e("Unknown auth code.");
                                    }
                                }
                            });
                        }
                    });
                    device.connectGatt(MainActivity.this, false, _ioqueue);
                }
            } catch (Exception e) {
                Logger.e(e.toString());
            }
        }
    };
    Logger.i("Starting scann ...");
    _scanning = true;
    _btAdapter.startLeScan(_leScanCallback);
}
Also used : BluetoothDevice(android.bluetooth.BluetoothDevice) Bundle(android.os.Bundle) BluetoothGattService(android.bluetooth.BluetoothGattService) Intent(android.content.Intent) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic) ByteBuffer(java.nio.ByteBuffer) BluetoothGatt(android.bluetooth.BluetoothGatt) BluetoothGattDescriptor(android.bluetooth.BluetoothGattDescriptor) BluetoothAdapter(android.bluetooth.BluetoothAdapter)

Example 3 with BluetoothGattCharacteristic

use of android.bluetooth.BluetoothGattCharacteristic in project BleSensorTag by StevenRudenko.

the class BleServicesAdapter method getChildView.

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
    final ChildViewHolder holder;
    if (convertView == null) {
        holder = new ChildViewHolder();
        convertView = inflater.inflate(R.layout.li_characteristic, parent, false);
        holder.name = (TextView) convertView.findViewById(R.id.name);
        holder.uuid = (TextView) convertView.findViewById(R.id.uuid);
        holder.modes = (TextView) convertView.findViewById(R.id.modes);
        holder.seek = (SeekBar) convertView.findViewById(R.id.seek);
        holder.seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (serviceListener == null || def == null || !fromUser) {
                    return;
                }
                final BaseSensor<?> sensor = (BaseSensor<?>) def.getSensor(holder.service.getUuid().toString());
                if (sensor == null) {
                    return;
                }
                if (sensor instanceof TiPeriodicalSensor) {
                    final TiPeriodicalSensor periodicalSensor = (TiPeriodicalSensor) sensor;
                    periodicalSensor.setPeriod(progress + periodicalSensor.getMinPeriod());
                    serviceListener.onServiceUpdated(holder.service);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
        convertView.setTag(holder);
    } else {
        holder = (ChildViewHolder) convertView.getTag();
    }
    final BluetoothGattCharacteristic item = getChild(groupPosition, childPosition);
    final String uuid = item.getUuid().toString();
    final String name;
    final String modes = getModeString(item.getProperties());
    holder.service = item.getService();
    final String serviceUUID = item.getService().getUuid().toString();
    final Sensor<?> sensor = def != null ? (Sensor<?>) def.getSensor(serviceUUID) : null;
    // reset visibility
    holder.uuid.setVisibility(View.VISIBLE);
    holder.seek.setVisibility(View.GONE);
    if (sensor != null) {
        name = sensor.getCharacteristicName(uuid);
        if (sensor instanceof BaseSensor) {
            final BaseSensor<?> tiSensor = (BaseSensor<?>) sensor;
            if (tiSensor.isConfigUUID(uuid)) {
                if (sensor instanceof TiPeriodicalSensor) {
                    final TiPeriodicalSensor periodicalSensor = (TiPeriodicalSensor) sensor;
                    final int max = periodicalSensor.getMaxPeriod() - periodicalSensor.getMinPeriod();
                    final int value = periodicalSensor.getPeriod() - periodicalSensor.getMinPeriod();
                    holder.seek.setMax(max);
                    holder.seek.setProgress(value);
                    holder.seek.setVisibility(View.VISIBLE);
                    holder.uuid.setVisibility(View.GONE);
                }
            }
        }
    } else {
        name = "Unknown";
    }
    holder.name.setText(name);
    holder.uuid.setText(uuid);
    holder.modes.setText(modes);
    return convertView;
}
Also used : SeekBar(android.widget.SeekBar) BaseSensor(sample.ble.sensortag.sensor.BaseSensor) TiPeriodicalSensor(sample.ble.sensortag.sensor.ti.TiPeriodicalSensor) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic)

Example 4 with BluetoothGattCharacteristic

use of android.bluetooth.BluetoothGattCharacteristic in project Gadgetbridge by Freeyourgadget.

the class UpdateFirmwareOperation method sendFirmwareData.

/**
     * Method that uploads a firmware (fwbytes) to the Mi Band.
     * The firmware has to be split into chunks of 20 bytes each, and periodically a COMMAND_SYNC command has to be issued to the Mi Band.
     * <p/>
     * The Mi Band will send a notification after receiving this data to confirm if the firmware looks good to it.
     *
     * @param fwbytes
     * @return whether the transfer succeeded or not. Only a BT layer exception will cause the transmission to fail.
     * @see MiBandSupport#handleNotificationNotif
     */
private boolean sendFirmwareData(byte[] fwbytes) {
    int len = fwbytes.length;
    final int packetLength = 20;
    int packets = len / packetLength;
    BluetoothGattCharacteristic characteristicControlPoint = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
    BluetoothGattCharacteristic characteristicFWData = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_FIRMWARE_DATA);
    try {
        // going from 0 to len
        int firmwareProgress = 0;
        TransactionBuilder builder = performInitialized("send firmware packet");
        if (prefs.getBoolean("mi_low_latency_fw_update", true)) {
            getSupport().setLowLatency(builder);
        }
        for (int i = 0; i < packets; i++) {
            byte[] fwChunk = Arrays.copyOfRange(fwbytes, i * packetLength, i * packetLength + packetLength);
            builder.write(characteristicFWData, fwChunk);
            firmwareProgress += packetLength;
            int progressPercent = (int) ((((float) firmwareProgress) / len) * 100);
            if ((i > 0) && (i % 50 == 0)) {
                builder.write(characteristicControlPoint, new byte[] { MiBandService.COMMAND_SYNC });
                builder.add(new SetProgressAction(getContext().getString(R.string.updatefirmwareoperation_update_in_progress), true, progressPercent, getContext()));
            }
        }
        if (firmwareProgress < len) {
            byte[] lastChunk = Arrays.copyOfRange(fwbytes, packets * packetLength, len);
            builder.write(characteristicFWData, lastChunk);
            firmwareProgress = len;
        }
        builder.write(characteristicControlPoint, new byte[] { MiBandService.COMMAND_SYNC });
        builder.queue(getQueue());
    } catch (IOException ex) {
        LOG.error("Unable to send fw to MI", ex);
        GB.updateInstallNotification(getContext().getString(R.string.updatefirmwareoperation_firmware_not_sent), false, 0, getContext());
        return false;
    }
    return true;
}
Also used : TransactionBuilder(nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder) IOException(java.io.IOException) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic) SetProgressAction(nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction)

Example 5 with BluetoothGattCharacteristic

use of android.bluetooth.BluetoothGattCharacteristic in project Gadgetbridge by Freeyourgadget.

the class MiBand2Support method setWearLocation.

/**
     * Part of device initialization process. Do not call manually.
     *
     * @param builder
     * @return
     */
private MiBand2Support setWearLocation(TransactionBuilder builder) {
    LOG.info("Attempting to set wear location...");
    BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC8);
    if (characteristic != null) {
        builder.notify(characteristic, true);
        int location = MiBandCoordinator.getWearLocation(getDevice().getAddress());
        switch(location) {
            case // left hand
            0:
                builder.write(characteristic, MiBand2Service.WEAR_LOCATION_LEFT_WRIST);
                break;
            case // right hand
            1:
                builder.write(characteristic, MiBand2Service.WEAR_LOCATION_RIGHT_WRIST);
                break;
        }
        // TODO: this should actually be in some kind of finally-block in the queue. It should also be sent asynchronously after the notifications have completely arrived and processed.
        builder.notify(characteristic, false);
    }
    return this;
}
Also used : BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic)

Aggregations

BluetoothGattCharacteristic (android.bluetooth.BluetoothGattCharacteristic)42 BluetoothGattService (android.bluetooth.BluetoothGattService)8 TransactionBuilder (nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder)7 IOException (java.io.IOException)6 BluetoothGattDescriptor (android.bluetooth.BluetoothGattDescriptor)5 GregorianCalendar (java.util.GregorianCalendar)4 GBAlarm (nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm)4 Alarm (nodomain.freeyourgadget.gadgetbridge.model.Alarm)4 Calendar (java.util.Calendar)3 HashMap (java.util.HashMap)3 Prefs (nodomain.freeyourgadget.gadgetbridge.util.Prefs)3 UUID (java.util.UUID)2 CalendarEvents (nodomain.freeyourgadget.gadgetbridge.model.CalendarEvents)2 BaseSensor (sample.ble.sensortag.sensor.BaseSensor)2 TiPeriodicalSensor (sample.ble.sensortag.sensor.ti.TiPeriodicalSensor)2 BluetoothAdapter (android.bluetooth.BluetoothAdapter)1 BluetoothDevice (android.bluetooth.BluetoothDevice)1 BluetoothGatt (android.bluetooth.BluetoothGatt)1 BluetoothManager (android.bluetooth.BluetoothManager)1 Context (android.content.Context)1