Espruino:Примеры/Создание панели управления при помощи Web Bluetooth

Материал из Онлайн справочника
Перейти к навигации Перейти к поиску

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Создание панели управления при помощи Web Bluetooth[1]

Иногда требуется создать веб-страницу с кнопками, графиками и индикаторами, позволяющую быстро мониторить и управлять различными встраиваемыми устройствами. В этом руководстве мы расскажем, как создать веб-страницу, похожую на эту:

Web Bluetooth Dashboard.png

Во-первых, советуем ознакомиться с руководством по Web Bluetooth – в нём рассказывается, как разрабатывать веб-страницы с поддержкой Web Bluetooth.

Мы воспользуемся TinyDash – очень простой библиотекой для HTML-панелей управления, которой требуется всего несколько файлов.

Инструкции по настройке собственной HTTPS-страницы смотрите в руководстве по Web Bluetooth, а затем вставьте в неё следующее:

<html>
 <head>
  <title>Dashboard</title>
  <meta name="viewport" content="width=620, initial-scale=1">
 </head>
 <body style="width:620px;height:450px">
  <link href="https://espruino.github.io/TinyDash/tinydash.css" rel="stylesheet">
  <script src="https://espruino.github.io/TinyDash/tinydash.js"></script>
  <script src="https://www.puck-js.com/puck.js"></script>  
  <script>
  var elements = {
    heading : TD.label({x:10,y:10,width:190,height:50,label:"My Dashboard"})
  }
  for (var i in elements)
    document.body.appendChild(elements[i]);
  </script>
 </body>
</html>

Это минимум для создания панели управления. Хорошо, но делает этот код?

  • В теге <meta> задаётся, что на устройствах вроде смартфонов и планшетов страница будет рендериться с шириной в 640 пикселей. Позднее, определившись с шириной панели управления, вы сможете сами настроить этот показатель как вам угодно.
  • В строчках с тегами <link> и <script> добавляется то, что понадобится нам для панели управления и управления Puck.js.
  • Фрагмент с многострочным <script> содержит код для элементов нашей панели управления. Мы привяжем все наши элементы к elements, чтобы нам было проще на них ссылаться – но делать это необязательно.
  • Функция TD.label() создаёт элемент с надписью. Аргументы x, y, width и height в ней задаются в пикселях. О других типах компонентов, которые можно добавить в панель управления, можно узнать тут.

Панель управления без режима реального времени

Для начала давайте создадим панель управления, которая после подключения будет показывать накопленные данные Puck.js.

Во-первых, показываем данные. Загрузите код ниже на Puck.js при помощи онлайн-IDE:

// Наши накопленные данные:
var history = new Int16Array(100);

// Считываем данные и сохраняем их в RAM-память:
function logData() {
  var data = E.getTemperature();
  for (var i=0;i<history.length-1;i++)
    history[i] = history[i+1];
  history[history.length-1] = data*100;
}

// Начинаем запись:
setInterval(logData, 1000);

Этот код каждую секунду записывает в переменную history новое температурное значение.

Теперь отключитесь и обновите страницу Web Bluetooth при помощи кода ниже (или можете просто кликнуть на кнопку «Попробуй!», находящуюся под кодом):

<html>
 <head>
  <title>Dashboard</title>
  <meta name="viewport" content="width=620, initial-scale=1">
 </head>
 <body style="width:620px;height:450px">
  <link href="https://espruino.github.io/TinyDash/tinydash.css" rel="stylesheet">
  <script src="https://espruino.github.io/TinyDash/tinydash.js"></script>
  <script src="https://www.puck-js.com/puck.js"></script>  
  <script>
  function connectDevice() {
    // Подключаемся и запрашиваем процент заряда батареи:
    Puck.eval("{bat:Puck.getBatteryPercentage()}", function(d,err) {
      if (!d) {
        alert("Подключиться через Web Bluetooth не получилось!\n"+(err||""));
        return;
      }
      // Удаляем окно подключения:
      elements.modal.remove();
      // Обновляем элементы панели управления
      // согласно полученным значениям: 
      elements.bat.setValue(d.bat);
      // Теперь считываем «history».
      // Это должно занять какое-то время, 
      // так что делаем это отдельно.
      Puck.eval("history", function(d) {
        elements.temp.setData(d);
      });
    });
  }
  // Настраиваем элементы панели управления,
  // которые видим на экране:
  var elements = {
    heading : TD.label({x:10,y:10,width:190,height:50,label:"My Dashboard"}),
    bat : TD.gauge({x:10,y:70,width:190,height:220,label:"Battery Level",value:0,min:0,max:100}),
    temp : TD.graph({x:210,y:10,width:400,height:180,label:"Temperature"}),
    redled : TD.toggle({x:210,y:200,width:200,height:90,label:"Red LED",value:0,onchange:function(el,v) {
      Puck.write("LED1.write("+v+");\n");
    }}),
    flash : TD.button({x:420,y:200,width:190,height:90,label:"Flash!",onchange:function(){
      Puck.write("digitalPulse(LED3,1,500);\n");
    }}),
    modal: TD.modal({x:10,y:10,width:600,height:430,label:"Click to connect",onchange:connectDevice})
  }
  for (var i in elements)
    document.body.appendChild(elements[i]);
  </script>
 </body>
