Ücretsiz APK oluştur

JavaScript köprü API'si

Web Bluetooth

navigator.bluetooth yapısı yerel olarak yanıtlanır; böylece Chrome için yazılmış bir sayfa değişmeden çalışır.

navigator.bluetooth web standardı#

navigator.bluetooth — Web Bluetooth

Örnek

Standart Web Bluetooth: Chrome için yazacağınız aynı navigator.bluetooth kodu, her Bluetooth Low Energy cihazı için yüklü uygulamada çalışır.

Döndürür: web standardındaki gibi Promise'ler. Değerler DataView nesneleridir. Gerekir: Bluetooth. Açılacak bir anahtar yoktur: ZIP veya HTML sayfasından derlerken, kodunuz navigator.bluetooth (veya BluetoothUUID) ifadesini andığında derleme bunu kendiliğinden açar. Bir web sitesi (URL) derlemesi bunu açamaz. Açık değilse navigator.bluetooth yoktur. İlk requestDevice() Yakındaki cihazlar iznini ister (Android 11 ve öncesinde Konum). Bluetooth kapalıysa uygulama kullanıcıdan açmasını ister ve ardından cihaz listesini kendiliğinden açar; Android 6 ile 11 arasında aynısını Konum ayarı için yapar, çünkü bu sürümler Konum kapalıyken hiçbir Bluetooth cihazı bulamaz.

Nabız bandı, bir düğme dokunuşundan. navigator.bluetooth ilk betiğiniz çalışmadan önce vardır, bu yüzden sayfanın başındaki özellik tespiti çalışır; burada olduğu gibi işleyicinin içinde kontrol etmek yine de en güvenli alışkanlıktır:

var hrDevice = null;

document.getElementById('connect').addEventListener('click', async function () {
  if (!navigator.bluetooth) { showStatus('Bluetooth is not available in this app.'); return; }
  try {
    hrDevice = await navigator.bluetooth.requestDevice({
      filters: [{ services: ['heart_rate'] }],        // or { name: 'Polar H10' } / { namePrefix: 'Polar' }
      optionalServices: ['battery_service']
    });
    hrDevice.addEventListener('gattserverdisconnected', function () {
      showStatus('Strap disconnected');
    });
    var server = await hrDevice.gatt.connect();
    var hr = await server.getPrimaryService('heart_rate');
    var chr = await hr.getCharacteristic('heart_rate_measurement');
    chr.addEventListener('characteristicvaluechanged', function (e) {
      var v = e.target.value;                                   // DataView
      var bpm = (v.getUint8(0) & 1) ? v.getUint16(1, true) : v.getUint8(1);
      document.getElementById('bpm').textContent = bpm;
    });
    await chr.startNotifications();

    var battery = await server.getPrimaryService('battery_service');
    var level = await (await battery.getCharacteristic('battery_level')).readValue();
    document.getElementById('battery').textContent = level.getUint8(0) + '%';
  } catch (err) {
    // NotFoundError: user cancelled the chooser, Bluetooth is off, or no such service.
    // SecurityError: permission denied.  NetworkError: connection lost.
    showStatus(err.name + ': ' + err.message);
  }
});

document.getElementById('disconnect').addEventListener('click', function () {
  if (hrDevice && hrDevice.gatt.connected) hrDevice.gatt.disconnect();
});

Yazma. writeValue ve writeValueWithResponse cihazın onaylamasını bekler; writeValueWithoutResponse beklemez:

async function sendCommands(server) {
  // Heart Rate Control Point: 0x01 = reset energy expended
  var hr = await server.getPrimaryService('heart_rate');
  var ctrl = await hr.getCharacteristic('heart_rate_control_point');
  await ctrl.writeValueWithResponse(new Uint8Array([0x01]));

  // A custom UART-style service (full 128-bit UUIDs work everywhere)
  var uart = await server.getPrimaryService('6e400001-b5a3-f393-e0a9-e50e24dcca9e');
  var rx = await uart.getCharacteristic('6e400002-b5a3-f393-e0a9-e50e24dcca9e');
  await rx.writeValueWithoutResponse(new TextEncoder().encode('LED ON\n'));
}

