Transcript

SVEUČILIŠTE U ZAGREBUFAKULTET ELEKTROTEHNIKE I RAČUNARSTVA

ZAVRŠNI RAD br. 2784

SenseGrid: Aplikacija za suradnoopažanje okoline putem uređaja s

operativnim sustavom AndroidSandro Gržičić

Zagreb, lipanj 2012.

iii

Sadržaj

1. Uvod 1

2. Android 22.1. Operativni sustav za prijenosne uređaje . . . . . . . . . . . . . . . 2

3. Scala 33.1. Programski jezik modernog programera . . . . . . . . . . . . . . . 33.2. HelloWorld . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43.3. Osnovne karakteristike . . . . . . . . . . . . . . . . . . . . . . . . 53.4. Funkcijski aspekti . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.5. Kolekcije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.6. Ostale mogućnosti . . . . . . . . . . . . . . . . . . . . . . . . . . 103.7. Vanjske biblioteke . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3.7.1. Unfiltered . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.7.2. SBT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3.8. Scala na Androidu . . . . . . . . . . . . . . . . . . . . . . . . . . 123.9. Protocol Buffers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.9.1. Implementacija u Scali: ScalaBuff . . . . . . . . . . . . . . 14

4. SenseGrid 164.1. Android klijent . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4.1.1. Senzori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164.2. Poslužitelj . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174.3. Mrežna komunikacija . . . . . . . . . . . . . . . . . . . . . . . . . 174.4. Upotreba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

5. Zaključak 19

Literatura 20

iv

A. Pokretanje SenseGrida 21

v

1. Uvod

Meteorološke postaje sadrže instrumente koji precizno i točno bilježe atmosferskeuvjete; međutim, takvih postaja postoji ograničen broj. Alternativa je koristitibrojne mobilne uređaje s operativnim sustavom Android čiji broj daleko nad-mašuje broj fiksnih meteoroloških postaja. Gotovo svaki takav mobilni uređajposjeduje velik broj različitih senzora, od kojih je određen broj koristan za opa-žanje okoline.

SenseGrid je projekt koji omogućava korištenje takvih senzora radi surad-ničkog opažavanja okoline: sastoji se od klijentske aplikacije za mobilne uređajes operativnim sustavom Android koja šalje poslužitelju podatke sa senzora i pri-kazuje dobivene podatke sa poslužitelja na intuitivnoj karti, te poslužitelja kojidobivene podatke skuplja i predaje klijentima.

Android platforma veoma je fleksibilna, te za pisanje aplikacija podržava je-zike koji se izvršavaju na Javinoj virtualnoj mašini (Java VM ), što (uz Javu)uključuje programski jezik Scalu. U radu će biti objašnjene osnove rada opera-tivnog sustava Android, ukratko će se objasniti programski jezik Scala zajedno skratkim opisom korištenih biblioteka te će biti opisana sâma aplikacija i posluži-telj.

1

2. Android

Prepoznavajući potrebu za univerzalnim operativnim sustavom za mobilne ure-đaje, tvrtka Google je odlučila napraviti takav sustav. Vlasnici tvrtke su pri-mjetili rad startup tvrtke Android Inc. na takvoj platformi 2005. godine, te jenakon kupnje startupa Google ubrzano nastavio razvoj na operativnom sustavuAndroid. Dvije godine kasnije je napravljen Open Handset Alliance, konzor-cij velikog broja tvrtki s ciljem napredovanja mobilnih platforma preko razvojaotvorenih standarda. U isto je vrijeme konzorcij predstavio javnosti prvu verzijusustava Android. Google je također predstavio Android Open Source Project,otvoreni projekt čiji je cilj poboljšavanje i nadograđivanje otvorenog operativnogsustava Android.

2.1. Operativni sustav za prijenosne uređaje

Android je operativni sustav primarno namijenjen prijenosnim (mobilnim) ure-đajima, u koje spadaju pametni mobiteli (smartphone) i tableti (mala prijenosnaračunala). Početne verzije su se izvršavale na uređajima koji nisu bili jako razli-čiti od običnih mobitela, no uskoro počinju izlaziti napredniji i prikladniji modelipametnih mobitela. Verzija 2 i njezine podverzije donose brojna poboljšanja temoderniziraju sustav. Verzija 3 je napravljena radi podrške za veće ekrane kojise nalaze na tabletima, a verzija 4 unificira verzije 2 i 3, kako bi postojala jednaverzija za sve prijenosne uređaje, te dakako nosi brojne nove mogućnosti i po-boljšanja.1

1Detaljnije o verzijama: http://en.wikipedia.org/wiki/Android_version_history

2

3. Scala

3.1. Programski jezik modernog programera

Neki se programski jezici danas primarno koriste za pisanje velikih poslovnihaplikacija. S druge strane, neki se uglavnom koriste za pisanje kraćih “skripti”- malih programa koji automatiziraju izvođenje radnji koje bi inače morale bitiizvedene ručno.

Programski jezici koji su više omiljeni kod programera obično imaju dinamičkitipski sustav (dynamic typing), tj. provjera tipova se izvodi prilikom izvođenjaprograma, što je gotovo uvijek sporije od statičkog tipskog sustava (static typing).Ipak, većina jezika sa statičkim tipskim sustavom zahtijeva od programera punoviše napisanog kôda u usporedbi s programskim jezikom s dinamičkim tipskimsustavom. Bez obzira na “sirovu” brzinu izvođenja, dinamički jezici obično nisutoliko skalabilni kao statički1.