</html>

Итак, как это всё работает?

  • Сначала мы задаём все компоненты панели управления, которые в дальнейшем будут помещены в elements.
  • В конце добавляем функцию TD.modal(). Она затрагивает все компоненты и после клика вызывает connectDevice() для инициализации соединения Web Bluetooth (в целях безопасности автоматическое подключение в Web Bluetooth настроить нельзя).
  • После установления соединения используем Puck.eval(), чтобы запросить процент заряда батареи, а затем в отдельном запросе считываем всё содержимое массива history.
  • Наконец, клик на компонент «Red LED» или «Flash» запускает функцию onchange(), которая вызывает функцию Puck.write() для выполнения действия, соответствующего нажатому компоненту.

Панель управления, работающая в режиме реального времени

Чтобы получать от Puck.js обновления в реальном времени, мы можем многократно вызывать Puck.eval(), чтобы прочесть нужную нам информацию, но это будет довольно медленно.

Вместо этого мы воспользуемся примером по созданию двухсторонней коммуникации из руководства по Web Bluetooth. Мы воспользуемся функцией Puck.connect(), которая создаст двустороннее соединение, функцией setInterval() на Puck.js, с помощью которой будем отправлять данные с регулярными интервалами, а также функцией-обработчиком onLine(), с помощью которой будем считывать эти данные.

Для примера мы возьмём ту же функцию Puck.light(), с помощью которой будем считывать световые значения в реальном времени, но мы также снабдили этот код выводом JSON-данных, чтобы при необходимости передавать больше данных за раз.

<html>
 <head>
  <title>Dashboard</title>
  <meta name="viewport" content="width=210, initial-scale=1">
 </head>
 <body style="width:210px;height:450px">
  <link href="https://espruino.github.io/TinyDash/tinydash.css" rel="stylesheet">
  <script src="https://espruino.github.io/TinyDash/tinydash.js"></script>
  <script src="https://www.puck-js.com/puck.js"></script>  
  <script>
  // Вызывается, когда мы считываем строчку данных,
  // и обновляет цвет лампочки:
  function onLine(line) {
    try {
      var j = JSON.parse(line);
      console.log("Присланные JSON-данные: ",j);
      elements.light.setValue(j.light*100);
    } catch(e) {
      console.log("Присланные данные: ",line);
    }
  }
  var connection;
  function connectDevice() {
    Puck.connect(function(c) {
      if (!c) {
        alert("Подключиться не удалось!");
        return;
      }
      connection = c;
      // Удаляем окно подключения:
      elements.modal.remove();
      // Обрабатываем данные, получаемые в ответ,
      // и вызываем onLine() при каждом получении строчки:
      var buf = "";
      connection.on("data", function(d) {
        buf += d;
        var i = buf.indexOf("\n");
        while (i>=0) {
          onLine(buf.substr(0,i));
          buf = buf.substr(i+1);
          i = buf.indexOf("\n");
        }
      });
      // Во-первых, выполняем сброс Puck.js:
      connection.write("reset();\n", function() {
        // Ждём, пока Puck.js выполнит сброс самого себя:
        setTimeout(function() {
          // Теперь делаем, чтобы Puck.js 10 раз в секунду
          // передавала через Bluetooth значение яркости.
          // Кроме того, после отключения выполняем сброс Puck.js, 
          // чтобы setInterval() не расходовала заряд батареи.      
connection.write("setInterval(function(){Bluetooth.println(JSON.stringify({light:Puck.light()}));},100);NRF.on('disconnect', function() {reset()});\n",
            function() { console.log("Готово..."); });
          }, 1500);
        });
      });

  }
  // Настраиваем средства управления, которые видим на экране: 
  var elements = {
    heading : TD.label({x:10,y:10,width:190,height:50,label:"My Dashboard"}),
    light : TD.gauge({x:10,y:70,width:190,height:220,label:"Light",value:0,min:0,max:100}),
    modal: TD.modal({x:10,y:10,width:190,height:430,label:"Click to connect",onchange:connectDevice})
  }
  for (var i in elements)
    document.body.appendChild(elements[i]);
  </script>
 </body>
</html>

Опять же, вы можете кликнуть на кнопку «Попробуй!», чтобы попробовать этот код – для этого не нужно предварительно загружать в Puck.js какую-либо информацию.

См.также

Ссылки на полезные ресурсы

Внешние ссылки