1. О чем речь?
В этой увлекательной кодовой лаборатории вы узнаете, как управлять беспламенной светодиодной свечой PLAYBULB с помощью только JavaScript, благодаря веб-интерфейсу Bluetooth API . Попутно вы также поиграетесь с такими функциями JavaScript ES2015, как классы , стрелочные функции , Map и Promises .
Что вы узнаете
- Как взаимодействовать с находящимся поблизости устройством Bluetooth с помощью JavaScript
- Как использовать классы ES2015, функции стрелок, карту и обещания
Что вам понадобится
- Базовое понимание веб-разработки
- Базовые знания Bluetooth Low Energy (BLE) и общего профиля атрибутов (GATT)
- Текстовый редактор по вашему выбору
- Mac, Chromebook или устройство Android M с браузерным приложением Chrome и кабелем USB micro-USB.
2. Играйте первым
Возможно, вы захотите проверить окончательную версию приложения, которое вы собираетесь создать, по адресу https://googlecodelabs.github.io/candle-bluetooth и поиграть с имеющимся в вашем распоряжении Bluetooth-устройством PLAYBULB Candle, прежде чем приступить к его изучению. кодовая лаборатория.
Вы также можете посмотреть, как я меняю цвета, на https://www.youtube.com/watch?v=fBCPA9gIxlU.
3. Настройте
Загрузите пример кода
Вы можете получить пример кода для этого кода, загрузив zip-архив здесь:
или клонировав этот репозиторий git:
git clone https://github.com/googlecodelabs/candle-bluetooth.git
Если вы загрузили исходный код в виде zip-архива, его распаковка должна предоставить вам корневую папку candle-bluetooth-master
.
Установите и проверьте веб-сервер
Хотя вы можете использовать собственный веб-сервер, эта лаборатория кода разработана для хорошей работы с веб-сервером Chrome. Если это приложение еще не установлено, его можно установить из Интернет-магазина Chrome.
После установки приложения «Веб-сервер для Chrome» нажмите ярлык «Приложения» на панели закладок:
В появившемся окне нажмите на значок Веб-сервера:
Далее вы увидите это диалоговое окно, которое позволит вам настроить локальный веб-сервер:
Нажмите кнопку «Выбрать папку» и выберите корень клонированного (или разархивированного) репозитория. Это позволит вам обслуживать незавершенную работу через URL-адрес, выделенный в диалоговом окне веб-сервера (в разделе URL-адреса веб-сервера ).
В разделе «Параметры» установите флажок « Автоматически показывать index.html », как показано ниже:
Теперь посетите свой сайт в веб-браузере (щелкнув выделенный URL-адрес веб-сервера), и вы должны увидеть страницу, которая выглядит следующим образом:
Если вы хотите увидеть, как это приложение выглядит на вашем телефоне Android, вам необходимо включить удаленную отладку на Android и настроить переадресацию портов (номер порта по умолчанию — 8887). После этого вы можете просто открыть новую вкладку Chrome по адресу http://localhost:8887 на своем телефоне Android.
Дальше
На данный момент это веб-приложение мало что делает. Давайте начнем добавлять поддержку Bluetooth!
4. Откройте для себя свечу
Мы начнем с написания библиотеки, которая использует класс JavaScript ES2015 для Bluetooth-устройства PLAYBULB Candle.
Сохранять спокойствие. Синтаксис класса не вводит в JavaScript новую объектно-ориентированную модель наследования. Он просто обеспечивает гораздо более понятный синтаксис для создания объектов и работы с наследованием, как вы можете прочитать ниже.
Сначала давайте определим класс PlaybulbCandle
в playbulbCandle.js
и создадим экземпляр playbulbCandle
, который позже будет доступен в файле app.js
playbulbCandle.js
(function() {
'use strict';
class PlaybulbCandle {
constructor() {
this.device = null;
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
Чтобы запросить доступ к ближайшему устройству Bluetooth, нам нужно вызвать navigator.bluetooth.requestDevice
. Поскольку устройство PLAYBULB Candle постоянно объявляет (если оно еще не сопряжено) постоянный UUID службы Bluetooth GATT, известный в краткой форме как 0xFF02
, мы можем просто определить константу и добавить ее к параметру сервисов фильтров в новом общедоступном методе connect
PlaybulbCandle
сорт.
Мы также будем отслеживать объект BluetoothDevice
внутри, чтобы при необходимости иметь к нему доступ позже. Поскольку navigator.bluetooth.requestDevice
возвращает обещание JavaScript ES2015 , мы сделаем это в методе then
.
playbulbCandle.js
(function() {
'use strict';
const CANDLE_SERVICE_UUID = 0xFF02;
class PlaybulbCandle {
constructor() {
this.device = null;
}
connect() {
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}]};
return navigator.bluetooth.requestDevice(options)
.then(function(device) {
this.device = device;
}.bind(this));
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
В целях безопасности обнаружение близлежащих устройств Bluetooth с помощью navigator.bluetooth.requestDevice
должно вызываться с помощью жеста пользователя, например касания или щелчка мыши. Вот почему мы будем вызывать метод connect
, когда пользователь нажимает кнопку «Подключиться» в файле app.js
:
приложение.js
document.querySelector('#connect').addEventListener('click', function(event) {
document.querySelector('#state').classList.add('connecting');
playbulbCandle.connect()
.then(function() {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
})
.catch(function(error) {
console.error('Argh!', error);
});
});
Запустите приложение
На этом этапе посетите свой сайт в веб-браузере (щелкнув URL-адрес веб-сервера, выделенный в приложении веб-сервера) или просто обновите существующую страницу. Нажмите зеленую кнопку «Подключиться», выберите устройство в средстве выбора и откройте свою любимую консоль Dev Tools с помощью сочетания клавиш Ctrl + Shift + J и обратите внимание на зарегистрированный объект BluetoothDevice
.
Вы можете получить сообщение об ошибке, если Bluetooth выключен и/или Bluetooth-устройство PLAYBULB Candle выключено. В этом случае включите его и продолжайте снова.
Обязательный бонус
Не знаю, как вы, но я уже вижу слишком много function() {}
в этом коде. Давайте вместо этого переключимся на стрелочные функции JavaScript ES2015 () => {}
. Они просто спасают жизнь: вся прелесть анонимных функций и никакой грусти привязки.
playbulbCandle.js
(function() {
'use strict';
const CANDLE_SERVICE_UUID = 0xFF02;
class PlaybulbCandle {
constructor() {
this.device = null;
}
connect() {
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}]};
return navigator.bluetooth.requestDevice(options)
.then(device => {
this.device = device;
});
}
}
window.playbulbCandle = new PlaybulbCandle();
})();
приложение.js
document.querySelector('#connect').addEventListener('click', event => {
playbulbCandle.connect()
.then(() => {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
})
.catch(error => {
console.error('Argh!', error);
});
});
Дальше
- Хорошо... можно мне вообще поговорить с этой свечой или как?
- Конечно... переходим к следующему шагу
Часто задаваемые вопросы
5. Почитайте что-нибудь
Итак, что же делать теперь, когда у вас есть BluetoothDevice
, возвращенный из обещания navigator.bluetooth.requestDevice
? Давайте подключимся к удаленному GATT-серверу Bluetooth, который содержит определения службы Bluetooth и характеристик, вызвав device.gatt.connect()
:
playbulbCandle.js
class PlaybulbCandle {
constructor() {
this.device = null;
}
connect() {
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}]};
return navigator.bluetooth.requestDevice(options)
.then(device => {
this.device = device;
return device.gatt.connect();
});
}
}
Прочитайте имя устройства
Здесь мы подключаемся к GATT-серверу Bluetooth-устройства PLAYBULB Candle. Теперь мы хотим получить первичную службу GATT (ранее объявленную как 0xFF02
) и прочитать характеристику имени устройства ( 0xFFFF
), принадлежащую этой службе. Этого можно легко добиться, добавив новый метод getDeviceName
в класс PlaybulbCandle
и используя device.gatt.getPrimaryService
и service.getCharacteristic
. characteristic.readValue
фактически вернет DataView
который мы просто декодируем с помощью TextDecoder
.
playbulbCandle.js
const CANDLE_DEVICE_NAME_UUID = 0xFFFF;
...
getDeviceName() {
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_DEVICE_NAME_UUID))
.then(characteristic => characteristic.readValue())
.then(data => {
let decoder = new TextDecoder('utf-8');
return decoder.decode(data);
});
}
Давайте добавим это в app.js
, вызвав playbulbCandle.getDeviceName
после подключения и отобразив имя устройства.
приложение.js
document.querySelector('#connect').addEventListener('click', event => {
playbulbCandle.connect()
.then(() => {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
return playbulbCandle.getDeviceName().then(handleDeviceName);
})
.catch(error => {
console.error('Argh!', error);
});
});
function handleDeviceName(deviceName) {
document.querySelector('#deviceName').value = deviceName;
}
На этом этапе посетите свой сайт в веб-браузере (щелкнув URL-адрес веб-сервера, выделенный в приложении веб-сервера) или просто обновите существующую страницу. Убедитесь, что свеча PLAYBULB включена, затем нажмите кнопку «Подключиться» на странице, и вы увидите имя устройства под палитрой цветов.
Прочитайте уровень заряда батареи
В Bluetooth-устройстве PLAYBULB Candle также доступна стандартная характеристика уровня заряда батареи Bluetooth , которая содержит уровень заряда батареи устройства. Это означает, что мы можем использовать стандартные имена, такие как battery_service
для UUID службы Bluetooth GATT и battery_level
для UUID характеристики Bluetooth GATT.
Добавим в класс PlaybulbCandle
новый метод getBatteryLevel
и будем считать уровень заряда батареи в процентах.
playbulbCandle.js
getBatteryLevel() {
return this.device.gatt.getPrimaryService('battery_service')
.then(service => service.getCharacteristic('battery_level'))
.then(characteristic => characteristic.readValue())
.then(data => data.getUint8(0));
}
Нам также необходимо обновить объект JavaScript options
, чтобы включить службу батареи в ключ optionalServices
, поскольку она не объявляется Bluetooth-устройством PLAYBULB Candle, но все же обязательна для доступа к ней.
playbulbCandle.js
let options = {filters:[{services:[ CANDLE_SERVICE_UUID ]}],
optionalServices: ['battery_service']};
return navigator.bluetooth.requestDevice(options)
Как и прежде, давайте подключим это к app.js
, вызвав playbulbCandle.getBatteryLevel
, как только мы получим имя устройства и отобразим уровень заряда батареи.
приложение.js
document.querySelector('#connect').addEventListener('click', event => {
playbulbCandle.connect()
.then(() => {
console.log(playbulbCandle.device);
document.querySelector('#state').classList.remove('connecting');
document.querySelector('#state').classList.add('connected');
return playbulbCandle.getDeviceName().then(handleDeviceName)
.then(() => playbulbCandle.getBatteryLevel().then(handleBatteryLevel));
})
.catch(error => {
console.error('Argh!', error);
});
});
function handleDeviceName(deviceName) {
document.querySelector('#deviceName').value = deviceName;
}
function handleBatteryLevel(batteryLevel) {
document.querySelector('#batteryLevel').textContent = batteryLevel + '%';
}
На этом этапе посетите свой сайт в веб-браузере (щелкнув URL-адрес веб-сервера, выделенный в приложении веб-сервера) или просто обновите существующую страницу. Нажмите кнопку «Подключиться» на странице, и вы должны увидеть имя устройства и уровень заряда батареи.
Дальше
- Как я могу изменить цвет этой лампочки? Вот почему я здесь!
- Ты так близко, обещаю...
Часто задаваемые вопросы
6. Измените цвет
Изменить цвет так же просто, как записать определенный набор команд в характеристику Bluetooth ( 0xFFFC
) в основной службе GATT, рекламируемую как 0xFF02
. Например, если ваша свеча PLAYBULB станет красной, это будет означать запись массива 8-битных целых чисел без знака, равных [0x00, 255, 0, 0]
где 0x00
— это насыщенность белого цвета, а 255, 0, 0
— соответственно красного цвета. значения зеленого и синего.
Мы будем characteristic.writeValue
, чтобы фактически записать некоторые данные в характеристику Bluetooth в новом общедоступном методе setColor
класса PlaybulbCandle
. И мы также вернем фактические значения красного, зеленого и синего, когда обещание будет выполнено, чтобы мы могли использовать их в app.js
позже:
playbulbCandle.js
const CANDLE_COLOR_UUID = 0xFFFC;
...
setColor(r, g, b) {
let data = new Uint8Array([0x00, r, g, b]);
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_COLOR_UUID))
.then(characteristic => characteristic.writeValue(data))
.then(() => [r,g,b]);
}
Давайте обновим функцию changeColor
в app.js
, чтобы она вызывала playbulbCandle.setColor
, когда установлен переключатель «Нет эффекта». Глобальные переменные цвета r, g, b
уже установлены, когда пользователь щелкает холст палитры цветов.
приложение.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
if (effect === 'noEffect') {
playbulbCandle.setColor(r, g, b).then(onColorChanged);
}
}
На этом этапе посетите свой сайт в веб-браузере (щелкнув URL-адрес веб-сервера, выделенный в приложении веб-сервера) или просто обновите существующую страницу. Нажмите кнопку «Подключиться» на странице и щелкните палитру цветов, чтобы изменить цвет вашей свечи PLAYBULB столько раз, сколько захотите.
Эффекты свечей Моара
Если вы уже зажигали свечу раньше, вы знаете, что свет не статичен. К счастью для нас, в основной службе GATT есть еще одна характеристика Bluetooth ( 0xFFFB
), рекламируемая как 0xFF02
, которая позволяет пользователю устанавливать некоторые эффекты свечей.
Например, установить «эффект свечи» можно, написав [0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]
. И вы также можете установить «эффект мигания» с помощью [0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]
.
Добавим методы setCandleEffectColor
и setFlashingColor
в класс PlaybulbCandle
.
playbulbCandle.js
const CANDLE_EFFECT_UUID = 0xFFFB;
...
setCandleEffectColor(r, g, b) {
let data = new Uint8Array([0x00, r, g, b, 0x04, 0x00, 0x01, 0x00]);
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_EFFECT_UUID))
.then(characteristic => characteristic.writeValue(data))
.then(() => [r,g,b]);
}
setFlashingColor(r, g, b) {
let data = new Uint8Array([0x00, r, g, b, 0x00, 0x00, 0x1F, 0x00]);
return this.device.gatt.getPrimaryService(CANDLE_SERVICE_UUID)
.then(service => service.getCharacteristic(CANDLE_EFFECT_UUID))
.then(characteristic => characteristic.writeValue(data))
.then(() => [r,g,b]);
}
И давайте обновим функцию changeColor
в app.js
, чтобы она вызывала playbulbCandle.setCandleEffectColor
, когда установлен переключатель «Эффект свечи», и playbulbCandle.setFlashingColor
, когда установлен переключатель «Мигающий». На этот раз мы воспользуемся switch
, если вас это устраивает.
приложение.js
function changeColor() {
var effect = document.querySelector('[name="effectSwitch"]:checked').id;
switch(effect) {
case 'noEffect':
playbulbCandle.setColor(r, g, b).then(onColorChanged);
break;
case 'candleEffect':
playbulbCandle.setCandleEffectColor(r, g, b).then(onColorChanged);
break;
case 'flashing':
playbulbCandle.setFlashingColor(r, g, b).then(onColorChanged);
break;
}
}
На этом этапе посетите свой сайт в веб-браузере (щелкнув URL-адрес веб-сервера, выделенный в приложении веб-сервера) или просто обновите существующую страницу. Нажмите кнопку «Подключиться» на странице и поиграйте с эффектами свечи и мигания.
Дальше
- Вот и все? 3 плохих эффекта свечей? Вот почему я здесь?
- Есть еще, но на этот раз ты будешь один.
7. Сделайте все возможное
Итак, мы здесь! Вы можете подумать, что это почти конец, но приложение еще не закончено. Давайте посмотрим, действительно ли вы поняли, что скопировали во время этой лабораторной работы. Вот что вы хотите сделать сами сейчас, чтобы это приложение засияло.
Добавить недостающие эффекты
Вот данные по недостающим эффектам:
- Пульс:
[0x00, r, g, b, 0x01, 0x00, 0x09, 0x00]
(возможно, вы захотите настроить там значенияr, g, b
) - Радуга:
[0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00]
(Люди с эпилепсией могут избегать этого) - Затухание радуги:
[0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x26, 0x00]
По сути, это означает добавление новых методов setPulseColor
, setRainbow
и setRainbowFade
в класс PlaybulbCandle
и вызов их в changeColor
.
Исправление «нет эффекта»
Как вы, возможно, заметили, опция «без эффекта» не сбрасывает текущий эффект, это незначительно, но все же. Давайте это исправим. В методе setColor
вам нужно сначала проверить, выполняется ли эффект с помощью новой переменной класса _isEffectSet
, и если true
, отключить эффект, прежде чем устанавливать новый цвет с помощью этих данных: [0x00, r, g, b, 0x05, 0x00, 0x01, 0x00]
.
Напишите имя устройства
Это легко! Написать собственное имя устройства так же просто, как записать предыдущую характеристику имени устройства Bluetooth. Я бы рекомендовал использовать метод encode
TextEncoder
, чтобы получить Uint8Array
содержащий имя устройства.
Затем я бы добавил «входной» eventListener
к document.querySelector('#deviceName')
и вызвал playbulbCandle.setDeviceName
, чтобы упростить задачу.
Я лично назвал свою СВЕЧУ ИГРА💡!
8. Вот и все!
Что вы узнали
- Как взаимодействовать с находящимся поблизости устройством Bluetooth с помощью JavaScript
- Как использовать классы ES2015, функции стрелок, карту и обещания
Следующие шаги
- Узнайте больше о веб-API Bluetooth.
- Просмотрите официальные образцы и демонстрации Web Bluetooth
- Посмотрите на летающего сварливого кота