Funkcijski jezici su programski jezici u u kojima programer piše slijed matema-tičkih izračuna, bez podrške za promjenjivim stanjem i promjenjivim podacima.Takvi su jezici najviše rašireni u akademskoj zajednici, no u zadnje vrijeme su svepopularniji i među širom programerskom zajednicom. Takvi jezici obično nemajupodršku za koncepte zastupljene u oblikovno orijentiranom programiranju, poputklasa, metoda, nasljeđivanja ili nadjačavanja (overloading). Korištenje takvih je-zika je obično veoma zahtjevno za programere naučene na raširenije proceduralneili objektno orijentirane jezike.

Scala je programski jezik koji kombinira najbolje karakteristike svih kategorijajezika: ima snažan statički tipski sustav, no ne zahtijeva definiranje tipa svakevarijable radi type inferencinga, tj. tipski sustav može samostalno zaključiti kojije statički tip varijable bez eksplicitnog definiranja. Pogodan je za pisanje velikihaplikacija kao i vodeći jezici u toj kategoriji, no zbog određenih karakteristika

1Među ostalim, neki popularniju dinamički jezici imaju podršku samo za jednu nit izvođenjau isto vrijeme.

3

koje smanjuju potrebnu količinu kôda jednako se lako može koristiti za pisanjemanjih skripti. Podržava funkcijsku paradigmu, međutim ne odbacuje objektnoorijentirane mogućnosti.

Scala se može nazvati duhovnim nasljednikom Jave: izvršava se na Java virtu-alnom stroju (Java Virtual Machine), kompatibilna je s postojećim Java progra-mima i bibliotekama te je pogodna za korištenje na operativnom sustavu Android.Prevedeni (compiled) programi su gotovo identični Javinim prevedenim progra-mima; glavna je razlika u tome što Scala programi zahtijevaju biblioteku Scalinihklasa (scala-library.jar) prilikom izvođenja. Za razliku od čistih funkcijskih jezika,učenje i korištenje Scale nije zahtjevno niti komplicirano, bez obzira na prijašnjeprogramersko iskustvo. Slično kao i korištenje dinamičkih jezika, korištenje Scalaje jednostavno i intuitivno.

3.2. HelloWorld

Primjer 3.1: Hello World program u Scali

1 object BokSvijete extends App {

2 println("Bok, svijete!")

3 }

Kôd na prvi pogled donekle podsjeća na Java kôd, no primjećuju se određenerazlike:

– Za razliku od Jave, Scala ne podržava static modifikator. Ključna riječobject uzrokuje kreiranje točno jedne instance klase, čiji se sadržaj možekoristiti kao statički dio klase u Javi.

– Svaka Scala klasa ima primarni konstruktor, koji se nalazi u tijelu klase.Ostali (sekundardni) konstruktori moraju zvati primarni konstuktor.

– Scala klase i objekti uvijek imaju na raspolaganju sve definicije koje senalaze u objektu Predef u paketu scala. Među njima se nalazi definicijametode println(String).

– Kao i sav ostali sadržaj scala paketa, u njemu je uvijek dostupan i App

trait koji (korištenjem DelayedInit marker traita) “prebacuje” tijelo klase(tj. konstruktor) u standardnu JVM main metodu, kako bi se kôd mogaojednostavno izvršiti bez potrebe za definicijom takve metode.

4

– Scala podržava, no ne zahtijeva točku sa zarezom na kraju svakog izraza.Korištenje tog interpunkcijskog znaka nije preporučeno, jer gotovo nikadane pridonosi čitljivosti kôda.

3.3. Osnovne karakteristike

Primjer 3.2: Demonstracija osnovnih karakteristika

1 class DemonstracijskiPrimjer (

2 val konstanta: Int,

3 var varijabla: Double,

4 opisnik: String = ""

5 ) {

6

7 def ispišiBroj(broj: Int) {

8 println(broj)

9 }

10 def udvostruči(broj: Int) = broj * konstanta

11

12 def primjeni(funkcija: (Int) => Int)(broj: Double) = funkcija(broj

toInt)

13

14 println(opisnik + ": " + primjeni(funkcija = udvostruči)(varijabla))

15 }

Tip varijable slijedi njeno ime te je odvojen dvotočkom, za razliku od Jave.Parametri klasa, metoda i funkcija mogu imati default vrijednost koja se koristiako vrijednost parametra nije navedena prilikom pozivanja. Moguće je imenovatiparametre prilikom poziva metode radi lakše čitljivosti kôda. Između definicijemetode i tijela mora stajati znak jednakosti = ukoliko metoda ima povratnuvrijednost; u suprotnom Scala pretpostavlja da metoda nema povratnu vrijednost,odnosno povratna vrijednost je Unit (slično kao void u Javi). Točka izmeđuobjekta nad kojim pozivamo metodu i poziva metode je opcionalna ako metodaprima točno 0 ili 1 parametar.

Scala razlikuje četiri vrste identifikatora:– val (value) predstavlja konstantu, odnosno varijablu čiji se sadržaj ne možemijenjati (immutable)

5

