Laboratorul 01. Fitbit SDK - Clock Face

Bine ați venit în laboratorul de Sisteme Embedded!

Laboratorul își propune să vă familiarizeze cu sisteme embedded care rulează Linux, și sisteme de operare RTOS precum cel folosit pe produsele Fitbit, și anume Fitbit Versa 3 sau Fitbit Sense.

În cadrul acestui laborator vom dezvolta o față de ceas (clock face) și în laboratorul următor o aplicație (app) pentru ceas, folosind Fitbit Software Development Kit (SDK), mediul de dezvoltare pus la dispoziție de către Fitbit (Fitbit Studio) și simulatorul (Fitbit OS Simulator). Documentația pentru dezvoltatorii de aplicații Fitbit se poate găsi pe https://dev.fitbit.com/.

Setup

Vă recomandăm să folosiți Windows sau macOS pentru aceste laboratoare!

Setup-ul oficial poate fi găsit aici la secțiunea What You’ll Need.

Mai exact, pentru a putea folosi infrastructura pusă la dispoziție de către Fitbit va trebui să urmați pașii:

  1. Creați-vă un cont Fitbit accesând acest link.
  2. Descărcați simulatorul (Fitbit OS Simulator) pentru Windows sau macOS. Nu există support pentru Linux, dar există workarounds pentru acest lucru în cazul în care doriți să utilizați Linux la aceste laboratoare (urmați pașii de aici pentru a rula simulatorul pe Linux).
  3. Accesați Fitbit Studio, mediul de dezvoltare online pus la dispoziție pentru developeri.

Conectați-vă atât la Fitbit Studio, cât și la simulator cu același cont Fitbit creat mai sus!

Dacă Fitbit Studio nu vede simulatorul (pe Windows), încercați cu aceasta versiune de simulator.

Arhitectura unei aplicații folosind Fitbit SDK

Informațiile următoare se regăsesc în documentația oficială: https://dev.fitbit.com/build/guides/application/

O aplicație tipică are următoarea structură de directoare:

  • /app/ - directorul conține logica aplicației care urmează a fi executată pe device. Un fișier index.js trebuie să existe în acest director, altfel operația de build va eșua.
  • /companion/ - director opțional ce conține logica companion-ului care este executată pe device-ul mobil (capabil să facă request-uri către Internet și să comunice cu aplicația). Dacă există un fișier index.js atunci componenta companion se va builda.
  • /common/ - director opțional ce conține fișiere care pot fi folosite atât de aplicație, cât și de companion.
  • /settings/ - director opțional ce conține informații despre setările aplicației.
  • /resources/ - directorul conține toate resursele care sunt folosite de aplicație.
  • package.json - fișierul de configurare al aplicației.

