La fel ca în laboratorul trecut, target-ul cu care vom lucru este un produs Fitbit, și anume Fitbit Versa 3 sau Fitbit Sense. Vom utiliza Fitbit Software Development Kit (SDK) pentru a dezvolta o aplicație (app) în acest laborator, folosind 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/.
O aplicație este de obicei un program specializat cu un scop clar (e.g. aplicație de exerciții fitness, aplicație de alarme/timere etc.), spre deosebire de o față de ceas care afișează în principiu ora și câteva statistici pentru ca utilizatorul să fie informat rapid când folosește smartwatch-ul.
Setup-ul este același ca în laboratorul trecut (laboratorul 1).
Mai exact, pentru a putea folosi infrastructura pusă la dispoziție de către Fitbit va trebui să urmați pașii:
Trebuie să folosiți versiunea 6.0 a SDK-ului.
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).
0. Ne propunem să creăm o aplicație cu luminițe (cea din GIF-ul de mai jos). Aplicația va avea trei butoane care pornesc/opresc un mic spectacol de lumini. Pentru aceasta creați un nou proiect în Fitbit Studio și alegeți template-ul Minimal. Descărcați template-ul pentru laborator și aplicați-l în cadrul proiectului. Asigurați-vă că în package.json
aveți setat tipul proiectului ca aplicație (Type → App). Deocamdată app/index.js
este gol, iar proiectul nu va fi buildat cu succes.
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ă.
1. Deocamdată app/index.js
este gol, iar proiectul nu va fi buildat cu succes. Pentru acest exercițiu ne propunem să avem referințe către toate elementele din index.view
și variabile pentru a putea manipula mai ușor starea luminițelor.
import document from "document"; // Get all lights references by the ID defined in index.view const lights = [ document.getElementById("bot1"), document.getElementById("bot2"), document.getElementById("bot3"), document.getElementById("bot4"), document.getElementById("bot5"), document.getElementById("bot6"), document.getElementById("bot7"), document.getElementById("bot8"), document.getElementById("bot9"), document.getElementById("bot10"), document.getElementById("bot11"), document.getElementById("bot12"), document.getElementById("bot13"), document.getElementById("bot14"), document.getElementById("bot15"), document.getElementById("bot16"), document.getElementById("bot17"), document.getElementById("bot18"), document.getElementById("bot19"), document.getElementById("bot20"), ];
const blinkLightsButton = document.getElementById("button1"); const slideLightsButton = document.getElementById("button2"); const customLightsButton = document.getElementById("button3");
// Colors for each light turned on const lightOnColor = [ "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", "#FFA500", ]; // Colors for each light turned off const lightOffColor = [ "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", "#FAF5EF", ];
const lightsOn = [ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ];
2. Pentru a putea face tranziția între jocurile de lumini avem nevoie de posibilitatea de a le stinge pe toate întâi.
function turnOffLights() { let i; for (i = 0; i < lights.length; i++) { lightsOn[i] = false; lights[i].style.fill = lightOffColor[i]; } }
turnOffLights();
3. Creați primul joc de lumini astfel încât atunci când apăsați primul buton toate luminițele să se aprindă și să se stingă la un interval de timp definit de voi (e.g. 200 ms). Toate butoanele trebuie să implementeze stingerea jocului de lumini deja activ pentru a nu se influența două jocuri de lumini între ele.
// We will recycle the same event handler let intervalHandler = -1; let rows = rows = lights.length / 2; // First button event blinkLightsButton.addEventListener("click", (evt) => { if (intervalHandler == -1) { intervalHandler = setInterval(blinkLights, 200); } else { // Turn off event and cleanup clearInterval(intervalHandler); intervalHandler = -1; turnOffLights(); } });
function blinkLights() { let i; for (i = 0; i < lights.length; i++) { if (lightsOn[i]) { lights[i].style.fill = lightOffColor[i]; } else { lights[i].style.fill = lightOnColor[i]; } lightsOn[i] = !lightsOn[i]; } }
4. Creați al doilea joc de lumini astfel încât atunci când apăsați al doilea buton să se aprindă o singură lumină, restul fiind stinse. La un interval de timp definit de voi (e.g. 200 ms) să se aprindă următoarea lumină, iar cea anterioară să se stingă. Toate butoanele trebuie să implementeze stingerea jocului de lumini deja activ pentru a nu se influența două jocuri de lumini între ele.
let currentLight; // keep track of the current lights for the slide show slideLightsButton.addEventListener("click", (evt) => { if (intervalHandler == -1) { currentLight = 0; lights[currentLight].style.fill = lightOnColor[currentLight]; lightsOn[currentLight] = true; intervalHandler = setInterval(slideLights, 200); } else { // Turn off event and cleanup clearInterval(intervalHandler); intervalHandler = -1; turnOffLights(); } });
function slideLights() { lights[currentLight].style.fill = lightOffColor[currentLight]; lightsOn[currentLight] = false; currentLight = (currentLight + 1) % lights.length; lights[currentLight].style.fill = lightOnColor[currentLight]; lightsOn[currentLight] = true; }
5. Creați al treilea joc de lumini după cum doriți voi. Puteți urma ca exemplu celălalte jocuri de lumini. Toate butoanele trebuie să implementeze stingerea jocului de lumini deja activ pentru a nu se influența două jocuri de lumini între ele.
customLightsButton.addEventListener("click", (evt) => { if (intervalHandler == -1) { intervalHandler = setInterval(customLights, 1000); // adjust the interval timer } else { // Turn off event and cleanup clearInterval(intervalHandler); intervalHandler = -1; turnOffLights(); } });
function customLights() { // TODO complete here console.log("custom lights show"); }
[BONUS]6. Folosiți diferite culori pentru lumini.
[BONUS]7. Înlocuiți imaginea de background cu o alta la alegerea voastra. Asigurați-vă că aceasta este tot un fișier cu extensia .png/.jpg și dimensiune maxim 336 x 336 pentru Fitbit Sense. Puteți muta poziția luminilor din fișierul index.view
. Distracție placuta!