– lazy val predstavlja konstantu čiji se sadržaj ne evaluira na mjestu defi-nicije, nego tek pri prvom pristupu

– var (variable) predstavlja uobičajenu promjenjivu varijablu (mutable)

– def (definition) predstavlja definiciju metode

Scala prati Uniform access principle; metode ne moraju imati zagrade, pričemu ne postoji razlika u pristupanju metoda bez argumenata (npr. def vraća2

= 2) i varijabli (val vraća2 = 2). Štoviše, oba imena (vraća2 ) se nalaze u istomprostoru imena, te bi takva “dvostruka” definicija uzrokovala grešku prilikom pre-vođenja. Ovaj princip omogućuje primjerice inicijalno definiranje neke varijable,te naknadnu zamjenu iste metodom, bez promjene klijentskog kôda. Neki jeziciimaju slične mogućnosti, no u Scali je ovo maksimalno pojednostavljeno. [9]

Svaki blok naredbi predstavlja izraz (expression) koji se može pridjeljivativarijablama, što znači da je kôd poput val dva = {val jedan = 1; jedan + 1}

valjan. Zadnji izraz predstavlja povratnu vrijednost bloka naredbi, pa nije po-trebno ni preporučljivo na kraju bloka koristiti ključnu riječ return; tada nijepotrebno definirati povratni tip, već će on biti automatski zaključen na temeljuzadnjeg izraza u bloku.

Primitivni tipovi kao što su int ili float ne postoje, već su svi takvi tipovipunopravne klase: Int, Float, itd. Prevoditelj prepoznaje u kojem se kontekstutipovi koriste, te ovisno o tome generira brži kôd koji koristi primitivne JVMtipove, bez da se programer brine o takvim detaljima. Svi tipovi nasljeđujuklasu Any; “primitivni” tipovi nasljeđuju klasu AnyVal, dok svi ostali (referentni)tipovi nasljeđuju AnyRef. Sve klase prevedene Scala prevoditeljem nasljeđujuklasu ScalaObject.

3.4. Funkcijski aspekti

Kontrola toka pomoću ključne riječi if funkcionira jednako kao u Javi; međutim,pošto je svaki blok naredbi ujedno i izraz sa povratnom vrijednošću, jednako takoi if statement ima povratnu vrijednost:

Primjer 3.3: if uvjet

1 val rezultat = if (1 + 1 == 2) "Procesor radi normalno." else "?!?"

Tip definirane nepromjenjive varijable rezultat je automatski zaključen prilikomprevođenja: String. Ukoliko ne definiramo else granu, tip će biti najopćenitiji

6

mogući: Any.

While petlja radi identično kao i u Javi.

Primjer 3.4: while petlja

1 var brojač = 0

2 while (brojač < 10) {

3 brojač += 1

4 println(brojač)

5 }

Operatori koji povećavaju ili smanjuju vrijednost neke varijable za 1 (pre/postincrement/decrement nisu podržani, pošto takav kôd nije u duhu funkcijskogprogramiranja.

Standardna for petlja je izbačena: umjesto nje postoji for comprehension,odnosno for izraz. Riječ je o naprednijem obliku uobičajene for petlje, koji seoslanja na određene metode koje implementiraju sve Scala kolekcije po kojima jemoguće iterirati.

Primjer 3.5: for izraz i lambda funkcije

1 val programskiJezici = List("Scala", "Haskell", "D")

2

3 for (jezik <- programskiJezici) {

4 println(jezik)

5 }

6

7 def mojPrintlnMetoda(nekiTekst: String)) { nekiTekst =>

println(nekiTekst) }

8

9 val mojPrintlnFunkcija: (String) => Unit = nekiTekst =>

println(nekiTekst)

10

11 programskiJezici.foreach(jezik => println(jezik))

12

13 programskiJezici foreach((jezik) => mojPrintlnFunkcija(jezik))

14

15 programskiJezici foreach(mojPrintlnFunkcija(_))

16

7

17 programskiJezici foreach { jezik =>

18 mojPrintlnMetoda(jezik)

19 }

Kao što je vidljivo, for comprehension se oslanja na postojanje metode foreach

u kolekciji po kojoj iteriramo. Metoda prima funkciju koja ima točno jedan para-metar, jednakog tipa kao što je i tip kolekcije, a rezultat funkcije se odbacuje. Akometoda prima funkciju kao parametar, radi bolje čitljivosti moguće je i preporučase korištenje vitičastih zagrada.

Funkcije se mogu definirati samostalno pridjeljivanjem funkcije varijabli, nou tom slučaju je bolje definirati pravu metodu pošto je takvu sintaksu jednos-tavnije čitati. Funkcije se najčešće definiraju unutar poziva neke metode kaolambda funkcije; tada obično nije potrebno definirati tipove parametara i po-vratne vrijednosti, pošto ih prevoditelj zaključuje na temelju potrebnih tipovametode. Lambda funkcije se vrlo jednostavno definiraju, te u slučaju 1 para-metra nije potrebno imenovati parametar, kojem se jednostavno pristupa wild-cardom _ (podcrtom). Moguće je koristiti anonimne parametre i u slučaju višeparametara; tada svaka podcrta predstavlja jedan parametar, redom. Ukolikoimenujemo parametre, oni se obvezno okružuju običnim zagradama ukoliko ihima više i odjeljuju od tijela lambda funkcije znakovima =>.

