Espruino:Примеры/Хранение данных в Bangle.js

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

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Хранение данных в Bangle.js[1]

При использовании Bangle.js часто возникает потребность периодически сохранять данные, а затем получать к ним доступ через ПК. В этом руководстве мы расскажем, как это сделать.

Также обратите внимание на более общее руководство по сохранению данных на Espruino.

Кроме того, это руководство рассчитано на тех, кто уже прошёл руководство по созданию приложения.

Здесь мы просто создадим меню, которое даст возможность сохранять в файл текущие GPS-данные, название места и время сохранения данных (например, вы можете пометить расположение каждого найденного дерева, став возле него и выбрав пункт Add Tree).

Примечание

В загрузчике приложений уже есть приложение gpspoilog, то есть вы можете загрузить код ниже и сами, но в принципе в загрузчике приложений он уже есть.

Приложение для смарт-часов

Вот код для этого приложения – большая его часть предназначена для создания меню:

var menuItems = {
  "":{title:"GPS POI Log"},
  " ":{value:"No Fix"},
  "Add Tree" : ()=>addItem("Tree"),
  "Add Gate" : ()=>addItem("Gate"),
  "Add Flower" : ()=>addItem("Flower"),
  "Add Plant" : ()=>addItem("Plant")
};

var menu = E.showMenu(menuItems);
var gps = { fix : 0};
var gpsCount = 0;
// Открываем файл в режиме добавления данных,
// попутно создавая этот файл:
var file = require("Storage").open("gpspoilog.csv","a");

function setStatus(msg) {
  menuItems[" "].value = msg;
  menu.draw();
}

Bangle.on('GPS',function(g) {
  gps = g;
  gpsCount++;
  var msg;
  if (g.fix) {
    msg = g.satellites + " Satellites";
  } else {
    msg = "No Fix";
  }
  setStatus(" "+"-\\|/"[gpsCount&3]);
});


function addItem(name) {
  if (!gps.fix) {
    setStatus("Игнорируем – без фиксации");
    return; // ничего не делаем, потому что нет фиксации позиции 
  }
  // Поля, которые мы хотим добавить в наш CSV-файл:
  var csv = [
    0|getTime(), // время с точностью до секунды
    gps.lat,
    gps.lon,
    gps.alt,
    name
  ];
  // Здесь записываем данные:
  file.write(csv.join(",")+"\n");
  setStatus("Данные записаны");
}

Bangle.loadWidgets();
Bangle.drawWidgets();
Bangle.setGPSPower(1);

Сначала нам нужно открыть файл, что делается с помощью этой строчки:

var file = require("Storage").open("gpspoilog.csv","a");

Это открывает файл в режиме добавления данных ("a"). Если этого файла не существует, он будет создан пустым, но если существует, то далее будет выполнена запись.

И теперь нам надо лишь записать данные в файл в выбранный элемент (Add Tree, Add Gate и т.д.) при помощи file.write():

file.write(csv.join(",")+"\n");

Здесь происходят следующие вещи:

  • csv – это массив, так что мы конвертируем его в строку при помощи функции join(), которая объединяет все элементы вместе, ставя между ними запятые.
  • write() не добавляет символ новой строки, так что мы должны добавить его сами при помощи \n, чтобы в дальнейшем у нас была возможность считывать данные строчка за строчкой.
  • Кроме того, write() на данный момент не умеет сохранять в файлы символьный код 255 ("\xff"), так что нам нужно придерживаться сохранения текста, а не двоичных данных.
  • write() записывает данные сразу в момент своего вызова, т.е. вам не нужно также вызывать close() для закрытия файла и завершения записи.
  • Файл, созданный при помощи require("Storage").open, будет отличаться от файла, созданного при помощи require("Storage").write, поскольку такой файл предназначен только для добавления данных. Таким образом, вы можете получить доступ к такому файлу только при помощи той же require("Storage").open, но не require("Storage").write/read/erase и так далее.

Так, с этим разобрались, теперь мы можем загрузить приложение, запустить его и прочесть какие-нибудь данные:

  • Открываем онлайн-IDE и подключаемся к своим Bangle.js.
  • Кликаем на треугольник под кнопкой загрузки, выбираем Storage > New File и в поле для названия вводим «gpspoilog.app.js».
  • Кликаем на кнопку загрузки, чтобы загрузить приложение.
  • Теперь копируем и вставляем код ниже в левую часть IDE. Это создаст (в обход загрузчика приложения) в лаунчере Bangle.js новое приложение, оснащённое списковым меню.
require("Storage").write("gpspoilog.info",{
  "name":"GPS POI Log",
  "src":"gpspoilog.app.js"
});

Теперь немного прогуляйтесь – когда появится GPS-сигнал, вы сможете начать сохранять данные, выбирая в меню пункты Add Plant, Add Gate и так далее.

Считывание данных

При помощи IDE

Простейший способ чтения данных – это открыть файл в онлайн-IDE. Для многих из вас этого должно быть достаточно:

  • Кликните по кнопке Storage в середине экрана (иконка с 4 дисками)
  • В появившемся окне кликните по иконке с глазом рядом с «gpspoilog.csv (StorageFile)»
  • Теперь вы должны увидеть содержимое файла и можете сохранить его в файл, если хотите.