Tipurile de resurse din directorul /resources/ sunt:

  • /resources/index.view - fișier obligatoriu, aici este definită interfața cu utilizatorul (fișier SVG).
  • /resources/widget.defs - fișier obligatoriu, acesta controlează ce widget-uri de sistem sunt disponibile pentru a fi folosite în index.view.
  • /resources/*.css - fișiere CSS care pot schimba aspectul elementelor din index.view.
  • /resources/*.png și /resources/*.jpg - imagini ce pot fi folosite în index.view folosind tag-ul <image>.

Exerciții

În cadrul simulatorului setați Versa 3 sau Sense ca de tip device (Settings → Device Type).

Trebuie să folosiți versiunea 6.0 a SDK-ului.

Dacă Fitbit Studio nu se conectează la simulator, iar în simulator (la Settings) apare eroarea “Device bridge is disconnected”, trebuie să actualizați certificatul simulatorului. Soluția se găsește în discuția de aici. Folderul este numit atlas pentru Versa 3 și vulcan pentru Sense.

* Pe Mac OS folderul este /Applications/Fitbit OS Simulator.app/Contents/Resources/static/devicesim/mac/vulcan.app/Contents/Resources (pentru Sense).

* Pe Windows folderul este C:\Users\YourUser\AppData\Local\Programs\@fitbitsimulator\resources\static\devicesim\win\atlas

0. Urmați primii 3 pași de la secțiunea Create Your First Project (Setup, Create a New Project, Installing) de pe https://dev.fitbit.com/getting-started/. În urma acestui exercițiu ar trebui să apară aceeași față de ceas (clock face) în simulator ca cea din ghid.

1. Ne propunem să creăm o nouă față de ceas (cea din GIF-ul de mai jos). Pentru aceasta o puteți edita pe cea de la exercițiul anterior sau să creați un nou proiect și să alegeți ca template tot Digital Clock. Descărcați template-ul pentru laborator de aici și aplicați-l în cadrul proiectului. Rulați aplicația în simulator.

Exercițiile din laborator se rezolvă în fișierul app/index.js. Template-ul conține comentarii de tip TODO pentru fiecare subpunct al exercițiilor. Vom utiliza doar Device APIs, documentația lor se află aici. Limbajul de programare utilizat este Javascript, dar ne vom limita la funcționalitățile de bază.

2. Deocamdată fața de ceas indică doar ora, dar nu și statisticile afișate in cele 4 cadrane. Pentru acest exercițiu ne propunem să selectăm prima opțiune (pașii).

  1. obțineți restul elementelor de UI (hr, floors, battery) și apoi adăugați acele variabile într-un array.
    const arcHR = document.getElementById("hr");
    const arcFloors = document.getElementById("floors");
    const arcBattery = document.getElementById("battery");
    const arcs = [arcSteps, arcHR, arcFloors, arcBattery];
  2. creați un array pentru culorile celor 4 cadrane.
    const arcColors = ["darkturquoise", "fb-red", "orange", "limegreen"];
  3. completați funcția initializeStat() astfel incât să seteze ca opțiunea cu pași să fie cea selectată inițial (la start-up), funcția nu trebuie să întoarcă nimic. Trebuie să setați culoarea cadranului și a label-ului, dar și textul label-ului (statLabel). Inițializați variabila currStat care va stoca opțiunea curentă.
    function initializeStat() {
      currStat = 0;
      arcs[0].style.fill = arcColors[0];
      statLabel.text = "Steps";
      statLabel.style.fill = arcColors[0];
    }

Explicații:

  • În Javascript, o constantă se definește astfel const my_const = 0.
  • În Javascript, o variabilă se definește astfel let my_var = 0.
  • În Javascript, un array se definește astfel const cars = [“Volvo”, “BMW”, “Dacia”, “Skoda”].
  • Pentru a obține un element UI putem folosi document.getElementById(<id>) din Document API, <id> fiind id-ul definit deja în /resources/index.view.
  • Puteți alege orice culori doriți de aici. Cele utilizate în exemplu sunt “darkturquoise”, “fb-red”, “orange”, “limegreen”.
  • Pentru a seta culoarea unui element x se poate folosi x.style.fill = “red”.
  • Pentru a seta textul unui element text x se poate folosi x.text = “Steps”.

3. Ne dorim ca fața de ceas să itereze prin cele 4 cadrane la apăsarea ecranului (click pe ecran în simulator). Funcția care a fost setată să se apeleze la un eveniment de click/tap este funcția changeStat(). Completați-o astfel încât la fiecare apel să se selecteze următoarea opțiune (setând culoarea, textul îl vom seta la următorul exercițiu). Înainte de a seta noua opțiune asigurați-vă că ați deselectat-o pe cea anterioară (setați-i culoarea alb).

function changeStat() {
  arcs[currStat].style.fill = "white";
  currStat = (currStat + 1) % 4;
 
  arcs[currStat].style.fill = arcColors[currStat];
 
  statLabel.style.fill = arcColors[currStat];
 
  // this will change the stat label, don't remove
  fillInStatLabel();
}

4. Pentru ca fața de ceas să fie completă, trebuie să îi adăugăm și datele pentru fiecare opțiune selectată. Completați funcția fillInStatLabel() astfel încât la fiecare apel să se seteze text-ul afișat din variabila statLabel în funcție de opțiunea curentă. Va trebui să includeți și să apelați API-urile pentru user-activity (pași, floors), heart-rate (hr) și power (baterie) pentru a obține datele.

  1. Importați API-urile de care avem nevoie pentru extragerea informațiilor din fiecare opțiune a cadranelor.
    import { HeartRateSensor } from "heart-rate";
    import { battery } from "power";
    import { today } from "user-activity";

    Modificați apoi în funcția initializeStat() textul de afișare a pașilor.

    function initializeStat() {
      currStat = 0;
      arcs[0].style.fill = arcColors[0];
      statLabel.text = `${statNames[0]}: ${today.adjusted.steps}`; // this has been changed
      statLabel.style.fill = arcColors[0];
    }
  2. Completați funcția fillInStatLabel() astfel încât la fiecare apel să se seteze text-ul afișat din variabila statLabel în funcție de opțiunea curentă.
    function fillInStatLabel() {
      switch(currStat) {
        case 0: // Steps
          statLabel.text = `${statNames[currStat]}: ${today.adjusted.steps}`;
          break;
        case 1: // HR
          if (HeartRateSensor && !hrm) {
            hrm = new HeartRateSensor({ frequency: 1 });
            hrm.start();
          }
     
          const hrmStr = hrm.heartRate == null ? '--' : `${hrm.heartRate}`;
          statLabel.text = `${statNames[currStat]}: ${hrmStr}`;
     
          break;
        case 2: // Floors
          statLabel.text = `${statNames[currStat]}: ${today.adjusted.elevationGain}`;
          break;
        case 3: // Battery
          statLabel.text = `${statNames[currStat]}: ${Math.floor(battery.chargeLevel)}%`;
          break;
      }
    }
  3. In package.json selectati permisiunile pentru Activity si Heart Rate.

Eplicații:

Resurse

si/lab/2022/laboratoare/01.txt · Last modified: 2023/09/26 14:15 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0