Primjer 3.6: Ključna riječ yield

1 val imena = List("Tamara", "Iva", "Ana")

2

3 val prvaSlova = for (ime <- imena) yield ime.head

4 prvaSlova foreach { println(_) }

5

6 (for (ime <- imena) yield ime.head) foreach (println(_))

Moguće je iskoristiti for comprehension i za kreiranje nove kolekcije iz posto-jeće: ako na kraju dodamo ključnu riječ yield, iteracija početne kolekcije će usvakom koraku dodavati po jedan svježe generiran element u novu kolekciju, arezultat cijelog for comprehensiona je upravo ta nova kolekcija.

Filtriranje elemenata je moguće ostvariti dodavanjem if uvjeta. Rezultat jeekvivalentan korištenju metode filter nad kolekcijom.

Iz vidljivog, očito je moguće povući paralelu s Haskellovim list comprehensionsintaksnim šećerom.

8

Primjer 3.7: if unutar for izraza

1 val raspon = 1 to 10

2

3 val parniBrojevi =

4 for (broj <- raspon if (broj % 2 == 0))

5 yield broj

6 println(parniBrojevi) // Vector(2, 4, 6, 8, 10)

7

8 val parniBrojevi2 = raspon filter(_ % 2 == 0)

9 println(parniBrojevi2) // Vector(2, 4, 6, 8, 10)

3.5. Kolekcije

Kolekcije podataka su veoma inteligentno napravljene i dovoljno razgranate dapokriju većinu potreba [8], no istovremeno su vrlo jednostavne za upotrebu [7].Najosnovnije strukture su lista (List), skup (Set) i mapa (Map). Scala podržavanekoliko podvrsta tih struktura za različite upotrebe, uključujući nepromjenjive(immutable), promjenjive (mutable), konkurentne (concurrent) i paralelne (paral-lel) verzije. Većina kolekcija implementira uobičajene metode funkcijskih jezika:map, fold, reduce, foreach, head, tail, take, drop, itd. Također je moguće kolekcijepretvarati iz jednog tipa u drugi; točni rezultati operacija ovise o tipu kolekcije.

Primjer 3.8: Primjer kolekcija

1 1 until 10 // collection.immutable.Range

2 1 to 10 // collection.immutable.Range.Inclusive

3 List(1, 2, 3) // collection.immutable.List

4 Set(1, 2, 3) // collection.immutable.Set

5 Map(1 -> ’a’) // collection.immutable.Map

6 Seq(1, 2, 3) // collection.immutable.List

7 IndexedSeq(1, 2) // collection.immutable.Vector

8 Traversable(1, 2) // collection.immutable.List

9

10 // collection.parallel.immutable.ParVector

11 (1 to 1000000).toList.par

Kolekcije su fundamentalno izmjenjene izlaskom Scale 2.8. Verzija 2.9. jedonijela nove paralelne kolekcije [2], a verzija 2.10 uvodi konkurentnu kolekciju

9

TrieMap koja omogućuje konkurentni pristup kolekciji bez potrebe za vanjskomsinkronizacijom (concurrent lock-free) [3]. Iako se radi o veoma naprednoj i kom-pleksnoj strukturi, korištenje je izuzetno jednostavno.

3.6. Ostale mogućnosti

Naprednije mogućnosti tipskog sustava uključuju: objekte (object - posebne je-dinstvene statičke instance klasa), traitove (trait - “mixin” - sučelje sa imple-mentacijama metoda), složene tipove (compound types), apstraktne tipove, gornjei donje granice generičkih tipova, kovarijantne i kontravarijantne tipove te impli-citno zaključivanje o tipovima.

Korisne mogućnosti za funkcijsko programiranje su: lambda funkcije, imeno-vani parametri, lokalne metode, rekurzija, repno-rekurzivna optimizacija (tail-recursive call optimization), parcijalne funkcije, currying, parcijalno primjenjenefunkcije, type classes te širok i koristan skup metoda kolekcijskih klasa koje dolazeiz čisto-funkcijskih jezika.

Jedinstvene mogućnosti Scale su: operatorske metode2, implicitne konverzije,implicitni parametri, “magične” metode apply i update, manifesti, jednostavnakonstrukcija DSL-ova3 kombinacijom operatorskih metoda i izostavljanja točkekod poziva takvih metoda.

3.7. Vanjske biblioteke

Iako Scala podržava sve postojeće biblioteke napisane za Javu, u zadnjih nekolikogodina se pojavio veliki broj različitih vanjskih biblioteka (third party libraries)različitih autora koje omogućuju pisanje jednostavnijeg, čitljivijeg i lakše održivogkôda u odnosu na Javine biblioteke.

Najpoznatije biblioteke su:

– Web: Lift, Play!, Scalatra, Bowler

– REST: Spray, BlueEyes, Dispatch, Unfiltered

– Baze podataka: Squeryl, ScalaQuery, O/R Broker, Scalandra, Anorm

– Raspodijeljeno računanje: Akka, Kestrel, Spark, Swarm

– Testiranje: ScalaTest, Specs2, ScalaCheck2imena metoda mogu sadržavati operatorske znakove, npr. +, -, *, itd.3Domain Specific Language - jezik napisan za određenu usku primjenu.

10

– Ostalo: Scalala, Scalaz

3.7.1. Unfiltered