Cihaz gezgini. Yakındaki herhangi bir cihazı seçin ve sahip olduğu tüm servisleri ve karakteristikleri, her birinin neler yapabildiğiyle birlikte listeleyin:

document.getElementById('explore').addEventListener('click', async function () {
  if (!navigator.bluetooth) { showStatus('Bluetooth is not available in this app.'); return; }
  try {
    var device = await navigator.bluetooth.requestDevice({ acceptAllDevices: true });
    var server = await device.gatt.connect();
    var lines = [];
    for (var service of await server.getPrimaryServices()) {
      lines.push(service.uuid === BluetoothUUID.getService('battery_service') ? 'Battery' : service.uuid);
      var chars = await service.getCharacteristics().catch(function () { return []; });
      chars.forEach(function (c) {
        var can = Object.keys(c.properties).filter(function (k) { return c.properties[k]; });
        lines.push('  ' + c.uuid + '  ' + can.join(', '));
      });
    }
    document.getElementById('tree').textContent = lines.join('\n');
    device.gatt.disconnect();
  } catch (err) {
    showStatus(err.name + ': ' + err.message);
  }
});

Bisiklet hız ve pedal çevirme (kadans) sensörü. Standart CSC servisinde tek bir sensör (veya ayrı bir hız ve kadans çifti). Değerler artan toplamlardır; bu yüzden hız ve kadans iki bildirim arasındaki farktan hesaplanır:

var WHEEL_MM = 2105;                       // 700x25c; set your own wheel circumference
var last = null;

async function connectCsc() {
  var device = await navigator.bluetooth.requestDevice({
    filters: [{ services: ['cycling_speed_and_cadence'] }]      // same as { services: [0x1816] }
  });
  device.addEventListener('gattserverdisconnected', function () { showStatus('Sensor disconnected'); });
  var server = await device.gatt.connect();
  var csc = await server.getPrimaryService('cycling_speed_and_cadence');
  var chr = await csc.getCharacteristic('csc_measurement');
  chr.addEventListener('characteristicvaluechanged', function (e) {
    var v = e.target.value, flags = v.getUint8(0), i = 1, now = {};
    if (flags & 1) { now.wheels = v.getUint32(i, true); now.wheelTime = v.getUint16(i + 4, true); i += 6; }
    if (flags & 2) { now.cranks = v.getUint16(i, true); now.crankTime = v.getUint16(i + 2, true); }
    if (last) {
      if (now.wheels !== undefined && now.wheelTime !== last.wheelTime) {
        var dt = ((now.wheelTime - last.wheelTime) & 0xffff) / 1024;          // seconds
        var kmh = (now.wheels - last.wheels) * WHEEL_MM / 1e6 / (dt / 3600);
        document.getElementById('speed').textContent = kmh.toFixed(1) + ' km/h';
      }
      if (now.cranks !== undefined && now.crankTime !== last.crankTime) {
        var ct = ((now.crankTime - last.crankTime) & 0xffff) / 1024;
        var rpm = ((now.cranks - last.cranks) & 0xffff) / ct * 60;
        document.getElementById('cadence').textContent = Math.round(rpm) + ' rpm';
      }
    }
    last = Object.assign({}, last, now);
  });
  await chr.startNotifications();
}

Her hatayı ekranda göstermek. Her adım adlandırılmış bir hatayla reddedilir; böylece sayfa sessiz kalmak yerine kullanıcıya ne yapacağını söyleyebilir:

async function connectWithMessage(connect) {
  try {
    await connect();
    showStatus('Connected');
  } catch (err) {
    var msg = {
      NotFoundError: 'No sensor chosen, Bluetooth was left off, or the sensor lacks that service.',
      SecurityError: 'Bluetooth permission was refused. Allow "Nearby devices" in the app settings.',
      NetworkError: 'The sensor went out of range or is connected to another app or watch. Try again.',
      TypeError: 'Programming error: ' + err.message
    }[err.name] || err.message;
    showStatus(err.name + ': ' + msg);
  }
}
document.getElementById('scan-hr').addEventListener('click', function () { connectWithMessage(connectHeartRate); });
document.getElementById('scan-csc').addEventListener('click', function () { connectWithMessage(connectCsc); });

Notlar: Cihaz seçici uygulama tarafından çizilir ve 30 saniye tarar, ardından "Yeniden tara" seçeneğini sunar; bir sayfa yalnızca kullanıcının seçtiği cihaza erişebilir. getAvailability(), telefonda Bluetooth'un olup olmadığını yanıtlar (Chrome'daki gibi), açık olup olmadığını değil: requestDevice() açmayı ister. Adını yalnızca tarama yanıtında gönderen bir sensör yine de adıyla listelenir ve namePrefix ile eşleşir. Android'in hemen kopardığı ilk bağlantı, connect() reddetmeden önce yeniden denenir. filters veya optionalServices içinde yanlış yazılmış bir servis adı TypeError ile reddedilir. Bir services filtresi yalnızca cihazın duyurduğu servislerle eşleşir. connect() sonrasında cihazın tüm servisleri, optionalServices içinde olmayanlar bile kullanılabilir (yine de bırakın, Chrome'un buna ihtiyacı var). Ayrıca kullanılabilir: getAvailability(), getPrimaryServices(), getCharacteristics(), stopNotifications(), characteristic.properties, device.forget(), BluetoothUUID.getService/getCharacteristic/canonicalUUID. getDevices(), requestLEScan(), watchAdvertisements() ve tanımlayıcılar NotSupportedError ile reddedilir. Sayıları zaten ayrıştırılmış standart fitness sensörleri için bkz. bleStartScan.

wbConnect köprü#

window.WebToApk.wbConnect(requestId: String, deviceId: String)

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

device.gatt.connect() arkasındaki iç aktarım. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: (gatt.connect() aracılığıyla) cihazın hizmetleri keşfedildikten sonra BluetoothRemoteGATTServer Promise'i. Gerekir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

async function connectAndList(device) {
  try {
    var server = await device.gatt.connect();
    var services = await server.getPrimaryServices();
    services.forEach(function (s) { console.log('service', s.uuid); });
    return server;
  } catch (err) {
    showStatus('Could not connect: ' + err.message);    // NetworkError, NotFoundError
    return null;
  }
}

Cihaz koptuğunda yeniden bağlanın. Aynı cihazda connect() işlevini yeniden çağırmak çalışır:

device.addEventListener('gattserverdisconnected', async function () {
  showStatus('Reconnecting...');
  try { await connectAndList(device); showStatus('Connected'); } catch (e) {}
});

İki sensöre aynı anda bağlanın, örneğin bir nabız bandı ve bir güç ölçer:

async function connectBoth(hrDevice, powerDevice) {
  var servers = await Promise.all([hrDevice.gatt.connect(), powerDevice.gatt.connect()]);
  var hr = await servers[0].getPrimaryService('heart_rate');
  var power = await servers[1].getPrimaryService('cycling_power');
  return {
    heartRate: await hr.getCharacteristic('heart_rate_measurement'),
    power: await power.getCharacteristic('cycling_power_measurement')
  };
}

Notlar: Ham imza wbConnect(requestId, deviceId). Zaten bağlı bir cihaza bağlanmak hemen yeniden çözülür. getPrimaryService(s), connect() tamamlanmadan önce NetworkError ile reddedilir. Aynı anda birkaç cihaz bağlanabilir.

wbDisconnect köprü#

window.WebToApk.wbDisconnect(deviceId: String)

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

device.gatt.disconnect() (ve device.forget()) arkasındaki dahili aktarım katmanı. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: hiçbir şey (disconnect() web standardında olduğu gibi eşzamanlıdır). Ardından cihaz gattserverdisconnected olayını tetikler. Gerektirir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