В приложении

Доступ к данным можно получить с помощью кода – либо считывая данные фрагментами, либо строчка за строчкой.

К примеру, код ниже сохраняет по одной строчке за раз:

var f = require("Storage").open("gpspoilog.csv","r");
var l = f.readLine();
while (l!==undefined) {
  console.log(l);
  l = f.readLine();
}

Считывание при помощи загрузчика приложений

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

Во-первых, нам надо добавить приложение. Делается это точно так же, как описано в этом руководстве, но с одним дополнением – элементом "interface" в JSON-файле.

  • Настройте свой загрузчик приложений как описано тут.
  • Скопируйте папку «apps/_example_app» в «apps/gpspoilog».
  • Сохраните JS-файл сверху «apps/gpspoilog/app.js».
  • Удалите «apps/gpspoilog/add_to_apps.json».
  • Добавьте код ниже в конец «apps.json» в корневой директории (без комментариев «исходная строчка»), но обязательно поставьте запятую в конец предыдущего элемента JSON-файла как показано ниже:
  }, //<--- исходная строчка – поставьте здесь запятую
  { "id": "gpspoilog",
    "name": "GPS POI Logger",
    "shortName":"GPS POI Log",
    "icon": "app.png",
    "version":"0.01",
    "description": "Метод записи точек интереса вместе с их GPS-координатами",
    "tags": "outdoors",
    "interface": "interface.html",
    "storage": [
      {"name":"gpspoilog.app.js","url":"app.js"},
      {"name":"gpspoilog.img","url":"app-icon.js","evaluate":true}
    ]
  }
] //<--- исходная строчка

Теперь надо добавить «интерфейсный» файл – скопируйте код ниже в «apps/gpspoilog/interface.html».

<html>
  <head>
    <link rel="stylesheet" href="../../css/spectre.min.css">
  </head>
  <body>
    <div id="data"></div>
    <button class="btn btn-default" id="btnSave">Save</button>
    <button class="btn btn-default" id="btnDelete">Delete</button>

    <script src="../../core/lib/interface.js"></script>
    <script>
var dataElement = document.getElementById("data");
var csvData = "";

function getData() {
  // Показываем окно загрузки:
  Util.showModal("Загрузка...");
  // Считываем данные:
  dataElement.innerHTML = "";
  Util.readStorageFile(`gpspoilog.csv`,data=>{
    csvData = data.trim();
    // Удаляем окно:
    Util.hideModal();
    // Если данных нет, сообщаем об этом и выходим:
    if (data.length==0) {
      dataElement.innerHTML = "<b>Данные не найдены</b>";
      return;
    }
    // В противном случае парсим данные и выводим их в виде таблицы:
    dataElement.innerHTML = `<table>
    <tr>
      <th>Time</th>
      <th>Lat</th>
      <th>Lon</th>
      <th>Alt</th>
      <th>Type</th>
    </tr>`+data.trim().split("\n").map(l=>{
      l = l.split(",");
      return `<tr>
      <td>${(new Date(l[0]*1000)).toLocaleString()}</td>
      <td>${l[1]}</td>
      <td>${l[2]}</td>
      <td>${l[3]}</td>
      <td>${l[4]}</td>
      </tr>`
    }).join("\n")+"</table>";
  });
}

// Можем вызвать вспомогательную функцию для сохранения данных:
document.getElementById("btnSave").addEventListener("click", function() {
  Util.saveCSV("gpsdata", csvData);
});
// Или также можем удалить файл:
document.getElementById("btnDelete").addEventListener("click", function() {
  Util.showModal("Удаление...");
  Util.eraseStorageFile("gpspoilog.csv", function() {
    Util.hideModal();
    getData();
  });
});
// Вызывается при запуске приложения:
function onInit() {
  getData();
}

    </script>
  </body>
</html>

Этот код делает ряд базовых действий:

  • onInit() вызывается при загрузке страницы.
  • getData() извлекает данные из часов.
  • Util.showModal() показывает окно состояния, когда происходят какие-то важные вещи.
  • Util.readStorageFile() считывает файл из Storage с Bangle.js и возвращает строку, содержащую содержимое этого файла.
  • Util.saveCSV() показывает диалог с запросом сохранения.
  • Util.eraseStorageFile() стирает файл.

Более подробную информацию о доступных функциях можно посмотреть в файле «interface.js».

Чтобы воспользоваться новым интерфейсным HTML-файлом:

  • Зайдите на свою страницу загрузчика приложений.
  • Кликните на Connect справа вверху.
  • Кликните на My Apps.
  • Рядом с GPS POI Logger будет иконка с направленной вниз стрелочкой. Кликните на неё.
  • Это откроет GPS POI Logger, который покажет записанные вами данные.
  • Теперь вы можете сохранить эти данные или удалить их с Bangle.js.

Вот и всё! Когда приложение будет работать как надо, вы даже можете предложить его для внесения в официальный загрузчик приложений.

См.также

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