Unfiltered je biblioteka koja omogućuje jednostavno postavljanje HTTP posluži-telja. Nathan Hamblen također je autor biblioteke Dispatch, koja služi za slanjeHTTP zahtjeva odgovarajućem poslužitelju, pa je moguće jednostavno kombini-rati Dispatch na strani klijenta s Unfiltered poslužiteljem. 4

Biblioteka obrađuje zahtjeve pomoću planova (plan) i namjera (intent).Namjera je parcijalna funkcija (PartialFunction 5) koja prima dolazni HTTPzahtjev te na njega odgovor ukoliko je za taj zahtjev definirana (ukoliko niti jednafunkcija nije definirana za neki zahtjev, Unfiltered automatski vraća HTTP grešku404). Plan je trait koji spaja parcijalnu funkciju sa poslužiteljskim sučeljem; svakosučelje ima vlastiti plan.

Moguće je napisati vlastiti poslužiteljski kôd koji će preko odgovarajućeg Un-filtered sučelja odgovarati na zahtjeve; ipak, biblioteka dolazi s nekoliko poslu-žiteljskih sučelja i ugrađenih poslužitelja koji se vrlo jednostavno koriste - nijepotrebno konfigurirati ili pokretati vanjske programe. Postoje sučelja za: JavaServlet API (Servlet Filters), Java Servlet 3.0 asinkroni API (Asynchronous Ser-vlet Filters te Netty mrežne kanale (channels). Ugrađeni poslužitelji su: Jetty,Jetty-AJP (Apache JServ Protocol) i Netty.

3.7.2. SBT

Simple Build Tool autora Marka Harraha preporučen je alat za izgradnju Scalaprojekata. Aktivno se razvija te ga koriste gotovo svi Scala projekti. Glavnaprednost korištenja SBT-a za prevođenje izvornih datoteka u odnosu na direktnokorištenje Scala prevoditelja je to što eliminira vrijeme potrebno za pokretanjeJava virtualnog stroja, pošto drži prevoditelj cijelo vrijeme pokrenut u stanjučekanja (warm standby).

Ima širok spektar mogućnosti:

– prevodi izvorne datoteke napisane u Scali i Javi4Dispatch (0.8) ima određene probleme s Android platformom, koji će biti riješeni tek u idu-

ćoj verziji biblioteke, Dispatch Reboot (0.9). Zato trenutno nije preporučljivo koristiti Dispatchna Android platformi.

5Klasa PartialFunction[A, B] predstavlja funkciju s jednim parametrom tipa A kojane mora biti definirana na cijeloj domeni tog tipa, a vraća rezultat tipa B.

11

– automatski preuzima odgovarajuće verzije Scale i svih potrebnih bibliotekao kojima ovisi projekt koristeći Apache Ivy

– opisnik projekta je napisan u Scala DSL-u

– sadrži ugrađenu ljusku za jednostavnije korištenje koja omogućuje:

• prevođenje i pokretanje programa

• pokretanje Scala REPL-a 6

• automatsko pozadinsko prevođenje i pokretanje programa prilikomizmjene izvornih datoteka

– mogućnost korištenja korisnih alata: ProGuard 7 i JRebel 8 pomoću od-govarajućih dodataka (plugin)

SBT se može koristiti u sklopu drugih alata; poznati primjer je Scala IDE zaEclipse, koji koristi SBT za izgradnju Scala projekata.

3.8. Scala na Androidu

Kao što je rečeno, Scala klase se mogu koristiti iz Jave; potrebno je samo uklju-čiti Scalinu biblioteku, scala-library.jar. Ipak, dotična je biblioteka relativnovelika i sadrži velik broj klasa; radi toga nije preporučljivo jednostavno pakira-nje navedene biblioteke u izlaznu Android aplikaciju, već ju je potrebno prvoobraditi pomoću ProGuarda, kako bi se samo korištene klase zadržale u izlaznojAPK datoteci9. Navedeni postupak je dugotrajan (30-60 sekundi, ovisno o brziniprocesora) i nije skalabilan (Proguard ne može koristiti više jezgri procesora),te je razlog duljem čekanju između izmjene u izvornicima programa i uspješnompokretanju na emulatoru ili uređaju prilikom korištenja Scala klasa.

Moguće rješenje je instalacija Scala biblioteke među sistemske biblioteke nauređaju; navedeni postupak zahtijeva rootani Android uređaj, no sam postupakinstalacije je veoma jednostavan, ako se koristi Scala Standard Library Installer

6Read-Evaluate-Print-Loop, ljuska u kojoj je moguće izravno izvršavati naredbe jezika teodmah vidjeti rezultate izvođenja

7ProGuard je alat koji obrađuje izlazne Java klase: može ih smanjiti, optimizirati, obfusciratite pre-verificirati.

8JRebel omogućuje instantne izmjene pokrenutih klasa u memoriji nakon ponovnog prevo-đenja bez ponovnog pokretanja programa

9Preciznije, kako bi se samo korištene klase predale Android Dex alatu.

12

aplikacija, dostupna na Google Play Storeu10. Nakon instalacije potrebno jeugasiti Proguard korak u odabranom sustavu izgradnje aplikacije, nakon čega ćeprevođenje i pokretanje Scala aplikacije biti puno brže (5-15 sekundi).

Za SBT sustav izgradnje aplikacije postoji nekoliko dodataka koji olakšavajurad s Androidom:

Jan Berkel sbt-android-plugin https://github.com/jberkel/android-plugin

pfn Android SDK Plugin https://github.com/pfn/android-sdk-plugin

Prvi plugin zahtijeva više predinstalacijskih koraka, više konfiguracije, te nijejednostavno prilagodljiv za rad s IDEom. Drugi je plugin je veoma sličan, nojednostavniji za konfiguraciju, uz nešto manje dostupnih mogućnosti.

Oba dodatka za SBT ostvaruju sve korake koji su potrebni da se izvornikôd Android aplikacije prevede, optimizira, zapakira, potpiše s debug ili releaseključem, poravna (align), instalira na uređaju/emulatoru te pokrene.

Alternativno, moguće je koristiti sustav izgradnje nekog od IDE programakoji imaju podršku za Android, direktno ili pomoću dodataka: jedan od takvihIDEa je IntelliJ IDEA, s direktnom podrškom za Android. Uz Scala plugin,IDE omogućuje izgradnju Android aplikacija na sličan način kao i neki od SBTdodataka s podrškom za Android, uz grafičko sučelje.

3.9. Protocol Buffers

Za izmjenu strukturiranih podataka (poruka) između klijenata i poslužitelja prekoprotokola HTTP najraširenije su dvije osnovne vrste formata:

– tekstualni kojem pripadaju XML, JSON, YAML i slični;

– binarni kojem pripada npr. Javina serijalizacija.

Poruke (strukturirani podaci) su često jednostavne za ručno čitanje i pisanje,pošto je s njima moguće raditi u bilo kojem tekstualnom editoru. Ipak, radikorištenja tekstualnog formata, za njihovo čitanje je potrebno koristiti posebni(relativno spori) parser, što usporava program koji ih koristi za izmjenu podataka;za pisanje se koristi također relativno spori prevoditelj. Takve poruke gotovouvijek zauzimaju nešto više prostora; moguće je rješenje korištenje on-the-flykompresije, no to dodatno usporava rad s porukama.

10https://play.google.com/store/apps/details?id=com.mobilemagic.

scalainstaller

13

Različiti binarni formati, uključujući nativnu Javinu serijalizaciju, omogućujunekoliko reda veličine brže slanje i primanje poruka. Takve poruke su običnominimalne moguće veličine, no ovisno o formatu, postoje mnogi problemi: najvećiproblem je nemogućnost direktnog pregleda poruke prilikom prijenosa.

Protokol Protocol Buffers tvrtke Google kombinira najbolje karakteristiketekstualnih i binarnih formata: prvo se definira struktura poruka u posebnoj.proto datoteci, a zatim se ta datoteka prevede u strukturu podataka (klasu)koja se može direktno koristiti u jeziku u kojem pišemo naš program. [6] SlužbeniProtocol Buffers (protobuf ) prevoditelj može prevoditi .proto datoteke u Java,C++ i Python klase, a postoje različiti dodaci i biblioteke za prevođenje u gotovosvaki korišteni programski jezik.11

Primjer 3.9: Definicije Protocol Buffers poruka

1 package com.example;

2 message ProbnaPoruka {

3 required int64 id = 1;

4 required ImePrezime ime_prezime = 2;

5 optional float prosjek = 3;

6 repeated string telefonski_broj = 4;

7 }

8 message ImePrezime {

9 required string ime = 1;

10 required string prezime = 2;

11 }

3.9.1. Implementacija u Scali: ScalaBuff

Do ljeta 2011. godine nije postojala podrška za prevođenje .proto datoteka uklase kompatibilne sa Scalom. ScalaBuff12 je upravo takav prevoditelj, nastaoza vrijeme programa Google Summer of Code 2011. ScalaBuff je program na-pisan u Scali koji ulazne .proto datoteke prevodi u valjane Scala klase čije jesučelje kompatibilno s Java klasama koje generira službeni Googleov prevoditelj;generirane klase se mogu koristiti jednako kao i Java verzije, no postoje određenapoboljšanja, tako da je Scala klase puno lakše koristiti (uz to, količina generiranogScala kôda je za red veličine manja).

11http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns12https://github.com/SandroGrzicic/ScalaBuff

14

Primjer 3.10: Jednostavna poruka

1 message DvaBroja {

2 required int32 prvi_broj = 1;

3 required float drugi_broj = 2;

4 }

Primjerice, Java klasa generirana iz navedene .proto datoteke ima 461 linijugeneriranog kôda, dok Scala klasa ima samo 76 linija, te je puno jednostavnija zakorištenje. Razlika je tim veća što je poruka složenija.

Primjer 3.11: Korištenje poruke DvaBroja u Scali i Javi

1 import {scala.DvaBroja => DvaBrojaScala}

2 import {java.DvaBroja => DvaBrojaJava}

3

4 val prviBroj = 1

5 val drugiBroj = 0.5f

6

7 val scalaPoruka = DvaBrojaScala(prviBroj, drugiBroj)

8

9 val javaPoruka = DvaBrojaJava

10 .newBuilder()

11 .setPrviBroj(prviBroj)

12 .setDrugiBroj(drugiBroj)

13 .build()

Klasa koja je popunjena podacima se može slati kao poruka preko mreževeoma jednostavno; moguće ju je zapisati kao polje byteova, u OutputStream,itd. Primatelj također veoma jednostavno može učitati popunjenu poruku iz poljabyteova, InputStreama, itd.

15

4. SenseGrid

SenseGrid omogućava korištenje senzora ugrađenih u mobilne uređaje s ciljemsuradničkog opažavanja okoline. Programska implementacija se sastoji od klijent-ske aplikacije za mobilne uređaje s operativnim sustavom Android te poslužiteljakoji dobivene podatke skuplja i predaje klijentima. Ipak, ukoliko klijent koristiHTTP za komunikaciju i SenseGrid Protocol Buffers poruke, moguće je napi-sati vlastitog klijenta za bilo koju platformu koja će komunicirati sa SenseGridposlužiteljem.

4.1. Android klijent

Klijentska aplikacija je napisana za Android platformu te podržava verzije opera-tivnog sustava 2.3.3 (API verzija 10) i više; konkretno, verzija 4.0 je u potpunostipodržana. Aplikacija automatski prepoznaje dostupne senzore te osluškuje nji-hova stanja radi slanja poslužitelju. Glavni način pregleda podataka sa senzoraostalih korisnika aplikacije je jednostavna karta koja prikazuje trenutne lokacijekorisnika.

4.1.1. Senzori

Podržani senzori uključuju sve senzore korisne za promatranje okoline:

– temperaturni senzor

– magnetometar

– senzor tlaka (Android verzija 4.0 ili viša)

– senzor relativne vlažnosti (Android verzija 4.0 ili viša)

Poslužitelju se šalju samo podaci sa senzora koji postoje na uređaju, kako bi seminimizirala količina poslanih podataka.

16

Rosište (dew point) i apsolutna vlažnost mogu se izračunati kombinacijomtemperaturnog senzora i senzora relativne vlažnosti; potrebno je da uređaj imaoba senzora, te Android verziju 4.0 ili višu. Računanje rosišta uz poznatu tem-peraturu t (u ◦C) i relativnu vlažnost RV:

td(t, RV ) = b γ(t, RV )a− γ(t, RV ) (4.1)

gdje je (uz a = 17.271, b = 237.7 ◦C):

γ(t, RV ) = a t

b+ t+ ln RV

100% (4.2)

Računanje apsolutne vlažnosti (u g/m3) moguće je korištenje formule:

dv = 216.7RV

100%A exp a∗ttn+t

273.15 + t(4.3)

gdje je A = 6.112 hPa, a = 17.271.

4.2. Poslužitelj

Poslužitelj je napisan u Scali i koristi Unfiltered biblioteku za primanje, obradu iodgovor HTTP zahtjeva. Koriste se Netty plan uz Java NIO kanale (channels) iNetty asinkroni poslužitelj.

Za pohranu podataka u memoriji koristi se konkurentna mapa ConcurrentTri-eMap koja omogućuje izuzetno brzo konkurentno pisanje i čitanje. Ključ mapeje jedinstveni identifikator prijenosnog uređaja, kako bi se struktura mogla osvje-žiti novim podacima bez iteracije kroz cijelu strukturu, a vrijednost su podaci uobliku Protocol Buffers poruka koje sadrži dotični prijenosni uređaj.

4.3. Mrežna komunikacija

SenseGrid Android klijent i poslužitelj koriste protokol Protocol Buffers za među-sobnu izmjenu poruka preko standardnog protokola HTTP; koristi se ScalaBuffza generiranje Scala klasa iz .proto opisnika.

1 val message = Sensors(deviceID, activity.lat, activity.long,

activity.accuracy, System.currentTimeMillis,

Vector(messages.filter(_ != null): _*)

2 )

3

4 message.writeTo(httpConnection.getOutputStream)

17

5. Zaključak

Moderan svijet se sve više fokusira na prijenosne uređaje. Meteorologija zatone treba zaostajati: povećavajući broj mogućih prijenosnih “mini-meteorološkihpostaja” dobivamo preciznije i aktualnije podatke o trenutnim vremenskim uvje-tima kako u našoj okolini, tako i u cijelom svijetu. Operativni sustav Android injegova platforma omogućuje jednostavno korištenje senzora prijenosnih uređaja.SenseGrid koristi te senzore kako bi omogućio jednostavno suradničko opažanjeokolinskih uvjeta na inovativan i zanimljiv način.

Moguća poboljšanja projekta uključuju: više društvenih aspekta u Androidaplikaciji, izradu klijenata za ostale mobilne platforme, izradu web sučelja premaposlužitelju te dodatak poslužiteljskog modula koji će na neki način pametnoobrađivati pristigle podatke u stvarnom vremenu. Također je moguće dodati po-dršku za vanjske senzore, koji se prijenosnim uređajem spajaju preko vanjskogsučelja, primjerice bežično preko protokola Bluetooth ili direktno preko USB ko-nektora. Korisnost aplikacije bi se dodatno povećala primjerice podrškom zasenzore koji mjere radioaktivnost.

18

Literatura

[1] Joel Abrahamsson. Learning Scala, 2010. URL http://joelabrahamsson.

com/entry/learning-scala.

[2] Heather Miller Aleksandar Prokopec. Parallel Collections Library.EPFL, Switzerland, 2012. URL http://docs.scala-lang.org/overviews/

parallel-collections/overview.html.

[3] Phil Bagwell Martin Odersky Aleksandar Prokopec, Nathan G. Bronson.Concurrent Tries with Efficient Non-Blocking Snapshots, 2012. URL http:

//lampwww.epfl.ch/~prokopec/ctries-snapshot.pdf.

[4] Scala Standard Library API Documentation. École Polytechnique Fédéralede Lausanne, Switzerland, 2012. URL http://www.scala-lang.org/api/

current/.

[5] Alex Payne Dean Wampler. Programming Scala. O’Reilly Media, 2008. URLhttp://ofps.oreilly.com/titles/9780596155957/index.html.

[6] Protocol Buffers Developer Guide. Google. URL https://developers.

google.com/protocol-buffers/docs/overview.

[7] Lex Spoon Martin Odersky. The Scala 2.8 Collections API, 2010. URL http:

//docs.scala-lang.org/overviews/collections/introduction.html.

[8] Lex Spoon Martin Odersky. The Architecture of Scala Collec-tions, 2010. URL http://docs.scala-lang.org/overviews/core/

architecture-of-scala-collections.html.

[9] Bertrand Meyer. Uniform Access. Eiffel Software, 2005. URL http://www.

eiffel.com/general/column/2005/Sept_October.html.Idem u školu.

19

Dodatak APokretanje SenseGrida

Sve što je potrebno za ispravnu “instalaciju” je dostupnost Javinog virtualnogstroja, odnosno java naredbe; nije potreban Javin javac prevoditelj (JDK) nitiinstalacija Scale. Moguće je preuzeti i podesiti recentnu verziju Simple BuildToola (http://www.scala-sbt.org/)1, no preporučena verzija tog alata se većnalazi u distribuciji programa u direktoriju sbt. U slučaju korištenja postojećegSBT-a, potrebno ga je pokrenuti prebacivanjem trenutnog direktorija u direktorijprojekta, te izvršavanjem naredbe sbt/sbt (inače je dovoljna samo naredba sbt).

Prvim pokretanjem SBT-a će proći neko vrijeme dok se ne preuzmu sve po-trebne biblioteke (uključujući android-sdk-plugin dodatak za SBT). Dolaskom doljuske SBT-a moguće je izvršavati naredbe; trenutnu je naredbu moguće dovršitipritiskom tipke TAB. Korisne naredbe uključuju:

– exit za izlaz

– help za pomoć

– devices za popis trenutno spojenih Android uređaja

– device <ID> za odabir zadanog spojenog Android uređaja

– android:run za pokretanje aplikacije na trenutno spojenom Android ure-đaju

– project <projekt> za odabir projekta (android ili server)

– run za pokretanje projekta

Naredba run će prije pokretanja prevesti izvorišne datoteke u izlazne, ukolikoizlazne datoteke ne postoje ili su se izvorišne datoteke promijenile u odnosu naposljednje prevađanje.

1android-sdk-plugin dodatak u obliku gotove binarne biblioteke u repozitoriju postoji samoza SBT verziju 0.11.2, pa je u slučaju novije verzije potrebno ručno izgraditi dodatak.

20

Za pokretanje Android aplikacije potrebno je odabrati projekt naredbomproject android, nakon čega će android:run pokrenuti aplikaciju na trenutnuodabranom spojenom uređaju.

Pokretanje poslužitelja se odvija odabirom poslužiteljskog projekta - project

server - te pokretanjem trenutno aktivno projekta: run. Poslužitelj se gasipritiskom bilo koje tipke.

Unutar SBT-a je moguće pokrenuti interaktivnu Scalinu konzolu (REPL) na-redbom console, iz koje se izlazi kombinacijom CTRL+D.

Cijeli ovaj postupak je moguć radi toga što SBT pokretač (kompatibilan sJavom) prvo preuzme potrebnu verziju Scalinih biblioteka (2.9.1) i definirane do-datke (u ovom slučaju sbt-android-plugin), zatim pokrene upravo preuzeti SBTkoji onda preuzme projektnu verziju Scalinih biblioteka (2.9.2) i sve ostale pro-jektne biblioteke.

21

SenseGrid: Aplikacija za suradno opažanje okoline putem uređaja soperativnim sustavom Android

Sažetak

U radu se opisuje projekt SenseGrid čija je namjena suradničko opažanje oko-linskih uvjeta. Projekt se sastoji od aplikacije za operativni sustav Android iposlužitelja, napisanih u programskom jeziku Scala. Komunikacija klijentskogprograma i poslužitelja se odvija preko mreže, koristeći Scala implementacijuProtocol Buffera za razmjenu poruka, ScalaBuff.

Ključne riječi: android, scala, sensegrid, mobilni uređaj, pokretna mreža, opa-žanje okoline, praćenje uređaja, kolaboracija, scalabuff

SenseGrid: Collaborative environment observation using mobiledevices with the Android operating system

Abstract

The result of this study is the SenseGrid project, with the goal of collabo-rative environment observation using mobile devices. The project consists of anapplication for the Android operating system and a server, both of which arewritten in the Scala programming language. The client application and the ser-ver communicate via network, using the Scala implementation of Protocol Buffersfor message sending, ScalaBuff.

Keywords: android, scala, sensegrid, mobile device, mobile network, environ-ment observation, device tracking, collaboration, scalabuff


Recommended