var device = null;   // from navigator.bluetooth.requestDevice(...)

document.getElementById('stop').addEventListener('click', function () {
  if (device && device.gatt.connected) device.gatt.disconnect();
});

// Fires for your own disconnect() and when the device goes away by itself.
function watch(dev) {
  dev.addEventListener('gattserverdisconnected', function () {
    showStatus('Disconnected from ' + (dev.name || dev.id));
  });
}

Kendi Durdur işleminizi, sensörün menzil dışına çıkmasından ayırın ve yalnızca ikinci durumda yeniden bağlanın:

var userStopped = false;

function stopSession(device) {
  userStopped = true;
  if (device.gatt.connected) device.gatt.disconnect();
}

function watchDrops(device) {
  device.addEventListener('gattserverdisconnected', function () {
    if (userStopped) { userStopped = false; showStatus('Session ended'); return; }
    showStatus('Sensor out of range, reconnecting...');
    device.gatt.connect()
      .then(resubscribe)                 // your code: get the characteristics, startNotifications()
      .catch(function () { showStatus('Could not reconnect'); });
  });
}

Bir "Sensörü kaldır" düğmesi: forget() bağlantıyı keser ve cihazı bırakır, ardından gattserverdisconnected gelmez:

var device = null;   // from navigator.bluetooth.requestDevice(...)

document.getElementById('forget').addEventListener('click', async function () {
  if (!device) return;
  await device.forget();
  device = null;
  showStatus('Sensor removed. Tap Connect to pick one again.');
});

Notlar: Ham imza wbDisconnect(deviceId). Bağlantı kesildikten sonra eski hizmet ve özellik nesneleri bildirim almayı bırakır; bir sonraki connect() sonrasında onları yeniden alın ve startNotifications() işlevini yeniden çağırın. Uygulama kapandığında her bağlantıyı bırakır.

wbGetCharacteristics köprü#

window.WebToApk.wbGetCharacteristics(requestId: String, deviceId: String, service: String)

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

service.getCharacteristic(uuid) ve service.getCharacteristics() arkasındaki iç aktarım. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: (hizmet aracılığıyla) bir BluetoothRemoteGATTCharacteristic Promise'i veya her biri uuid ve properties ile (read, write, writeWithoutResponse, notify, indicate, broadcast, authenticatedSignedWrites) bunların bir dizisi. Gerekir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

async function describe(server) {
  var service = await server.getPrimaryService('heart_rate');

  // One characteristic, by standard name, 16-bit number or full UUID:
  var measurement = await service.getCharacteristic('heart_rate_measurement'); // same as 0x2a37

  // All of them:
  var list = await service.getCharacteristics();
  list.forEach(function (c) {
    var p = c.properties;
    console.log(c.uuid, p.read ? 'read' : '', p.write ? 'write' : '', p.notify ? 'notify' : '');
  });
  return measurement;
}

UUID'lerini koda sabit yazmak yerine, özel bir servisin karakteristiklerini yapabildikleri işe göre bulun:

async function findSerialPipes(server) {
  var svc = await server.getPrimaryService('0000ffe0-0000-1000-8000-00805f9b34fb');
  var list = await svc.getCharacteristics();
  var incoming = list.find(function (c) { return c.properties.notify || c.properties.indicate; });
  var outgoing = list.find(function (c) { return c.properties.write || c.properties.writeWithoutResponse; });
  if (!incoming || !outgoing) throw new Error('This device does not look like a serial adapter');
  return { incoming: incoming, outgoing: outgoing };
}

İsteğe bağlı bir karakteristiği okuyun ve NotFoundError hatasını "bu cihazda yok" olarak değerlendirin:

var LOCATIONS = ['Other', 'Chest', 'Wrist', 'Finger', 'Hand', 'Ear lobe', 'Foot'];

async function sensorLocation(server) {
  var hr = await server.getPrimaryService('heart_rate');
  try {
    var chr = await hr.getCharacteristic('body_sensor_location');   // 0x2a38, optional in the spec
    var v = await chr.readValue();
    return LOCATIONS[v.getUint8(0)] || 'Unknown';
  } catch (err) {
    if (err.name === 'NotFoundError') return null;                   // this strap does not report it
    throw err;
  }
}

Notlar: Ham imza wbGetCharacteristics(requestId, deviceId, service). Servisin sahip olmadığı bir UUID NotFoundError ile reddedilir; bilinmeyen bir ad TypeError hatası verir (özel karakteristikler için tam bir UUID verin). Liste servis başına bir kez alınır, sonra yeniden kullanılır.

wbIsAvailable köprü#

window.WebToApk.wbIsAvailable(): Boolean

getAvailability(): telefonda Bluetooth OLUP OLMADIĞI (Chrome'un yanıtı), açık olup olmadığı değil. requestDevice(), kullanıcıdan açmasını ister; yalnızca kapalıyken false yanıtı vermek, önce kontrol eden sayfaların ("if (!await getAvailability())") "Bluetooth desteklenmiyor" demesine ve o isteme hiç ulaşmamasına yol açıyordu (fitness raporu 2026-10-03).

Örnek

navigator.bluetooth.getAvailability() arkasındaki iç aktarım. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: (getAvailability() aracılığıyla) derlemede Bluetooth varsa ve telefonun Bluetooth'u açıksa true, aksi halde false Promise'i. Gerekir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

async function updateBluetoothHint() {
  var hint = document.getElementById('bt-hint');
  if (!navigator.bluetooth) { hint.textContent = 'Bluetooth is not available in this app.'; return; }
  var on = await navigator.bluetooth.getAvailability();
  hint.textContent = on ? '' : 'Turn on Bluetooth to connect your sensor.';
}
document.addEventListener('visibilitychange', function () {
  if (!document.hidden) updateBluetoothHint();
});

Bağlan düğmesini yalnızca Bluetooth açıkken etkinleştirin ve kullanıcı uygulamaya her döndüğünde yeniden kontrol edin:

async function refreshConnectButton() {
  var btn = document.getElementById('connect');
  if (!navigator.bluetooth) { btn.hidden = true; return; }
  btn.disabled = !(await navigator.bluetooth.getAvailability());
}
window.addEventListener('load', refreshConnectButton);
document.addEventListener('visibilitychange', function () {
  if (!document.hidden) refreshConnectButton();
});

Seçiciyi açmadan önce, sonrasında bir NotFoundError yerine net bir "Bluetooth kapalı" mesajı verin:

document.getElementById('scan').addEventListener('click', async function () {
  if (!navigator.bluetooth) { showStatus('Bluetooth is not available in this app.'); return; }
  if (!(await navigator.bluetooth.getAvailability())) {
    showStatus('Bluetooth is off. Turn it on, then tap Scan again.');
    return;
  }
  try {
    var device = await navigator.bluetooth.requestDevice({ acceptAllDevices: true });
    showStatus('Picked ' + (device.name || device.id));
  } catch (err) {
    showStatus(err.name === 'NotFoundError' ? 'No device chosen.' : err.message);
  }
});

Notlar: Ham imza wbIsAvailable(): Boolean (eşzamanlı). Yalnızca bağdaştırıcıyı kontrol eder - hiçbir izin istemez. Web standardının availabilitychanged olayı tetiklenmez, bu yüzden sayfa görünür olduğunda yeniden kontrol edin.

wbNotify köprü#

window.WebToApk.wbNotify(

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

characteristic.startNotifications() ve stopNotifications() arkasındaki iç aktarım. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: (özellik aracılığıyla) özelliğin kendisinin bir Promise'i. Her yeni değer, üzerinde characteristicvaluechanged tetikler; değer event.target.value içindedir (bir DataView). Gerekir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

var cadenceChr = null;

async function startCadence(server) {
  var svc = await server.getPrimaryService('running_speed_and_cadence');
  cadenceChr = await svc.getCharacteristic('rsc_measurement');
  cadenceChr.addEventListener('characteristicvaluechanged', onRsc);
  await cadenceChr.startNotifications();
}

function onRsc(e) {
  var v = e.target.value;
  var kmh = v.getUint16(1, true) / 256 * 3.6;
  var spm = v.getUint8(3);
  show('run', kmh.toFixed(1) + ' km/h, ' + spm + ' steps/min');
}

async function stopCadence() {
  if (!cadenceChr) return;
  cadenceChr.removeEventListener('characteristicvaluechanged', onRsc);
  try { await cadenceChr.stopNotifications(); } catch (e) {}
}

Ölçümü yalnızca indication destekleyen bir termometreye aynı şekilde abone olunur; burada oncharacteristicvaluechanged özelliği üzerinden:

async function watchThermometer(server) {
  var svc = await server.getPrimaryService('health_thermometer');
  var chr = await svc.getCharacteristic('temperature_measurement');
  chr.oncharacteristicvaluechanged = function (e) {
    var v = e.target.value;
    var mantissa = v.getUint32(1, true) & 0x00ffffff;          // IEEE-11073 FLOAT
    if (mantissa & 0x800000) mantissa -= 0x1000000;
    var fahrenheit = v.getUint8(0) & 1;
    show('temp', (mantissa * Math.pow(10, v.getInt8(4))).toFixed(1) + (fahrenheit ? ' °F' : ' °C'));
  };
  await chr.startNotifications();
}

Seri tarzı bir cihazdan metin satırları alın; bir satırı ortadan bölen bildirimleri birleştirin:

async function listenForLines(server, onLine) {
  var uart = await server.getPrimaryService('6e400001-b5a3-f393-e0a9-e50e24dcca9e');
  var tx = await uart.getCharacteristic('6e400003-b5a3-f393-e0a9-e50e24dcca9e');
  if (!tx.properties.notify && !tx.properties.indicate) throw new Error('This device does not stream data');
  var decoder = new TextDecoder(), buffer = '';
  tx.addEventListener('characteristicvaluechanged', function (e) {
    buffer += decoder.decode(e.target.value, { stream: true });
    var lines = buffer.split('\n');
    buffer = lines.pop();
    lines.forEach(onLine);
  });
  await tx.startNotifications();
  return tx;
}

Notlar: Ham imza wbNotify(requestId, deviceId, service, characteristic, enable). Yalnızca gösterge (indication) destekleyen bir özellik otomatik olarak göstergelerle abone olunur. Bildirim veremeyen bir özellik NotSupportedError ile reddedilir. oncharacteristicvaluechanged = fn de çalışır. Bağlantı kesildikten sonra yeniden abone olun.

wbRead köprü#

window.WebToApk.wbRead(requestId: String, deviceId: String, service: String, characteristic: String)

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

characteristic.readValue() arkasındaki iç aktarım. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: (readValue() aracılığıyla) bir DataView Promise'i; characteristic.value de güncellenir. Gerekir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

async function readInfo(server) {
  try {
    var battery = await server.getPrimaryService('battery_service');
    var level = await (await battery.getCharacteristic('battery_level')).readValue();
    show('battery', level.getUint8(0) + '%');

    var info = await server.getPrimaryService('device_information');
    var maker = await (await info.getCharacteristic('manufacturer_name_string')).readValue();
    show('maker', new TextDecoder().decode(maker));
  } catch (err) {
    // NotFoundError: the device has no such service/characteristic
    // NotSupportedError: read rejected by the device   NetworkError: not connected / read failed
    show('info', err.message);
  }
}

Yalnızca okunabilen bir sensörü yoklayın; burada standart Temperature karakteristiği (0x2a6e, derecenin yüzde biri cinsinden):

var pollTimer = null;

async function startTemperaturePolling(server) {
  var env = await server.getPrimaryService('environmental_sensing');
  var temp = await env.getCharacteristic(0x2a6e);
  pollTimer = setInterval(async function () {
    try {
      var v = await temp.readValue();
      show('temp', (v.getInt16(0, true) / 100).toFixed(1) + ' °C');
    } catch (err) {
      clearInterval(pollTimer);          // NetworkError once the sensor is gone
      show('temp', err.message);
    }
  }, 5000);
}

Birkaç okumayı aynı anda başlatarak bir "Bu cihaz hakkında" panelini doldurun; sizin için birbiri ardına çalışırlar:

async function readDeviceInfo(server) {
  var info = await server.getPrimaryService('device_information');
  var names = ['model_number_string', 'serial_number_string', 'firmware_revision_string'];
  var decoder = new TextDecoder();
  var results = await Promise.allSettled(names.map(async function (name) {
    var chr = await info.getCharacteristic(name);
    return decoder.decode(await chr.readValue());
  }));
  results.forEach(function (r, i) {
    show(names[i], r.status === 'fulfilled' ? r.value : '-');   // missing ones reject with NotFoundError
  });
}

Notlar: Ham imza wbRead(requestId, deviceId, service, characteristic). Bir cihazdaki okuma, yazma ve bildirim değişiklikleri, çağırdığınız sırayla birbiri ardına çalışır; böylece arada beklemeden birkaçını art arda başlatabilirsiniz.

wbRequestDevice köprü#

window.WebToApk.wbRequestDevice(requestId: String, optionsJson: String)

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

navigator.bluetooth.requestDevice(options) arkasındaki iç aktarım: uygulamanın cihaz seçicisini gösterir. Sayfalar navigator.bluetooth.requestDevice kullanır; bunu doğrudan çağırmayın.

Döndürür: (requestDevice aracılığıyla) bir BluetoothDevice {id, name, gatt} Promise'i. Gerekir: Bluetooth (kodunuz navigator.bluetooth ifadesini andığında ZIP veya HTML derlemesi tarafından açılır) ve ilk kullanımda sorulan Yakındaki cihazlar izni.

document.getElementById('pick').addEventListener('click', async function () {
  if (!navigator.bluetooth) { showStatus('Bluetooth is not available in this app.'); return; }
  try {
    var device = await navigator.bluetooth.requestDevice({
      filters: [{ services: ['cycling_power'] }, { namePrefix: 'KICKR' }],
      optionalServices: ['battery_service']
    });
    showStatus('Picked ' + (device.name || device.id));
  } catch (err) {
    if (err.name === 'NotFoundError') showStatus('No device chosen.');   // also: Bluetooth off
    else showStatus(err.name + ': ' + err.message);                     // SecurityError = permission
  }
});

Filtrelemek yerine yakındaki tüm cihazları listelemek için: requestDevice({ acceptAllDevices: true }).

Özel bir cihazı tam adı veya ad önekiyle seçin; bağlandıktan sonra kullanılabilmesi için kendi 128 bitlik servisini listeleyin:

async function pickLamp() {
  try {
    return await navigator.bluetooth.requestDevice({
      filters: [{ name: 'Desk Lamp' }, { namePrefix: 'LAMP-' }],   // either one matches
      optionalServices: ['0000ffe0-0000-1000-8000-00805f9b34fb']
    });
  } catch (err) {
    if (err.name === 'SecurityError') showStatus('Allow Nearby devices to find your lamp.');
    else if (err.name !== 'NotFoundError') showStatus(err.message);  // NotFoundError = cancelled
    return null;
  }
}

Cihazı oturum başına bir kez isteyin ve sonraki dokunuşlarda yeniden kullanın (getDevices() kullanılamaz, bu yüzden aldığınız nesneyi saklayın):

var scale = null;

document.getElementById('weigh').addEventListener('click', async function () {
  if (!navigator.bluetooth) { showStatus('Bluetooth is not available in this app.'); return; }
  try {
    if (!scale) {
      scale = await navigator.bluetooth.requestDevice({
        filters: [{ services: ['weight_scale'], namePrefix: 'MI' }]   // both keys must match
      });
    }
    var server = await scale.gatt.connect();
    var svc = await server.getPrimaryService('weight_scale');
    var chr = await svc.getCharacteristic('weight_measurement');
    chr.addEventListener('characteristicvaluechanged', onWeight);
    await chr.startNotifications();
  } catch (err) {
    showStatus(err.name + ': ' + err.message);
  }
});

Notlar: Ham imza wbRequestDevice(requestId, optionsJson); yanıt sayfaya değil, polyfill'e döner. requestDevice işlevini bir dokunuştan çağırın. Filtreler services (reklam edilmeli), name (tam eşleşme) ve namePrefix kullanır; bir filtre tüm anahtarları eşleştiğinde eşleşir ve cihaz herhangi bir filtre eşleştiğinde eşleşir. Ne filters ne de acceptAllDevices yoksa → TypeError. Seçiciyi iptal etmek NotFoundError ile reddeder. Seçici 30 saniye tarar. device.id cihazın Bluetooth adresidir.

wbWrite köprü#

window.WebToApk.wbWrite(

WebBluetoothPolyfill için ham aktarım katmanı. Bir sayfa bunları doğrudan çağırmaz; tarayıcıda yapacağı gibi navigator.bluetooth'u çağırır.

Kendi başına değil, grubu Web Bluetooth (navigator.bluetooth) tarafından açıklanır.

Örnek

characteristic.writeValue(), writeValueWithResponse() ve writeValueWithoutResponse() arkasındaki iç aktarım. Sayfalar navigator.bluetooth kullanır; bunu doğrudan çağırmayın.

Döndürür: (karakteristik aracılığıyla) undefined değerinin bir Promise'ini. Gerektirir: Bluetooth (kodunuz şunu andığında ZIP veya HTML derlemesi tarafından açılır: navigator.bluetooth).

Yanıtlı (writeValue da aynıdır): cihaz yazmayı onayladığında tamamlanır.

async function setTargetPower(server, watts) {
  var ftms = await server.getPrimaryService('fitness_machine');
  var cp = await ftms.getCharacteristic('00002ad9-0000-1000-8000-00805f9b34fb'); // FTMS control point
  await cp.writeValueWithResponse(new Uint8Array([0x00]));                       // request control
  var cmd = new DataView(new ArrayBuffer(3));
  cmd.setUint8(0, 0x05);                 // set target power
  cmd.setInt16(1, watts, true);
  await cp.writeValueWithResponse(cmd);
}

Yanıtsız: daha hızlı, bir paketin kaybolmasının önemli olmadığı akışlar için.

async function sendText(characteristic, text) {
  if (!characteristic.properties.writeWithoutResponse) throw new Error('This characteristic needs writeValue');
  await characteristic.writeValueWithoutResponse(new TextEncoder().encode(text));
}

Uzun bir metin komutunu 20 baytlık parçalar halinde gönderin. Uygulama cihazdan daha büyük bir paket boyutu istemez, bu yüzden tek yazmaya 20 bayt sığar:

async function sendLine(rx, text) {
  var bytes = new TextEncoder().encode(text + '\n');
  for (var i = 0; i < bytes.length; i += 20) {
    await rx.writeValueWithoutResponse(bytes.subarray(i, i + 20));
  }
}
// sendLine(rxCharacteristic, 'SET COLOR 255 120 0 BRIGHTNESS 80');

Notlar: Ham imza wbWrite(requestId, deviceId, service, characteristic, valueBase64, withResponse). Değer bir ArrayBuffer, herhangi bir tipli dizi, bir DataView veya düz bir bayt dizisi olabilir; başka her şey TypeError hatası verir. Hatalar: NotSupportedError (yazma reddedildi), NetworkError (yazma başarısız oldu veya bağlı değil), NotFoundError.

Her belge derlemesinde uygulama çalışma zamanından ve örnek dosyalarından oluşturulur. Markdown olarak okuyun · Tüm aileler.

22.10.2026 tarihinde yayınlanan köprüyle karşılaştırılarak kontrol edildi.