Høgskolen i Østfold Avdeling for Ingeniørfag Kråkerøy 1671 Fredrikstad Telefon: 69 21 50 00 www.hiof.no Bacheloroppgave Prosjektkategori: Fritt tilgjengelig Hovedprosjekt Omfgang i studiepoeng: Fritt tilgjengelig etter: 20 Fagområde: Tilgjengelig etter avtale med Elektronikk oppdragsgiver Tittel: Dato: Mobilt tidtakersystem 2015-06-14 Forfatterere: Veileder: Arshad Shakil Per T. Huth 7 David Kristiansen Avdeling / Program: Gruppenummer: Avdeling for ingeniørfag / Elektronikk H15E11 Oppdragsgiver: Kontaktperson hos oppdragsgiver: Båstad IL. Per T. Huth Ekstrakt: Det skal utvikles et mobilt tidtagersystem, ved hjelp av radio- sendere/mottakere, og mobil-app. Det skal evalueres hvilken trådløs teknologi som egner seg best av WiFi, iBeacon og RFID 3 emneord: Tidtaking Mobilapplikasjon Databasebehandling H15E01 14. juni 2015 Østfold University College The faculty of engineering Kråkerøy 1671 Fredrikstad Phone: 69 21 50 00 www.hiof.no Bachelor Thesis Category of project: Free accessible Major project Number of stp. (1stp = 1ECTS): Free access after: 20 Enigneering field: Accessible after agreement Electronics with the contractor Poject title: Date: Mobile time measurement system 2015-06-14 Authors: Councellor: Arshad Shakil Per T. Huth 7 David Kristiansen Department / Line: Poject number: The faculty of engineering / Electronics H15E11 Produced in cooperation with: Contact person at the contractor: Båstad IL. Per T. Huth Extract: Developing a mobile timer with the use of radio senders/recievers and mobile app. Also to evaulate which wireless technology is most suited for this choosing from Wi-Fi, iBeacon or RFID 3 indexing terms: Time measurement Mobile application Database management H15E01 14. juni 2015 i Forord Prosjektet går ut på å konstruere et mobilt tidtakersystem, ved bruk av radiomottakere/sendere, og mobil-app. Det skal også vurderes flere mulige løsninger for radio. Deriblant iBeacon og Radio Frequency Identification (RFID). Vår studieveileder Per Thomas Huth har gjennom sitt virke i Båstad IL, kommet med et ønske om å få konstruert et mobilt tidtakersystem for bruk ved Båstad IL kunstisbane. Vi vil gjerne takke Dejan Krunic for all hjelpen vi mottok med arbeidet rundt beacon og databaser. Vi vil også takke Marius Aurmo, Martinius Hæreid og Øystein Olsen for lån av Estimote beacon, og innblikk i kildekoden de brukte i beacon prosjektet deres. Gruppen har også hatt dårlig tid med å jobbe med bacheloren. Dette er fordi gruppen fikk tildelt oppgaven sent som følge av sykdom hos forrige veileder på en annen oppgave, og fordi det skjedde en feil ved bestilling av varer. Varene ankom den 23 mai, og for å sikre at det ble laget en løsning, så ble arbeidsoppgavene fordelt. Arshad Shakil tok seg av utvikling av mobilapplikasjon, mens David Kristiansen skulle jobbe med serverdrift og oppsett av database. Arshad Shakil H15E01 David Kristiansen 14. juni 2015 iii Innhold 1 Innledning 1.1 Bakgrunn for oppgaven . . 1.2 Oppgavens mål og formål . 1.2.1 Prosessmål: . . . . 1.2.2 Resultatmål: . . . 1.2.3 Effektmål: . . . . 1.3 Krav . . . . . . . . . . . . 1.4 Prioritet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 1 2 2 2 3 2 Teori 2.1 Trådløse overføringsprotokoller . . . 2.1.1 Bluetooth . . . . . . . . . . . Bluetooth Smart . . . . . . . 2.1.2 iBeacon . . . . . . . . . . . . Funksjoner . . . . . . . . . . Tekniske detaljer . . . . . . . Strømforbruk . . . . . . . . . Krav til bruk . . . . . . . . . 2.1.3 RFID . . . . . . . . . . . . . 2.1.4 WiFi . . . . . . . . . . . . . 2.2 Programmering . . . . . . . . . . . . 2.2.1 Programmeringsspråk . . . . 2.2.2 Utviklerverktøy . . . . . . . . 2.2.3 Åpen kildekode og bibliotek . 2.3 Androidapplikasjoner . . . . . . . . . 2.3.1 Hovedkomponentene i en app 2.3.2 Livssyklus . . . . . . . . . . 2.3.3 Brukergrensesnitt . . . . . . . 2.4 Server . . . . . . . . . . . . . . . . . 2.4.1 LAMP . . . . . . . . . . . . 2.4.2 MySQL . . . . . . . . . . . . PHPMyAdmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 5 5 6 6 7 8 8 9 9 10 10 10 10 11 11 11 12 13 13 13 13 3 Løsningsstrategi 3.1 Beskrivelse av totalsystemet 3.2 Valg av trådløs teknologi . . 3.2.1 RFID . . . . . . . . 3.2.2 Wi-Fi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 16 16 17 H15E01 . . . . . . . . . . . . . . . . . . . . iv INNHOLD 3.2.3 iBeacon . . . . . . . . . . . . . 3.3 Valg av beacon . . . . . . . . . . . . . 3.4 Definering av et enkelt region . . . . . 3.5 Valg av utviklerverktøy . . . . . . . . . 3.6 Bruk av åpen kildekode og bibliotek . . 3.7 Kalkulering av rundetid . . . . . . . . . 3.8 Valg av hastighet på mottaker og sender 3.9 Valg av serverløsning . . . . . . . . . . 3.9.1 Raspberry Pi . . . . . . . . . . 3.9.2 Arch Linux ARM . . . . . . . . 3.10 Utstyrsliste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 19 20 21 21 21 22 23 23 24 25 4 Løsning 4.1 Mobilapplikasjon . . . . . . . . . . . . . 4.1.1 Registrering og sletting av bruker 4.1.2 Kommunikasjon med server . . . 4.1.3 Bruk av drivere og funksjoner . . 4.1.4 Rundetelling og tidtaking . . . . . 4.1.5 Brukergrensesnitt og varsler . . . 4.1.6 Varsler . . . . . . . . . . . . . . 4.1.7 Sikkerhet . . . . . . . . . . . . . 4.1.8 Justering av innstillinger . . . . . 4.2 Server . . . . . . . . . . . . . . . . . . . 4.2.1 Oppsett av server . . . . . . . . . 4.2.2 Oppsett av nettkiosk . . . . . . . 4.2.3 Oppsett av database . . . . . . . . 4.2.4 Registrering og sletting av bruker 4.2.5 Registrering av rundetid . . . . . 4.2.6 Visning av resultater . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 27 28 28 29 30 30 31 33 33 34 34 34 35 35 36 36 . . . . 37 38 41 42 44 5 Testing 5.1 Registrering og sletting av bruker . 5.2 Detektering av beacons . . . . . . 5.3 Registrering av rundetid . . . . . 5.4 Stabilitet og sikkerhet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Diskusjon 45 7 Konklusjon 47 Vedlegg A Flytskjema registrering Vedlegg B Flytskjema sletting Vedlegg C Flytskjema Rundetelling I III V Vedlegg D Kildekode for UpdateInfo VII Vedlegg E Kildekode for UserProfile XIX 14. juni 2015 INNHOLD Vedlegg F Kildekode for deleteUser.php XXXIII Vedlegg G Kildekode for insertValue.php XXXV Vedlegg H Kildekode for updateInfo.php XXXVII Vedlegg I Kildekode for passering.php Vedlegg J Post-installeringsskript Arch Linux H15E11 XXXIX XLIII v 14. juni 2015 vii Figurer 1.1 Spesifikasjoner for skøytebanen . . . . . . . . . . . . . . . . . . . . 2.1 2.2 2.3 2.4 2.5 Soner i en beacon region[11] . . . . . . . . . . Detektere bevegelse inn og ut av en region[11] Strømforbruk ved scanning av beacons[14] . . Livssyklus for aktiviteter Android . . . . . . . LAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7 8 12 13 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 Flyt mellom enhetene ved Wi-FI/iBeacon løsning Flyt mellom enhetene ved RFID løsning . . . . . Forskjellene mellom iBeacon, Wi-Fi og RFID . . Model X dimensjoner . . . . . . . . . . . . . . . Estimote beacon . . . . . . . . . . . . . . . . . . Skjermbilde fra Estimote app . . . . . . . . . . . Region . . . . . . . . . . . . . . . . . . . . . . Rapsberry Pi logo . . . . . . . . . . . . . . . . . Arch Linux ARM logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 16 19 19 20 20 22 23 24 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 Totalsystemet . . . . . . . . Registreringsskjemaet . . . . Hovedsiden . . . . . . . . . Bluetooth tillatelse . . . . . Skrur på bluetooth . . . . . . Notifikasjon fra låst skjerm . Notifikasjon i statusfeltet . . Holder på å registrere bruker Bekreft at bruker skal slettes Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 31 31 32 32 32 32 32 32 36 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 Automatisk åpning av registreringskjema . . . Beskjed om at bruker har blitt opprettet . . . . Databaseoppføring for bruker . . . . . . . . . . Beskjed om at bruker allerede finnes . . . . . . Brukeropplysninger har blitt endret . . . . . . . Databaseoppføring med endringer . . . . . . . Bekreftelse på at bruker har blitt slettet . . . . . Diverse feilmeldinger . . . . . . . . . . . . . . Appen ser en region med to forskjellige beacons Antall kringkastinger mottat på rundt ett sekund . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 38 39 39 39 40 40 41 42 42 H15E01 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 viii FIGURER 5.11 5.12 5.13 5.14 5.15 5.16 5.17 5.18 Runderegisterring med påfølgende korrigering . Databaseoppføring med korrigert rundetall . . . Opptil ni målinger pr sekund . . . . . . . . . . Ingen bruker registrert i tabellen ved passering . Stopp rundetelling . . . . . . . . . . . . . . . . Feil ved tilkobling til server . . . . . . . . . . . Bluetoothkræsj . . . . . . . . . . . . . . . . . Antallet bluetoothkræsj på 4 timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 43 43 43 44 44 44 44 14. juni 2015 ix Tabeller 1.1 Liste over hva gruppen prioriterer av arbeid . . . . . . . . . . . . . . 3.1 3.2 3.3 3.4 Fordeler / ulemper med RFID . . Fordeler / ulemper med Wi-Fi . Fordeler / ulemper med iBeacon Utstyrsliste . . . . . . . . . . . H15E01 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 16 17 18 25 14. juni 2015 xi Kodeopplistinger 4.1 4.2 4.3 4.4 4.5 4.6 D.1 E.1 F.1 G.1 H.1 I.1 J.1 H15E01 Inkludering av bibliotek i build.gradle . . . . . Definere hvilke regioner som skal overvåkes . . Definering av hvert region . . . . . . . . . . . Utklipp av setBeaconVariables klassen . . . . . Initialisering av verdier . . . . . . . . . . . . . Automatisk oppdatering av nettside med live.js UpdateInfo.java . . . . . . . . . . . . . . . . . UserProfile.java . . . . . . . . . . . . . . . . . deleteUser.php . . . . . . . . . . . . . . . . . insertValue.php . . . . . . . . . . . . . . . . . updateInfo.php . . . . . . . . . . . . . . . . . passering.php . . . . . . . . . . . . . . . . . . post_install.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 29 30 33 34 35 VII XIX XXXIII XXXV XXXVII XXXIX XLIII 14. juni 2015 xiii Sammendrag Denne oppgaven går ut på å konstruere et enkelt tidtagersystem for bruk på Båstad ILs kunstisbane. Systemet skal være trådløst, og enkelt å bruke for sluttbrukere. En del av oppgaven går ut på å finne ut hvilken løsning som egner seg best for trådløst kommunikasjon.Teknologiene å vurdere er iBeacon, RFID og Wireless Fidelty (IEEE 802.11x) (WiFi). Løsning havnet på førstnevnte. Det ble utviklet en appløsning som kunne kommunisere med en server. Denne appen gjorde det mulig å registrere seg, og hadde en rekke funksjoner knyttet til registrering av bruker, samt rundetelling og tidtaking. Systemet er kjapt, enkelt å vedlikeholde og kan kjøres på de nyeste mobiltelefonene. H15E01 14. juni 2015 xv Abstract This paper is based on an assignment given from Båstad IL to contstruct a simple time measuring system. The system is supposed to be wireless and should be easy to use. A part of the assignmen is to discuss which solution is the best for wireless communication in this given case. The technologies to evaluate are iBeacon, RFID and WiFi. The conclusion was that iBeacon was the most viable solution An application was developed to communicate with a server. This application made it possible for a user to make a user account.It also had a lot of functionality when it came to the registration process and calulation of laps and laptime a user had. The system is easy to maintain, has low latency, and can be run on most of the newer mobilephones. H15E01 14. juni 2015 1 Kapittel 1 Innledning 1.1 Bakgrunn for oppgaven Oppdragsgiver har forespurt, gjennom vår kontaktperson, et system som går ut på å konstruere en rundeteller til Båstad ILs skøytebane. Oppdragsgiver ønsker et system for rundetelling og tidtaking i forbindelse med trimarrangementene Villbåstingen og Paddehatten; hvor noe av konkurransen er å gå flest mulig runder på fire timer. I tillegg ønskes same system å benyttes i trenings-sammenheng ved at enkeltløpere da kan benytte samme systemet. Oppdragsgiver ønsker også at vi skal vi skal vurdere flere løsninger for trådløs kommunikasjon mellom deltaker og rundetelleren. 1.2 Oppgavens mål og formål Formålet med oppgaven er å kunne telle antall runder enkeltløpere har gjort på skøytebanen til Båstad IL. Det er også ønskelig å kunne ta rundetiden, samt å sette alt dette opp via en mobilapplikasjon. Målet er å gjøre konstruksjonen av systemet på et nivå, som gjør det mulig for Båstad IL å kunne benytte seg av dette. 1.2.1 Prosessmål: Gi deltakerne kunnskap innen programmering av mobil-applikasjoner, og oppsett av databaser. Samt å lære om forskjellige trådløse protokoller og hvordan de kan brukes. H15E01 2 1.3. KRAV 1.2.2 Resultatmål: Gruppen ønsker å få til et mobilt system som kan ta tiden på deltakere i løp, og sende den trådløst til en serverløsning. Resultatene kan i etterkant vises på skjerm, og om det er ønskelig kan det vises resulateter etter gitte kriterier. 1.2.3 Effektmål: Lage et resultat som Båstad IL kan benytte seg av under sine arrangementer. 1.3 Krav Oppdragsgiver ga følgende krav til systemet: Systemet skulle konstrueres til en skøytebane. Banen er en 400 meter hurtigløpsbane, og målepunktet bør være på oppløpssiden ved målgang 1000m. Den er 12 meter bred og er delt inn i tre baner på 4 meter og følger ISU sine krav til bruk av baner i konkurranser [1, s. 37]. Figur 1.1: Spesifikasjoner for skøytebanen For trimløp hadde burde systemet ha følgende funksjoer: • Telle runder for hver deltaker. • Måle tid på hver runde for hver deltaker. • Styre storskjerm med følgende funksjoner. • Vise navn og antall runder for alle deltakere når de passerer målefeltet. 14. juni 2015 KAPITTEL 1. INNLEDNING • Vise foreløpig resultatliste etter antall runder. • Kunne vise enkeltresultater etter forskjellige kriterier som alder, kjønn etc. • Ha en total resultatlsite hvor det kan sorteres etter forskjellige kriterier • Ha mulighet til å presentere resultatene på personlig mobil. Oppdragsgiver stiller med opptil 5000kr for utvikling av dette systemet. 1.4 Prioritet For å få til en best mulig løsning har de forskjellige kravene blitt gitt forskjellig prioritet. Det er også lagt vekt på prioritet som følge av tid, kompetanse eller nødvendighet for at en løsning skal kunne være god nok. Høyest prioritet: Dette er arbeid som gruppen prioriteter høyest. Dette er arbeid som er essensielt for utforming av en løsningsstrategi. Dette er arbeid som må gjøres. Høy prioritet: Dette er arbeid som gruppen burde få til. Dette er viktig for å kunne lage en platform som kan utvikles vider. Denne platformen kan forbedres og flere funksjoner kan legges til. Middels prioritet: Dette er arbeid som gruppa ser på som greit å få til, men ikke nødvendig for at en løsning skal kunne fungere, men som forbedrer brukeropplevelsen. Lav prioritet: Dette er arbeid som i stor helhet dreier seg om det kosmetiske og arbeid som ikke påvirker løsnignen i stor grad. Tabell 1.1: Liste over hva gruppen prioriterer av arbeid Høyest prioritet: • Vurdere og finne ut av hvilken trådløs teknologi som egner seg best. • Konstruere et system som kan telle antall runder enhver deltaker har tatt. • Konstruere et system som kan måle rundetiden. Høy prioritet: H15E11 3 4 1.4. PRIORITET Tabell 1.1 (Fortsettelse) • Gjøre at systemet kan lagre rundetider og antall runder • Mulighet til å vise resultatene på skjerm • Sikkerhetsmekanismer for å forhindre feiloppføringer og rot i resultatlista Middels prioritet: • Mulighet til å vise resultatene på mobil fortløpende. • Mulighet til å sortere resultater som vises på skjerm Lavest prioritet: • Design og layout av mobilapplikasjon og resultatlister. • Bruk av farger og fine ikoner i applikasjonen • Kryptering av kommunikasjonen mellom klient og server 14. juni 2015 5 Kapittel 2 Teori 2.1 Trådløse overføringsprotokoller 2.1.1 Bluetooth Bluetooth er definert i IEEE802.15.1. Dette er en del av Wireless Personal Area Network (WPAN)-standaren. [2]. Dette er en trådløs overføringsteknologi som benytter båndbredde fra 2.4 til 2.485 GHz. Bluetooth er designet for å minke forstyrrelser fra andre enheter som også bruker 2.4GHz spektrumet. Ved å bruke adaptive frequency hopping(AFH) bytter den mellom 79 forskjellige frekvenser ved å endre frekvensen med 1MHz av gangen. Dermed er forbindelsen tilnærmet immun mot forstyrrelser.[3] Bluetooth kan brukes opp mot 100 meter, alt etter som hvilken klasse senderen har. Den deles opp i tre klasser, hvor klasse 1 radio har størst rekkevidde.[4] Bluetooth har en peakstrøm på 40mA.[5] Bluetooth Smart Bluetooth 4.0 Low Energy eller Bluetooth Smart, er en viderføring av Bluetooth protokollen. Den har lavere strømforbruk, mulighet til å kjøre i mange år på små battericeller, koster mindre å implementere og har en forbedret rekkevidde.[6] I forhold til Bluetooth har den en peakstrøm på 15mA[5] H15E01 6 2.1. TRÅDLØSE OVERFØRINGSPROTOKOLLER 2.1.2 iBeacon iBeacon er en teknologi utviklet av Apple[7], som ved hjelp av Bluetooth-protokollen, gir sendere muligheten til å informere iOS enheter at de befinner seg i nærheten. Et av bruksområdene for iBeacon er innendørs lokalisering, hvor smarttelefoner finner sin eksakte posisjon. Ved hjelp av en iBeacon kan det utvikles apper som responderer forskjellig alt ut fra hvor brukeren befinner seg. Hittil har bruksområdene til iBeacon hovedsakelig vært i butikker. Brukeren legger inn en app og får forskjellige beskjeder alt etter som vedkomne går inn eller ut av en butikk. Det kan være alt å gi beskjed om mulige tilbud i en gitt butikk, til å sende brukeren en takk for besøket når de forlater butikken.[8] Funksjoner IBeacon bruker Bluetooth Low Enegy (BLE)-teknologien. Senderne bruker denne teknologien til å sende en Universally Unique Identifier (UUID), som er den unike IDen til denne gitte iBeacon. Den sender også to verdier til som kalles Major og Minor. Beacons som deler samme verdi på en av identifikatorene danner en region.[9] Smartelefonen kan utføre forskjellige handlinger alt etter som den går inn eller ut av en region. Dette er innebygde funksjoner i beacondriverene på telefonen.Denne funksjonen kalles monitoring mode.[10] En iBeacon sender har tre forskjellige soner den opererer med i en region: Immediate (veldig nærme): Opptil 50cm unna. (0-0.5m) Near (nærme) Noen få meter unna (0.5-3m) Far (langt unna): Langt unna (3-70m) 14. juni 2015 KAPITTEL 2. TEORI Figur 2.1: Soner i en beacon region[11] Telefonen kan også avgjøre avstand til beacon. Den tar utgangspunkt i signalstyrken til Bluetooth signalet den mottar for å avgjøre dette. Denne funksjonen kalles ranging mode og er også en integrert del av ibeacon driverne.[11] Figur 2.2: Detektere bevegelse inn og ut av en region[11] Tekniske detaljer De forskjellige identifikatorene har følgende format:[12] UUID: Dette er en 16 byte streng. Den kan ha formen ”10D39AE7-020E-4467-9CB2DD36366F899D”. Det er også mulig å ha flere beacons med samme UUID. Disse danner en felles region Major: Dette er en 2 byte streng. Det betyr at Major verdien kan ha alle mulige verdier fra 0-65536. Alle beacons med samme Major danner en region. Minor: Denne er også en 2 byte streng slik som Major og fungerer på tilsvarende måte. H15E11 7 8 2.1. TRÅDLØSE OVERFØRINGSPROTOKOLLER Strømforbruk iBeacon bruker Bluetooth Smart og har dermed veldig lavt strømforbruk. Batteritiden på beacon enhetene vil avhenge av hvor ofte beacon sender ut signalene. Å tømme et et iPhone 5 batteri for strøm ved bare å bruke denne teknologien ville tatt et sted mellom 5 og 10 år.[13] Dermed stiller iBeacon enhetene sterkt når det kommer til battertid. Mobiltelefoner bruker også lite strøm på å scanne etter beacons. Strømforbruket avhenger av hvor ofte det scannes og hvor mange beacons som er i området. Ved å scanne hvert sekund ser forbruket ut slik på forskjellige telefoner: Figur 2.3: Strømforbruk ved scanning av beacons[14] Krav til bruk For å kunne ta imot beaconsignaler er minstekravene til mobiltelefoner dette: • iOS: Enheter med Bluetooth 4.0; iPhone 4S+, iPad (3 generasjon+), iPad Mini (1 generasjon+) • Android: Enheter med Android 4.3+ Windows Phone støtter ikke iBeacon ennå grunnet manglende støtte for Bluetooth LE, men er forventet å komme senere i 2015.[15] 14. juni 2015 KAPITTEL 2. TEORI 2.1.3 RFID RFID er en teknologi for å detektere objekter ved hjelp av radiosignaler. Den blir brukt for å holde orden på utstyr[16], eller for tidtaging i sportsbegivenheter[17]. RFID fungerer ved at den leser kode over en avstand. Teknologien er automatisert, og blir brukt for å identifisere personer, pakker eller et objekt.[18] For å gjøre dette bruker den RFID-tags. Tags-ene er små transpondere (radiomottaker og sender) som vil sende identiteten sin over en avstand når den blir forespurt om det[19]. For å kunne benytte seg av RFID-tags må man ha en RFID-leser. Noen tags kan bli lest fra et par meters avstand, mens andre kan leses fra flere hundre meters avstand.[20] De fleste RFID-tags inneholder minst to deler. Den ene delen er en integrert krets for å lagre og behandle informasjon, modulering og de-modulering[21] av et Radio Frekvens (RF)-signal, og andre spesialiserte funksjoner. Den andre er en antenne for å motta og sende signalet. [19] Det finnes to typer RFID-tags; aktive RFID-tags som inneholder batteri, og passive RFID-tags som ikke har noe batteri.[22] 2.1.4 WiFi WiFi er et merkenavn eid av Wi-Fi Alliance. WiFi bruker IEEE 802.11-standarden til å sende og motta informasjon mellom enheter. En WiFi enhet kan fungere hvor som helst i verden.[23] Det er mange typer WiFi standarder, noen av dem er bedre kjent som Wireless A, B, G, N. [24] Forskjellen mellom disse standardene er hvor lang avstanden kan være mellom tilkoblingspunktet og enheten for å opprette en forbindelse, og hastigheten på overføringen.[25] De fleste trådløse nettverk bruker to frekvensbånd. Det finnes flere, men disse to er mest brukt for den vanlige brukeren. Den ene opererer på 2.4GHz og den andre på 5GHz.[26] De fleste mobile enheter bruker 2.4GHz-båndet. Et problem er at andre produkter som mikrobølgeovn. Baby Call, og andre trådløse enheter også bruker 2.4GHz-båndet så det kan bli forstyrrelser. Ved å bruke 5GHz-båndet minker man rekkevidden, men får mindre forstyrrelser i signalene.[27] Det er også flere regler knyttet til hvordan man kan bruke båndet. 5GHz-båndet må bl.a. reduseres i sendestyrke, skal det brukes utendørs [28]. Fordi færre enheter også bruker 5GHz-båndet, er de også dyrere. H15E11 9 10 2.2. PROGRAMMERING 2.2 Programmering Programmering er når en har noe man vil gjøre og legger opp en oppskrift eller algoritme for å få det utført. Uten denne algoritmen er det ikke mulig å programmere noe. Programmet følger denne algoritmen og baserer seg på logikk. For å holde styr på logikken og alt som foregår i programmet, blir det brukt variable. Disse blir kalt datatyper og kan ha forskjellig størrelse. Størrelsen på de bestemmer hvor mye plass de tar i bit. [29] 2.2.1 Programmeringsspråk Det finnes egne språk for programmering. De er forskjellige i måten koden skrives inn i tekstform. Dette kalles syntaks. Når koden blir utført er det viktig at denne syntaksen er lik det som forventes av kompilatoren. Ellers vil man få en feilmelding og programmet vil ikke kjøres. Kompilatoren kjører koden.[30] 2.2.2 Utviklerverktøy For å utvikle programmer brukes utviklerverktøy. Det kan være en IDE (Integrated Development Environment) som Eclipse, Android Studio eller Netbeans. Felles for disse er at man kan utvikle programmer til forskjellige platform, og de inneholder alt man trenger av biblioteker man trenger til det aktuelle prosjektet. Blant annet finnes det moduler som gjør det mulig å logge hva som skjer i appen direkte til terminal. Logcat et eksempel på en slik logger, og den er integrert i Android Studio.[31] Det er mulig å gå fra ren kildekode til ferdig program i en IDE[32] 2.2.3 Åpen kildekode og bibliotek Åpen kildekode er kildekoder som ligger tilgjengelig for alle. Det kan være f.eks. prosjekter som drives av mange, hvor hvert bidrag er med på å forbedre prosjektet. Eller så kan kodesnutter som ligger fritt tilgjengelig på nett anses som åpen kildekode.[33] Bibliotek er en totalpakke med funksjoner og kode for å bistå en programmerer med å utvikle programmer. De kan være utvidelser eller funksjoner som kan være nyttige å importere. Et eksempel på et bibliotek er Altbeacon biblioteket, Android sitt iBeacon bibliotek.[34] 14. juni 2015 KAPITTEL 2. TEORI 2.3 Androidapplikasjoner En android appliksjon er en kodesnutt som er ferdig kompilert, og som har mulighet til å kjøre på android operativsystem. De er kodet i Javaprogramming:java og android operativsystemet er basert på linux. Hver installsjon av en app er knyttet opp mot en unik ID som blir generert i telefonen. 2.3.1 Hovedkomponentene i en app En android app har fire hovedkompontenter[35]: • Aktiviteter • Innholdsleverandør • Tjenester • Kringskasting mottakere En aktivitet er koder som kjører og vises på en enkelt side. Det kan være aktiviteter i en og samme app, og de har forskjellige funksjoner. En side som tar seg av innlogging til en tjeneste kan være en aktivitet, og når man har logget seg inn så får man en ny side, og dermed en ny aktivitet. En innholdslevarandør er ansvarlig sending og skriving av informasjon til en aktivitet. Den kan bruke funksjoner som SQL databaser for å holde orden på all data internt i appen. En tjeneste er når en del av appen kjører i bakgrunnen. Den trenger ikke et brukergrensesnitt. Kringkasting mottakere er komponenter i appen som responderer på det systemet har kringkastet. Det kan være være beskjeder om statusen på forskjellige andre funkskjoner i appen. Mottakerne har som oftest ikke noe grensesnitt, med unntak av notifikasjoner. [35] 2.3.2 Livssyklus En android applikasjon har forskjellige tilstander den kan være i. Tilstanden bestemmer hvordan flyten av programmet skal være, og hva som prioriteres høyet av operativsystemet. En app som ikke er i forgrunnen kan f.eks. bruke mindre datatrafikk eller strøm, enn om den hadde vært synlig på skjermen. H15E11 11 12 2.3. ANDROIDAPPLIKASJONER Created Applikasjonen er lagd, men er enda ikke synlig. Started Applikasjonene er i ferd med å bli vist, og er bare delvis synlig. Resumed Applikasjonen er fullt synlig, og kan samhandles med. Paused Applikasjonen er delvis synlig. Stopped Applikasjonen er ikke synlig, og kan enten startes om, eller bli ødelagt (Destroyed). Destroyed Applikasjonen er ikke lengre i minne. onCreate() Created onStart() Started onResume() onStart() Resumed onStop() Paused onRestart() Stopped onPause() Destroyed Figur 2.4: Livssyklus for aktiviteter Android 2.3.3 Brukergrensesnitt Et brukergrensesnitt er den grafiske fremstillingen av programmet, og gjør det mulig for brukeren å sende kommandoer og informasjon til appen, gjennom å klikke eller skrive inn i appen.[36] Alle de grafiske komponentene bruker klassen View og ViewGroup. Brukergrensesnittet er kodet i XML.[37] 14. juni 2015 KAPITTEL 2. TEORI 2.4 Server 2.4.1 LAMP Figur 2.5: LAMP LAMP er en software-pakke bestående av Linux Apache MySQL og PHP. Dette er en velkjent og vel fungerende løsning for web-servere. Linux er operativsystemet, Apache er web-serveren mySQL er databasebehandler og PHP er et skriptspråk som binder alt sammen. PHP har den fordelen at det kan kjøres innebygd i HTML-koder, noe som gjør at det fungerer veldig bra til å opprette dynamiske nettsider. [38] 2.4.2 MySQL MySQL er et datapråk for å skrive/lese/administrere databaser.[39] PHPMyAdmin PHPMyAdmin er et grafisk brukergrensesnitt for å skrive, lese og administrere databaser.[40] H15E11 13 14. juni 2015 15 Kapittel 3 Løsningsstrategi 3.1 Beskrivelse av totalsystemet For å kunne oppfylle kravene til systemet, ble det valgt å basere løsningen på en server og klientløsning. Klienten bruker en mobilapplikasjon, og serveren håndterer informasjonen sendt. For Wi-Fi og iBeacon løsninger var det ment at rundetiden skal kalkuleres, og sendes til server slik som vist på figuren. Serveren skal også kunne vise resultatene fra målingene på en ekstern skjerm. Figur 3.1: Flyt mellom enhetene ved Wi-FI/iBeacon løsning I en eventuell løsning med iBeacon ville det blitt fokusert på oppsett av server og mobilapplikasjon. De blå pilene viser informasjonsflyten ved en slik løsning. Den røde viser hvis det hadde blitt valgt en løsning som innebar bruk av Wi-Fi, i tillegg til de blå. For RFID løsninger ville flyten sett annerledes ut. Der ville mottakeren og serveren holde på rundetiden, og sendt informasjonen tilbake til bruker. H15E01 16 3.2. VALG AV TRÅDLØS TEKNOLOGI Figur 3.2: Flyt mellom enhetene ved RFID løsning 3.2 Valg av trådløs teknologi For å vurdere hvilken av de trådløse teknologiene løsningen skulle basere seg på, ble det laget tre tabeller med fordeler og ulemper ved hver teknologi: 3.2.1 RFID Fordeler: Ulemper: • Blir brukt som tidtakingsløsning i andre løp, det betyr at det er mulig å realisere en løsning. • Det er ingen krav til utstyr eller kunnskaper hos brukeren, det eneste de trenger å gjøre er å ha på seg en RFID tag. • Utvikling av systemet med RFID lesere og tags overstiger 5 000kr. • En administrator må knytte informasjonen rundt en tag til en enkelt bruker, og så legge dette inn i en database. • Når flere deltakere går over mållinjen på en gang kan det skape forstyrrelser for leseren. Noen resultater kan ende opp med å ikke bli oppfattet. Tabell 3.1: Fordeler / ulemper med RFID RFID ble vurdert til en god kandidat, men pris ble avgjørende for valg av løsning. En god RFID leser kan koste fra $1500 og oppover. Hver tag måtte ha vært aktive, og de hadde kostet minimum $5 pr stykk. Det ville også krevd at en person måtte skrevet inn 14. juni 2015 KAPITTEL 3. LØSNINGSSTRATEGI all informasjonen tilhørende hver tag og lagt de inn i en database. Det er også slik at det kunne vært mulighet for at RFID leseren ikke oppfattet hver enkelt tag om det var flere som krysset mållinjen på en gang. Denne unøyaktigheten og mulighet for feil hadde medført at man ville trengt flere lesere for å øke sikkerheten på avlesningene. Dette hadde da betydd at løsningen ville blitt enda dyrere. 3.2.2 Wi-Fi Fordeler: Ulemper: • «Alle» mobile enheter har WiFi. • Det kan lages mobilapplikasjoner som kan ta seg av registrering av bruker, samt holde orden på rundetider og antall runder i løpet. • Det finnes ikke mange produsenter som lager billige og enkle Wi-Fi løsninger til bruk i dette prosjektet. • Stor signalstyrke kan skape interferens om det blir brukt flere Wi-Fi sendere for å lage systemet. • Strømforbruket for Wi-Fi er høyere enn ved Bluetooth. Tabell 3.2: Fordeler / ulemper med Wi-Fi Wi-Fi var en god kandidat til valg av trådløs teknologi, men ble valgt bort grunnet høyt strømforbruk i forhold til iBeacon som bruker Bluetooth Smart. Videre er det også lite inititativ hos produsenter å utvikle billige enheter til bruk av lokalisering med Wi-Fi, i forhold til hva utviklingen og tilgjengeligheten er med iBeacon. 3.2.3 iBeacon iBeacon kom frem som den klart beste løsningen. Mest på grunn av pris, men også på grunn av at det var enklest å realisere denne løsningen. Siden brukeren kun trengte å laste ned en app, fylle inn navn og email, så ville alt foregå automatisk deretter. Utstyret koster bare $100 for tre beacon moduler. Ved å ha flere slike langs mållinjen, med flere meters avstand og på her side av banen, sikrer at hver bruker blir registrert. Siden hver beacon kan detektere når en bruker går inn og ut av en sone, kan det da utvikles en algoritme som ikke bare sikrer at en bruker har blitt registrert, men også kan regne ut rundetiden og gjennomsnittshastighet. En annen bekymring er også at brukeren kanskje har en gammel telefon. Pr 14.06.15 har ca. 51 prosent av alle telefoner Android 4.4 eller H15E11 17 18 3.2. VALG AV TRÅDLØS TEKNOLOGI høyere installert. Selv om denne statistikken kommer av at det også er mange brukere i fattige land som har gamle telefoner, så betyr det ikke at det ikke finnes brukere i Norge også som har gamle telefoner. For iOS brukere krever det at de har en 4S eller høyere. Men på en annen side så kommer alle de nyeste telefonene med støtte for Bluetooth Smart, så for en langsiktig løsning er dette ikke noe problem. Fordeler: • Teknologien er knyttet opp mot detektering av regioner og avstand til bruker • Det kan lages mobilapplikasjoner som kan ta seg av registrering av bruker, samt holde orden på rundetider og antall runder i løpet. • Utstyret er billig, og det finnes mange produsenter. • Produsenter har god dokumentasjon på hvordan utvikle apper til å fungere med iBeacon sendere. Ulemper: • Kan være vanskelig å få nøyaktig tidtaging når appen kjører i bakgrunnen, i stedet for å forgrunnen. • Krever at brukeren har telefon som støtter nyeste Bluetooth. Dette er telefoner med minst Android 4.3 eller iOS 7.1 og høyere. • Kan være vanskelig å få nøyaktig tidtaging når løpere går veldig fort på banen, hvis det blir brukt den innebygde avstandskalkulatoren i appen. • Det finnes hjelpeforum på nett for brukere som har problemer • Strømforbruket for Bluetooth er lavt. Tabell 3.3: Fordeler / ulemper med iBeacon En annen figur som også viser forskjellen mellom de tre teknologiene tilsier også at Beacon er et veldig godt valg til denne type løsning. Denne figuren er et utklipp av en annen større figur.[41] 14. juni 2015 KAPITTEL 3. LØSNINGSSTRATEGI Figur 3.3: Forskjellene mellom iBeacon, Wi-Fi og RFID 3.3 Valg av beacon For å realisere løsningen lette gruppen etter aktuelle leverandører av iBeacon moduler. Det ble lagt vekt på visse kriterier, hvor de viktigste står øverst: • Sender signaler veldig ofte • Tåler utendørs bruk • God batterilevetid • Har god rekkevidde • Har god støtte til utvikling av apper i form av dokumentasjon Figur 3.4: Model X dimensjoner Valget falt på Model X fra ROXMITY. Denne enheten dekket de viktigste kriteriene for en iBeacon modul. Den skilte seg ut fra de andre i form av at den var større, den H15E11 19 20 3.4. DEFINERING AV ET ENKELT REGION tålte utendørs bruk, den var kjapp, og hadde vanlige batterier i stedet for battericeller. Model X har følgende spesifikasjoner (tatt fra hjemmesiden): • Bluetooth® Smart / Bluetooth Low Energy • Ad rate: 100ms (iBeacon Certified) • Range: 60 meters / 200 feet • Battery life: Up to 5 years • Operating temp: -40 to +85 degrees Celsius • Indoor/outdoor: NEMA 3R enclosure • Security: Patent Pending ROXIMITY/iBeacon security • Made in US Senere var også en beacon fra Estimote tilgjengelig for testing og utvikling av systemet. Den var mindre, hadde dårligere batteri og mindre robust innpakning. Men den hadde mulighet til å konfigureres gjennom en app på mobilen. Der kunne man endre alt fra batterisinnstillinger, beacon UUID/Major/Minor til sendestyrke og sendefrekvens. Figur 3.6: Skjermbilde fra Estimote app Figur 3.5: Estimote beacon 3.4 Definering av et enkelt region Beacon fra ROXIMITY og Estimote hadde begge forskjellig UUID. Derfor var det mer hensiktsmessig å definere en region ut fra Major verdi og Minor verdi. For å gjøre det simpelt, så ble en region definert som alle beacon hvor Major var lik 12401. Denne verdien var identisk med en av Major verdiene fra ROXIMITY. Ved hjelp av Estimote sin app ble Major verdien på beacon endret til dette. Sammen dannet en beacon fra ROXIMITY og en beacon fra Estimote en region. 14. juni 2015 KAPITTEL 3. LØSNINGSSTRATEGI 3.5 Valg av utviklerverktøy For å utvikle appen ble det valgt å bruke Android Studio etter anbefaling fra produsenten av iBeacon enhetene. Det var også mulig å bruke Eclipse SDK, men stabiliteten og funksjonaliteten til appen ville vært noe dårligere. Produsenten hadde allerede lagt ut en SDK som kunne importeres inn i Android Studio, og dermed skulle det i teorien være rett frem å kompilere og bygge denne appen. Etter hvert skulle det også være mulig for å modifisere appen, til å bli mer kompleks etter ulike behov som måtte oppstå. For å forhindre å støte på problemer, ble det bestemt å lage appen så enkel som mulig, siden objektorientert programmering i Java og utvikling av mobilapplikasjoner, ikke er noe som har vært del av pensumet for elektrostudenter. Det ble ansett som viktigere å få noe til å fungere, enn å fokusere på kompleksitet når det kom til applikasjonen. 3.6 Bruk av åpen kildekode og bibliotek For å kunne realisere oppgaven på best mulig måte, og samtidig finne smarte løsninger å integrere i applikasjonen, ble det brukt eksempler på kildekoder tatt fra nett. Dette kom primært fra stackoverflow, som er kjent for å være nettstedet hvor brukere kan få hjelp til å feilsøke sin kode. Av bibliotek fantes det bare et fungerende bibliotek til å ta ibruk ibeacon. Dette var utviklet av Radius Networks, og er ment til å fungere som en standardisert løsning for kommunikasjon med alle beaconenheter. Hovedpersonen bak utviklingen, David G. Young, var også aktiv på stackoverflow for å hjelpe brukere som hadde problemer med applikasjonen. 3.7 Kalkulering av rundetid For å kalkulere rundetiden var det to mulige måter å gjøre dette på. Enten ved å bruke ranging mode, og ta utgangspunkt i avstand til hver beacon. Eller ved å ta utgangspunkt i monitoring mode, og se på når en bruker kommer inn eller går ut av en region. Valget falt på å bruke monitoring mode. Dette var fordi det ble ansett som mer responsivt å detektere når en bruker hadde Bluetooth signaler eller ikke, enn å måtte ta hensyn til kontinuerlige og feilfrie målinger uten signalforstyrrelse. H15E11 21 22 3.8. VALG AV HASTIGHET PÅ MOTTAKER OG SENDER Tanken bak tidsmålingen var å ta utgangspunkt i når en bruker forlot en region. Siden en region kan defineres som enten en beacon eller flere, så blir det lett å lage et felt som detekterer når brukeren kommer inn og går ut av den. Ved å sette en på hver side av mållinjen sikrer man overlapping og at brukeren er sikret å bli detektert av minst en beacon. På figuren har hver beacon en radius på 15 meter. Figur 3.7: Region Systemet loggfører når en bruker går ut av regionen, og så skjer det samme igjen ved neste gang en bruker går ut av regionen. Dermed har man rundetiden. 3.8 Valg av hastighet på mottaker og sender Beacon modulene har mulighet til å sende med opptil 10hz, altså med en periode 100ms. Siden mobilapplikasjonen kun trenger å motta ett signal for å vite at brukeren er inne i en region, så betyr det at brukeren ikke må gå forbi hele regionen på fortere enn sendeperioden. Hvis hver beacon har et felt med radius 15 meter slik som figuren over, så betyr det at det er maksimalt 30 meter for hver bruker å bli oppfattet av en beacon på. Ved å ta utgangspunkt i verdensrekorden på skøyter på 500meter, kommer man frem til en gjennomsnittshastighet på 15m/s. Dette betyr altså at den minimale frekvensen som man kan sende med er 0.5Hz. Dette er selvsagt grove overslagsberegninger, for i virkeligheten vil ikke disse regionene være akkurat 15 meter i radius, men de vil variere veldig. 14. juni 2015 KAPITTEL 3. LØSNINGSSTRATEGI Videre er det også slik at tester har vist at en enhet som scanner med 100ms intervaller kontinuerlig bruker 26 prosent strøm på 152 minutter.[42]. Derfor anbefales det heller å øke scanningsintervallet til 200ms for å spare strøm. Ved større felt kan denne perioden økes ytterligere. Senderne kan også stilles inn på 200ms. Sendefrekvensen avhenger av signalstyrken og feltet til hver beacon. Ved liten signalstyrke er det nødvendig med lav periode, og motsatt. 3.9 Valg av serverløsning Et av kriteriene til oppdragsgiver er at systemet skal kunne være mobilt, og enkelt kunne flyttes til begge banene de eier. Det er derfor valgt å bruke en Raspberry Pi 2 Model B i serverløsningen. Serveren skal også brukes til å vise data til brukere. Grensesnittet skal være så minimalt som mulig. Optimalt sett er det kun nødvendig for serveren å starte en nettleser som viser et lokalt grensesnitt. 3.9.1 Raspberry Pi “The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It is a capable little computer which can be used in electronics projects, and for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming.” —The Raspberry Pi Foundation Figur 3.8: Rapsberry Pi logo Raspberry Pi er en liten datamaskin, på størrelse med et kredittkort. Raspberry Pi er basert rundt Acorn RISC Machine (ARM)-arkitekturen. Den er utviklet av The Raspberry Pi Foundation. Raspberry Pi benytter i hovedsak Linux. Det finnes en utviklerutgave av Windows 10 til Raspberry Pi 2 Model B [43]. H15E11 23 24 3.9. VALG AV SERVERLØSNING Den offisielle linux-distribusjonen (distro-en) for Raspberry Pi er Raspbian; en Debianbasert distro. Det finnes utallige distro-er til Raspberry Pi å velge mellom. Flere av disse kan lastes ned fra den offisielle nettsiden til Raspberry Pi [44]. Det ble først utprøvd å lage en serverløsning med Raspian, men distro-en visste seg å være unødvendig oppblåst, med programmer man ikke har bruk for i vår implementering. Det er derfor valgt, for å holde systemet så lettvektig som mulig, en løsning med Arch Linux ARM. Fordelen med denne distro-en er at den er ekstremt lettvektig, og inneholder kun det aller nødvendigste for et Linux-system. Dette medfører også en ulempe med at systemet kommer fullstendig strippet for grafisk grensesnitt, og man selv må installere grafikk-driver, og et vindussystem. 3.9.2 Arch Linux ARM Figur 3.9: Arch Linux ARM logo Arch Linux ARM er en distro for datamskiner med ARM-prosessorer. De spesialiser seg på flere typer ARM-prosessorer, deriblant ARMv7 Hard Float, som Raspberry Pi benytter seg av [45]. Arch Linux ARM ble lastet ned og installert på Raspberry Pi i henhold til installasjonsveiledningen på Arch Linux ARMs hjemmesider [46]. Logget inn som bruker root med passord: root. 14. juni 2015 KAPITTEL 3. LØSNINGSSTRATEGI 3.10 Utstyrsliste Tabell 3.4: Utstyrsliste 3 1 1 1 H15E11 beacon fra ROXIMITY beacon fra Estimote Raspberry Pi HTC One m8 med Android versjon 5.0 25 14. juni 2015 27 Kapittel 4 Løsning For å løse denne oppgaven ble det fokusert på utvikling av mobilapplikasjon og oppsett av server med database. All kildekoden som er relevant for denne oppgaven ligger vedlagt og har blitt grundig kommentert. Figuren under viser de forskjellige enhetene i systemet. Figur 4.1: Totalsystemet 4.1 Mobilapplikasjon All kildekode og hele prosjektet er tilgjengelig på http://https://github.com/ arshadlol/BachelorAPP Mobilappen ble opprettet med to aktiviteter. De to aktivitetene er UserProfile og UpdateInfo. I UpdateInfo ble all registrering og omregistrering av brukere håndtert. I UserProfile ble lasting av drivere, vising av resultater, sending av resultater til server, og sletting av bruker utført. Det ble laget en kobling mellom de to aktivitetene, slik at en bruker kunne gå fra den ene til den andre. For å gjøre det enklere å holde orden H15E01 28 4.1. MOBILAPPLIKASJON på aktivitene. har det blitt valgt å kalle UserProfile for hovedsiden og UpdateInfo for registreringsskjemaet i resten av kapittelet. Når applikasjonen starter blir bruker sendt til hovedsiden. Så vil brukeren enten bli sendt til registreringsskjemaet automatisk, om brukeren ikke er registrert fra før. Eller så kan brukeren navigere seg til registreringsskjemaet ved å slette egen bruker, eller ved å omregistrere seg. 4.1.1 Registrering og sletting av bruker Når en bruker kjører appen for første gang, blir vedkomne bedt om å registrere seg. Dette skjer fordi det sjekkes om enhetens unike android ID er registrert i appen fra før. Dette ble gjort ved å bruke SharedPreferences klassen i Java, som gjør det mulig å lagre variabler selv etter at appen er lukket. Om IDen ikke eksisterer, så sendes bruker videre til registreringsskjemaet automatisk. Når brukeren registrerer er det seks felt som kan fylles ut. Det er fornavn, etternavn, alder, vekt, epost og kjønn. Alle bortsett fra vekt er obligatoriske å fylle ut. Brukeren får opp feilmelding om det er et av feltene som mangler. Om nok felt har blitt fylt ut kan registreringen sendes. Hvis det viser seg at en bruker allerede er registrert, så sendes vedkomne videre til hovedsiden med påfølgende melding om nettop dette. Hvis ikke får brukeren opp meldingen om at registreringen var vellykket. Om en bruker har lyst å slette seg selv, eller endre noen opplysninger om seg selv, er det også mulig å gjøre dette. Ved å trykke på menyknappen øverst på skjermen, så kommer disse to mulighetene opp. De tre prosessene blir kalt opp av tre forskjellige funksjoner, register(), update() og deleteUser(). I de tre prosessene er det lagt opp at alle felt skal sendes. Flytskjema for både registrering, omregistrering og sletting av bruker står beskrevet i vedlegg A og B. 4.1.2 Kommunikasjon med server For å kommunisere med serveren ble det brukt eksempler på koder fra stackoverflow. Dette fordi det var en kompleks og vanskelig oppgave å få til. Kodene ble tilpasset vårt behov med hensyn på parametre som skulle sendes. 14. juni 2015 KAPITTEL 4. LØSNING Når en bruker sendte informasjon til serveren, ble det sendt til egne PHP script som tok imot dette. Alle kommandoer som skal utføres på serveren dobbeltsjekkes opp mot den unike android ID’en som har blitt registrert for å forhindre at noe feil skjer. Når en operasjon blir utført på serversiden, så sender den tilbake et resultat til mobilapplikasjonen. Alt etter som hva resultatet er vet mobilen hva den skal gjøre videre. Om en registrasjon av bruker er vellykket, så sender den en utskrift til mobilen, og en annen hvis den feilet. 4.1.3 Bruk av drivere og funksjoner Det ble først bestemt å bruke produsentens utviklerverktøy, men etter hvert kom det frem at den manglet mulighet for å modifisere enkelte innstillinger, og kunne være til tider meget vanskelig å forstå. Derfor ble mobilapplikasjonen bygget fra bunn, og så ble altbeacon biblioteket lagt inn i prosjektet. Dette ble gjort ved å laste ned en fil, legge den i en mappe kalt libs, og så ble den filen inkludert i kompliatoren. Kodeopplisting 4.1: Inkludering av bibliotek i build.gradle dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat -v7:22.1.1' compile 'org.altbeacon:android-beacon-library:2+' } Det ble brukt eksempelprogram fra utvikleren til biblioteket i appen. Dette for å sikre at funksjonene fungerte som de skulle. Alt ble hentet fra https://altbeacon.github. io/android-beacon-library/ Dette biblioteket hadde innebgyde funksjoner som kunne håndtere avstandsmåling i ranging mode, og om brukeren gikk inn eller ut av en region i monitoring mode. Av disse var kun monitoring mode relevant til selve løsningen, men ranging mode var nødvendig for å kunne lese ut informasjon om hver beacon. Dette var på grunn av måten biblioteket var bygget opp på fra utviklernes side. Det er mulig å ha flere regioner å overvåke samtidig. De blir lagt under hverandre slik som vist her: Kodeopplisting 4.2: Definere hvilke regioner som skal overvåkes try { beaconManager.startMonitoringBeaconsInRegion(region1); beaconManager.startMonitoringBeaconsInRegion(region2); } H15E11 29 30 4.1. MOBILAPPLIKASJON Hvor hver enkelt region ble deklarert øverst i programmet. Feltene UUID, Major og Minor kan velges til de verdiene som vi ønsker å definere hvert region til. Kodeopplisting 4.3: Definering av hvert region Region region1 = new Region("UniktNavnForRegion", UUID, Major, Minor); Region region2 = new Region("UniktNavnForRegion", UUID, Major, Minor) 4.1.4 Rundetelling og tidtaking For å måle antall runder og rundetid ble det tatt ibruk monitoring region funksjonen. Når en bruker forlater en region blir det gjort en timestamp. Neste gang en bruker forlater den samme regionen blir det gjort en ny timestamp. Ved å ta differansen har man rundetiden. Siden Android driveren sier ifra 10 sekunder etter at en bruker har forlatt en region, så ble dette tatt hensyn til i beregningene. For å forhindre at appen telte feil rundetid og antall runder, ble det laget en start og stopp knapp. Tanken var at en bruker kunne trykke på start knappen når vedkomne stod på mållinjen, og dermed ville systemet begynne å telle antall runder. Ved første utgang av region ville det bli tatt en timestamp. Hvis det viste seg at differansen mellom den nye og den gamle var mindre enn 30 sekunder, ville rundetellingen forkastes. Det ble også lagret en variabel som holdt orden på beste rundetid. Når rundetiden, antall runder og beste rundetid var blitt registrert i appen, ble den sendt til server for å lagre i databasen. Hvis det viste seg at appen sender feil rundetall til serveren, så er det innebygd en korrigerende algoritme for å sikre at rundetiden ikke går tapt. Slik vil alle oppføringer lagres i databasen om brukeren har trykket på startknappen. Flytskjema for sending av rundetid og rundetelling står beskrevet i vedlegg C. 4.1.5 Brukergrensesnitt og varsler For hver aktivitet ble det utviklet to forskjellige grafiske brukergrensesnitt. Disse ble laget så enkle som mulig, og design var ikke prioritet for denne løsningen. I registreringsskjemaet var det tre felt hvor brukeren kunne fylle inn tekst. Dette er fornavn, etternavn og epostfeltet. I feltene fødselsdato og vekt får brukeren mulighet til å fylle inn tall. Forskjellen mellom de første tre feltene som ble nevnt og de to siste, 14. juni 2015 KAPITTEL 4. LØSNING er at brukeren får opp tall som input metode, istedet for et fullstendig tastatur. Hvis et av feltene mangler eller er fylt inn feil,får brukeren en feilmelding i det feltet det gjelder. Hvis eposten er på feil format eller mangler får brukeren beskjed om dette. Ved registrering av fødselsdato får brukeren feilmelding om f.eks. årstallet er høyere enn nåværende årstall, eller hvis vedkomne skriver at de er født på 1800 tallet. Videre får også brukeren beskjed om feil i fødselsdato om måneden eller dagen er feil. For å velge kjønn ble det lagt ved to knapper hvor det kun var mulig å velge ett kjønn av gangen. Om kjønn ikke ble valgt fikk brukeren en feilmelding På de nyeste android telefoner er det også en tilbakeknapp nederst på skjermen. Denne har blitt deaktivert i registreringsskjema aktivteten. Hvis brukeren har lyst å avbryte registreringen finnes det en knapp øverst på skjermen og en nederst hvor det står avbryt. I hovedsiden ser man øverst en velkomstmelding med navnet til brukeren. Det er også to knapper hvor brukeren kunne starte og stoppe tidtakingen. Om tidtakingen var startet eller stoppet vises også på skjermen. Øverst er det mulighet til å få opp en meny øverst til høyre hvor brukeren har mulighet til å slette seg selv, eller å omregistrere seg for å oppdatere informasjon. Om brukeren velger å slette seg selv, så blir de sendt til registreringsskjemaet automatisk. Det skal ikke være mulig å komme til hovedsiden uten å være registrert. Figur 4.2: Registreringsskjemaet Figur 4.3: Hovedsiden 4.1.6 Varsler Når en bruker starter appen så kjøres det også en sjekk om Bluetooth er på, og om enheten har støtte for Bluetooth LE. Denne testen var tatt rett fra et eksempelprogram fra utgiveren av beacon biblioteket. Hvis ikke brukeren har skrudd på Bluetooth H15E11 31 32 4.1. MOBILAPPLIKASJON kommer det opp en dialogboks som ber om tillatelse om å skru den på. Figur 4.4: Bluetooth tillatelse Figur 4.5: Skrur på bluetooth Ved rundepasseringer får brukeren opp en notifikasjon. Denne viser beste rundetid og antall runder brukeren har gått. Notifikasjonen vises også når skjermen er låst, slik at det er mulig å se resultatet uten å måtte låse opp mobilen. Figur 4.6: Notifikasjon fra låst skjerm Figur 4.7: Notifikasjon i statusfeltet Under registrasjonen kommer det opp en dialogboks som viser at systemet jobber, og ber brukeren vente. Denne lukker seg selv når registreringen er vellykket. Velger en bruker å slette seg selv kommer det opp en boks som spør om bekreftelse. Figur 4.8: Holder på å registrere bruker Figur 4.9: Bekreft at bruker skal slettes 14. juni 2015 KAPITTEL 4. LØSNING Etter hvert av disse bekreftelsene kommer det opp en midlertidig beskjed på skjermen som forteller brukeren hva som nettopp har skjedd. Ved registrering, omregistrering og sletting kommer det opp en beskjed nederst på skjermen som beskriver nettopp dette. Eventuelle feilmeldinger kommer også opp der. 4.1.7 Sikkerhet Når det kommer til sikkerhet er den eneste sikkerheten i applikasjonen bruk av Android ID. Denne skal brukes i all kommunikasjon med server. Selve kommunikasjonen med serveren er ukryptert, og for en datakyndig person er det lett å finne ut hva de forskjellige parametrene er. ved å overvåke kommunikasjonen ut av en mobil. Dermed er det også et stort potensielt sikkerhetshull i systemet. Men dette er noe som ikke har blitt lagt vekt på å finne ut av i løsningen. 4.1.8 Justering av innstillinger I appen er det kun fem ting som kan justeres på. • Foreground scan period • Foreground between scan period • Background scan period • Background between scan period • SetBeaconParser Foreground scan period er definert som hvor ofte den skal søke etter nye beacon signaler når appen er aktiv på skjermen. Foreground between scan period er definert som tiden mellom hver gang den skal kjøre en scan period. Så en scan period på 100ms og en between scan period på 100ms gir kun mulighet til å få inn signaler i 100 av de 200ms. Det samme prinsippet gjelder for background scan period og background between scan period. Den eneste forskjellen er at appen kjører i bakgrunnen eller at skjermen er låst. SetBeaconParser definerer formatet på UUID som blir sendt fra beacon. Kodeopplisting 4.4: Utklipp av setBeaconVariables klassen beaconManager.setForegroundScanPeriod(FScanPeriod); beaconManager.setForegroundBetweenScanPeriod(FScanBetweenPeriod); beaconManager.setBackgroundScanPeriod(BScanPeriod); H15E11 33 34 4.2. SERVER beaconManager.setBackgroundBetweenScanPeriod(BScanBetweenPeriod); if (!checkBound) { beaconManager.getBeaconParsers().add(new BeaconParser(). setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")); } De forskjellige verdiene kan lett stilles på øverst i koden. Kodeopplisting 4.5: Initialisering av verdier Long FScanPeriod = 100L; Long FScanBetweenPeriod = 0L; Long BScanPeriod = 100L; Long BScanBetweenPeriod = 0L; 4.2 Server 4.2.1 Oppsett av server Serveren er en apache-server som er satt opp med mySQL og PHP-støtte. 4.2.2 Oppsett av nettkiosk Som nevnt i avsnitt 3.9.1 på side 23; er det fordelaktig at systemet kun starter en nettleser som viser en lokal nettside. I dette oppsettet benyttes Firefox-nettleser med R-Kiosk-tillegg. I prosessen ble det utprøvd å kun starte Firefox, men dette viste seg å være problematisk. Årsaken til dette er nødvendigheten av å presisere hvilken oppløsning den skal starte i, og at man på forhånd ikke vet hvilken oppløsning monitor har. Løsningen ble å starte Firefox gjennom en vindusbehandler som automatisk finner ut nødvendig oppløsning. Matchbox Window Manager er en lettvektig vindusbehandler for Xorg (X)-vindussystem [47]. Denne vindusbehandleren ble benyttet. For å starte Firefox med den oppsatte brukeren pi, trengs en innloggingsbehandler som logger inn brukeren og starter Matchbox og Firefox. På grunn av dens lettvektighet, falt valget på Slim. Hele installasjonsprossesen er automatiser gjennon et Bash-skript som kan lastes ned og kjøres. Se kodeopplisting J.1 på side XLIII. 14. juni 2015 KAPITTEL 4. LØSNING For å gjøre jobben med å konfigure serveren lettere, installerer skriptet Bonjour og Samba i tillegg. Dette muliggjør og montere filer fra serveren på egen maskin, samt å kunne bruke adressen alarmpi.local istedenfor for å lete opp, og bruke IP-adressen til Raspberry Pi. Det er ønskelig å kunne se endringen man har gjort i index.html umiddelbart. Ved å legge innholdet i kodeopplisting 4.6 øverst i index.html, kan man få til nettopp dette. Kodeopplisting 4.6: Automatisk oppdatering av nettside med live.js <html> <head> <script type="text/javascript" src="http://livejs.com/live.js"></ script> ... </head> <body> ... 4.2.3 Oppsett av database Databasen er satt opp med to tabeller: users og Rundeteller. users er brukertabellen. Denne inneholder personinformasjon som for eksempel navn og fødselsdag. Rundeteller er tabellen som holder holder styr på hvor mange runder enhver deltaker har gått. Brukertabellen inneholder et unikt felt (androidID) som vist i figur 4.10 på neste side. Denne ID-en er hentet fra mobiltelefonen, og er en unik ID alle androidtelefoner har. Dette gjør at tabellen kun tillater én oppføring med samme ID. Noe som igjen gjør at det ikke er nødvendig for mobilapplikasjonen å sjekke om bruker allerede eksisterer, før den oppretter en. Siden androidID er unik i brukertabellen, er det hensiktmessig å bruke den som link mellom de to oprettede tabellene. 4.2.4 Registrering og sletting av bruker Det er kun mulig å registrere bruker via mobiltelefonen. Ved sletting kan dette gjøres enten via mobiltelefon, eller gjennom webgrensesnittet på http://baastadIL. H15E11 35 36 4.2. SERVER users Rundeteller name ID (unik) lastname rounds age time gender besttime birthday androidID email androidID (unik) Figur 4.10: Database local/admin.php. Adressen forutsetter at server og enheten som kobler seg opp, er i samme nettverk. 4.2.5 Registrering av rundetid Når en bruker sender rundetiden til en server, så sendes i følgende format: Serveren leser ut denne informasjonen. Hvis et av feltene er tomme, så dør scriptet på serversiden, og en respons blir sendt tilbake. og kjører en SQL setning på databasen for å lagre resultatene i riktig tabell. Den utgangspunkt i android ID som blir sendt og samtidig rundetallet. Deretter prøver serveren å kjøre SQL setningen. Om setningen ikke lar seg fullføre, så sender serveren tilbake en respons til mobilappen. 4.2.6 Visning av resultater Resultatet ved hver passering blir vist på skjermen som er koblet til serveren. Denne er linket til http://localhost. 14. juni 2015 37 Kapittel 5 Testing Alle tester ble gjort med følgende utstyr eller programvare: • Beacon fra Estimote • Beacon fra ROXIMITY • HTC one m8 med Android 5.0 • Logcat fra Android Studio med mobilen tilkoblet Når det kom til innstillinger av de forskjellige komponentene, så ble følgende brukt: • Sendefrekvens på beaconsignaler: 10hz • Sendestyrke på Estimote beacon: -30dBm (omtrent 1.5 meters radius) • Major verdi til Estimote beacon satt til 11070 • Perioden for hver scanning i for og bakgrunnen på app: 100ms • Perioden mellom hver scanning på app: 0ms Testbrukeren som skulle bruke dette systemet hadde følgende personalia: • Fornavn: Arne • Etternavn: Johansen • Fødselsdato: 01/01/1985 • Epost: arne@johansen.no Koden på mobilappen fungerte som det skulle, men det var problemer med strengkonverteringen på serverside. Derfor kommer epost til å ikke syns i databaseoppføringer. Den er nevnt her kun for å vise feilmeldinger ved registrering på mobilappen. H15E01 38 5.1. REGISTRERING OG SLETTING AV BRUKER 5.1 Registrering og sletting av bruker Først ble det forsøkt å åpne appen for første gang etter installasjon. Som forventet ble brukeren henvist til registreringsskjemaet, med påfølgende varsel: Figur 5.1: Automatisk åpning av registreringskjema Deretter ble informasjonen fylt ut korrekt og det ble forsøkt å registrere seg. Hvis brukeren ikke var registrert fra før, ville det komme en melding om at bruker har blitt opprettet nederst på skjermen. Figur 5.2: Beskjed om at bruker har blitt opprettet Dette ble sjekket opp databasen at Arne befant seg der. Merk den unike android IDen. 14. juni 2015 KAPITTEL 5. TESTING Figur 5.3: Databaseoppføring for bruker Så ble appen avinstallert og det ble forsøkt å gjenta installasjon og registrering på nytt. For å sjekke at brukeren faktisk har blitt registrert ble også databasen sjekket for oppføringer. Figur 5.4: Beskjed om at bruker allerede finnes Etter dette ble det gjort et forsøk på å endre personopplysninger. Tanken var at Arnes tvillingsøster Anne skal kunne bruke mobilen til samme formål. Dette ble også sjekket opp mot databasen. Figur 5.5: Brukeropplysninger har blitt endret Dette ble sjekket opp mot databasen også for å se endringene. Merk at android IDen er den samme, men at fornavnet har endret seg opp oppføringen. H15E11 39 40 5.1. REGISTRERING OG SLETTING AV BRUKER Figur 5.6: Databaseoppføring med endringer Tilslutt ble det forsøkt å slette Anne fra databasen. Figur 5.7: Bekreftelse på at bruker har blitt slettet Det ble gjort forsøk på å fylle inn skjemaet feil. Om et av feltene mangler så får man følgende feilmeldinger. Disse står oppført i figuren på neste side. 14. juni 2015 KAPITTEL 5. TESTING (a) Fornavn (b) Etternavn (c) Dag (d) Måned (e) Årstall (f) Årstall (g) Epost (b) Kjønn Figur 5.8: Diverse feilmeldinger 5.2 Detektering av beacons For å teste at programmet klarte å detektere hver beacon og skille mellom de, ble hele regionen definert som alle beacons med Major verdi lik 11070. Det var ikke gitt noe dokumentasjon på at Major verdien på ROXIMITY beacons endrer seg med regelmessige tidspunkt. Sist det ble testet var verdien 12401. Derfor ble Estimote beacon oppdatert med den nye Major verdien. Ved å kjøre en utskrift på skjerm kunne man se de forskjellige UUID fra begge beacon. H15E11 41 42 5.3. REGISTRERING AV RUNDETID Figur 5.9: Appen ser en region med to forskjellige beacons Hyppigheten på hvor ofte signaler ble registrert ble også målt. En tilnærmet optimal registrering står vist under. Men det kunne også hende at det kun ble registrert fire målinger pr sekund på det minste. Figur 5.10: Antall kringkastinger mottat på rundt ett sekund 5.3 Registrering av rundetid Det ble gjort en test med å først trykke på start knappen i hovedsiden, og dermed skru av bluetooth manuelt. Etter at loggen viste at beacon ikke lenger var i region, ble den skrudd på og deretter gjentatt til rundetid ble registert. Det ble også gjort slik at feil antall runder skulle sendes fra appen. Figur 5.11: Runderegisterring med påfølgende korrigering Som loggen viser så blir det registrert at det er blitt sendt feil antall runder, og så prøver appen på nytt å sende resultatene, men med det riktige antallet runder. Ved å se på tiden mellom første gang brukeren går ut av en sone til neste gang det registreres, og deretter trekker ifra 10 sekunder, så ser man at rundetiden blir kalkulert riktig også. Dette blir også registrert i databasen på riktig måte. 14. juni 2015 KAPITTEL 5. TESTING Figur 5.12: Databaseoppføring med korrigert rundetall Det sendes også en notifikasjon i statusfeltet hvor det står rundetiden og hvor mange runder vedkomne har gått: Figur 5.13: Opptil ni målinger pr sekund Om en bruker ikke var registrert i det hele tatt, så ble dette oppdaget av systemet når rundetiden ble sendt. Det ble ikke lagt inn noe varsler utenom en oppføring i loggen som gjorde bruker oppmerksom på dette. Dette er kun for å illustrere at bruker ikke fantes i databasen. Figur 5.14: Ingen bruker registrert i tabellen ved passering Det ble også gjort en test om rundetiden ble registrert om stoppknappen var trykket inn. H15E11 43 44 5.4. STABILITET OG SIKKERHET Figur 5.15: Stopp rundetelling 5.4 Stabilitet og sikkerhet Når det kommer til stabilitet har appen blitt testet på to forskjellige mobiler, og den har vært stabil på begge. Appen har kræsjet når den kke får koblet seg opp mot server. Det ble ikke lagt mer vekt på å forhindre at denne kræsjen kunne forebygges. Figur 5.16: Feil ved tilkobling til server Appen hadde også en sårbarhet i at bluetooth driveren kræsjet. Utvikleren av altbeacon driveren har laget en innebygd funksjon som restarter bluetooth driveren om den stopper. Denne prosessen tar ca. 6 sekunder. Figur 5.17: Bluetoothkræsj Hyppigheten av denne kræsjen er usikker, men på tre timer skjedde det totalt fire kræsj. De fire kræsjene er ikke ført opp i kronologisk rekkefølge. Figur 5.18: Antallet bluetoothkræsj på 4 timer 14. juni 2015 45 Kapittel 6 Diskusjon Ved registrering av bruker og sletting fungerte det meste slik det skulle. De små feilene som oppstod var på serversiden, og dette skyldes feil i konvertering av strengene som ble mottatt. Derfor ble de heller ikke tatt med i dokumentasjonen. Det skulle gjerne utbedres, men tiden var knapp. Det samme gjelder også registrering av bestetid og rundetid. Ved sending av bestetid ble variabelen lagret som et heltall, mens rundetiden ble lagret med to siffers nøyaktighet. Det er også mulig å utvide antallet parametre som blir sendt til server. Feilmeldingene fungerte også slik som de skulle, sammen med alle andre varsler brukeren fikk. Etter hvert er det også mulig å gjøre brukergrensesnittet bedre, og ha bedre varsler. Detektering av beacons fungerte slik det skulle, og defineringen av et region med flere beacons var også mulig å få til. Et problem var at beacons fra ROXIMITY krevde at appen kjørte på deres platform. Dette var fordi UUID til beacon endret seg med faste intervaller, og da måtte man ha en spesiell kode å sette inn i programmet for at beacon skulle bli gjenkjennelig. Estimote sin beacon hadde derimot en verdi alt etter som man satte den. Etter å ha jobbet med både ROXIMITY og Estimote viste det seg at Estimote helt klart hadde vært den beste løsningen til fremtidig bruk. De er åpne og har større fleksibilitet. De har bedre brukerstøtte for utvikling av apper. ROXIMITY hadde fordelen i at beacon de produserte var mer robuste og hadde veldig god batteritid. Men det viste seg det at disse to kriteriene ikke var så viktige, siden det hadde vært enklere å erstatte en Estimote beacon som er ødelagt, ved å logge seg inn på den nye og endre innstillingene til å likne den gamle. De var responsive og fra testingen kan man se at 100ms periode på sender og mottaker er godt nok. Det er mulig å øke denne perioden, men for treningsformål og trimløp blir det ikke sett på som nødvendig. Et forbedringspotensiale hadde vært å utvidet H15E01 46 appen til å automatisk øke eller minke perioden på beacons. Når en bruker trenger god responsivitet kunne man sendt denne beskjeden til beacons, og når en bruker drar hjem for dagen, settes perioden til maksverdi. Rundetellingen fungerte slik den skulle om startknappen ble trykket inn, og sendte rundetiden slik den skulle til serveren. Om antallet runder registrert på mobilen var feil, så ble den automatisk korrigert av server. Om bruker ikke fantes i serveren ble det dette sendt tilbake som en respons til appen. I løsningen derimot gjør ikke appen noe videre med denne responsen. Dette skyldes at det ikke var tid til å lage noen tilleggsfunksjoner som håndterte dette. Om man ville stoppe rundetellingen fungerte stoppknappen slik som forventet. Når det kommer til stabilitet så holdt systemet seg ganske stabilt. Kræsj av bluetooth kan forekomme, men den restarter seg selv som oftest innen 6 sekunder. Hyppigheten i testene viste også at forekomsten var relativt lav. Dette betyr at en eventuell bluetooth crash ikke bør anses som noe stor trussel på selve systemet. Det verste som kan skje er at bluetooth kræsjer når bruker nærmer seg mållinjen, og dermed blir en runde ikke registert. En mulig løsning på dette kan være å anta en kræsj, om neste registrerte rundetid er omtrent to ganger gjennomsnittet av rundetidene. Og dermed korrigere forrige rundepassering og føre den inn i tabellen. Det at appen kræsjer når den ikke får opprettet forbindelse ble det ikke gjort noen forsøk på å utbedre. Dette ble for teknisk og tidkrevende, og at gruppen ikke så på det som noe stor prioritet. For videre utvikling av systemet er det mulig å få på plass ting som: • Utvikle appen på nytt med Estimote utviklerverktøy • Utvikle appen for iOS enheter • Integrere database i applikasjonen for å holde på resultater • Mulighet for å vise resultater bedre på mobil • Få til bedre kommunikasjon med server med hensyn på sikkerhet • Jobbe med å bygge en prototype, og gjøre målinger for å bestemme nøyaktig feltstyrke på region. • Utvikle forskjellige strømprofiler for mobil og beacons integrert i appen. • Få til visning av gjennomsnittshastighet og forbedre siden for visning av resultater. • Få til muligheten å sende epost med resultatene fra løp til bruker • Skrive brukermanual og teknisk brukermanual til systemet 14. juni 2015 47 Kapittel 7 Konklusjon Det er mulig å konstruere en tidtagerløsning ved hjelp av iBeacon teknologien. iBeacon egner seg best til denne type løsning på grunn av pris, tilgjengelighet på utstyr og strømforbruk. Nøyaktigheten i målingene er ukjent, men systemet er responsivt nok til å kunne jobbes videre med. Utvikling av app er heller ikke noe problem. Det viser seg at alt som trengs av utviklerverktøy og bibliotek er gratis. Det er videre også mulighet til å utvide applikasjonen til å ha flere funksjoner alt ettersom behovene oppstår. Systemet har også mulighet for enkel vedlikehold. En enkelt enhet kan lett byttes ut ved feil og erstattes med en annen, uten at det vil medføre mye jobb i programmering av app. Hver bruker har mulighet til å registrere seg, og de vil automatisk bli lagret i en database. Dette minker arbeidet personalet ved de forskjellige løpene har ved å holde styr på hver løper. Det er videre også mulig å vise resultatene til hver enkelt på storskjerm. H15E01 14. juni 2015 49 Referanser [1] I. S. UNION, Special regulations & technical rules speed skating and short track speed sk ating 2014, 2014. side: http://www.skoyteforbundet.no/ hurtiglop/Lover%20og%20bestemmelser/ISU%20konkurranseregler% 20hurtigl%C3%83%C2%B8p.pdf (sjekket 11.06.2015). [2] The Institute of Electrical and Electronics Engineers, Inc. (2015). IEEE 802.15 WPAN task group 1 (TG1), side: http://www.ieee802.org/15/pub/TG1. html (sjekket 09.06.2015). [3] Bluetooth SIG. (2005). A look at the basics of bluetooth technology, side: http: //www.bluetooth.com/Pages/Basics.aspx (sjekket 13.06.2015). [4] Joshua Wright. (2015). Dispelling common bluetooth misconceptions, side: http : / / www . sans . edu / research / security - laboratory / article / bluetooth (sjekket 13.06.2015). [5] Panasonic. (2014). Moving forward with bluetooth® low energy, side: http : / / www . digikey . no / en / articles / techzone / 2014 / aug / moving forward-with-bluetooth-low-energy%20PEAK%20STR%C3%98M (sjekket 13.06.2015). [6] Bluetooth SIG. (2015). The low energy technology behind bluetooth smart, side: http : / / www . bluetooth . com / Pages / low - energy - tech - info . aspx (sjekket 13.06.2015). [7] Pocket-lint. (2013). Apple’s ibeacons explained: what it is and why it matters, side: http://www.pocket-lint.com/news/123730-apple-s-ibeaconsexplained-what-it-is-and-why-it-matters (sjekket 20.05.2015). [8] A. Cavallini, «iBeacons bible 2.0,» Gaia-Matrix, juni 2014. side: https : / / meetingofideas.files.wordpress.com/2014/06/ibeacon-bible-20.pdf (sjekket 01.05.2015). [9] Estimote. (2015). What is a beacon region? Side: https : / / community . estimote.com/hc/en- us/articles/203776266-What-is-a-beaconregion- (sjekket 13.06.2015). [10] Apple. (2014). Region monitoring and ibeacon, side: https : / / developer . apple . com / library / mac / documentation / UserExperience / H15E01 50 REFERANSER Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring. html (sjekket 13.06.2015). [11] Estimote. (2015). What are region monitoring and ranging? Side: https : / / community.estimote.com/hc/en-us/articles/203356607-What-areregion-Monitoring-and-Ranging- (sjekket 13.06.2015). [12] iBeaconInsider. (2015). What is ibeacon? a guide to beacons, side: http : / / www.ibeacon.com/what- is- ibeacon- a- guide- to- beacons/ (sjekket 13.06.2015). [13] Aislelabs. (2014). What is bluetooth low energy? Side: http : / / www . aislelabs.com/blog/2014/06/06/what-is-bluetooth-low-energy/ (sjekket 13.06.2015). [14] ——, (2014). Ibeacon battery drain on apple vs android: a technical report, side: http : / / www . aislelabs . com / reports / ibeacon - battery - drain iphones/ (sjekket 13.06.2015). [15] David G. Young. (2014). Ibeacon support for windows phone devices, side: http://stackoverflow.com/questions/26229765/ibeacon-supportfor-windows-phone-devices (sjekket 13.06.2015). [16] Technovelgy.com. (). What can rfid be used for? Side: http : / / www . technovelgy . com / ct / Technology - Article . asp ? ArtNum = 4 (sjekket 13.06.2015). [17] RFID im Blick. (2013). Without rfid technology time measurement at running events would be impossible, side: http : / / www . rfid - im - blick . de / en/201308191407/ohne- die- rfid- technologie- ist- heute- einezeitmessung - bei - grossen - laufevents - nicht - moeglich . html (sjekket 13.06.2015). [18] Kevin Bonsor, Wesley Fenlon. (2015). How rfid works, side: http : / / electronics . howstuffworks . com / gadgets / high - tech - gadgets / rfid.htm (sjekket 13.06.2015). [19] ——, (2015). How rfid works, side: http://electronics.howstuffworks. com/gadgets/high-tech-gadgets/rfid2.htm (sjekket 13.06.2015). [20] Mark Roberti. (2014). What is an rfid reader’s maximum range? Side: http : / / www . rfidjournal . com / blogs / experts / entry ? 10918 (sjekket 13.06.2015). [21] M. Böhm, A System Study for RFID: Transponders Based on Polymer Semiconductors, 1. utg. Germany: Cuvillier, E, 2007. [22] Kevin Bonsor, Wesley Fenlon. (2015). How rfid works, side: http : / / electronics . howstuffworks . com / gadgets / high - tech - gadgets / rfid3.htm (sjekket 13.06.2015). 14. juni 2015 REFERANSER [23] V. Beal. (2015). What is wifi, side: http://www.webopedia.com/TERM/W/ Wi_Fi_Alliance.html (sjekket 14.05.2015). [24] Matt Smith. (2011). Understanding the common wifi standards [technology explained], side: http : / / www . makeuseof . com / tag / understanding common-wifi-standards-technology-explained/ (sjekket 13.06.2015). [25] Homenetworkadmin. (2015). Wireless b vs g vs n vs ac | what is the difference? Side: http://homenetworkadmin.com/wireless-b-vs-g-vs-n-vs-acdifference/ (sjekket 13.06.2015). [26] Glenn Fleishman. (2009). Understanding wi-fi’s two spectrum bands, side: http : / / www . pcworld . com / article / 165240 / article . html (sjekket 13.06.2015). [27] Joe Levi. (2014). Here’s why you should use 5ghz wifi instead of 2.4ghz, side: http://pocketnow.com/2014/01/23/5ghz-wifi (sjekket 13.06.2015). [28] Fribruksforskriften, Forskrift om generelle tillatelser til bruk av frekvenser (fribruksforskriften), 2012. side: https : / / lovdata . no / dokument / SF / forskrift / 2012 - 01 - 19 - 77 / KAPITTEL _ 4 # %C3 % 82 % C2 % A711 (sjekket 10.06.2015). [29] Brad Miller. (2014). What is programming? Side: http://interactivepython. org/courselib/static/pythonds/Introduction/WhatIsProgramming. html (sjekket 13.06.2015). [30] Margaret Rouse. (2010). Definition: compiler, side: http : / / whatis . techtarget.com/definition/compiler (sjekket 13.06.2015). [31] Android. (2015). Debugging with android studio, side: https://developer. android . com / tools / debugging / debugging - studio . html (sjekket 13.06.2015). [32] Jennifer Kyrnin. (2015). What is an ide and do you need an ide to build web applications? Side: http://webdesign.about.com/od/webprogramming/ a/what-is-an-ide.htm (sjekket 13.06.2015). [33] Opensource.com. (2015). What is open source? Side: http : / / opensource . com/resources/what-open-source (sjekket 13.06.2015). [34] Cory Janssen. (2015). Software library, side: http : / / opensource . com / resources/what-open-source (sjekket 13.06.2015). [35] Android. (2015). Application fundamentals, side: http : / / developer . android . com / guide / components / fundamentals . html (sjekket 13.06.2015). [36] ——, (2015). User interface, side: https : / / developer . android . com / guide/topics/ui/index.htm (sjekket 13.06.2015). H15E11 51 52 REFERANSER [37] ——, (2015). Ui overview, side: https : / / developer . android . com / guide/topics/ui/overview.html (sjekket 13.06.2015). [38] E. Rosebrock og E. Filson, Setting up LAMP: getting Linux, Apache, MySQL, and PHP working together. John Wiley & Sons, 2006. [39] Android. (2015). What is mysql? Side: https : / / www . siteground . com / tutorials/php-mysql/mysql.htm (sjekket 13.06.2015). [40] ——, (2015). Phpmyadmin tutorial, side: https://www.siteground.com/ tutorials/phpmyadmin/ (sjekket 13.06.2015). [41] GSMA. (2014). A guide to bluetooth beacons, side: http://www.gsma.com/ digitalcommerce/wp- content/uploads/2013/10/A- guide- to- BLEbeacons-FINAL-18-Sept-14.pdf (sjekket 13.06.2015). [42] Radius Networks. (2014). Fast background detection with android 5.0, side: http://developer.radiusnetworks.com/2014/10/28/android-5.0scanning.html (sjekket 13.06.2015). [43] The Raspberry Pi Foundation. (2015). Raspberry pi faqs - frequently asked questions, side: https : / / www . raspberrypi . org / help / faqs / #introWhatIs (sjekket 16.05.2015). [44] ——, Download. side: https : / / www . raspberrypi . org / downloads (sjekket 10.06.2015). [45] Arch Linux ARM. (2015). Arch Linuc ARM, side: http : / / www . archlinuxarm.org (sjekket 20.05.2015). [46] ——, Raspberry Pi 2. side: http : / / archlinuxarm . org / platforms / armv7/broadcom/raspberry-pi-2 (sjekket 10.06.2015). [47] Y. Project. (2015). Matchbox | Yocto Project, side: https : / / www . yoctoproject . org / tools - resources / projects / matchbox (sjekket 20.05.2015). 14. juni 2015 VEDLEGG A. FLYTSKJEMA REGISTRERING Start Fill form Cancel? Display error True False Send form Correctly filled? False Cancel True Register or update? Update Register Call register Call update Response == success False True Notification Notification Launch activity Close activity Stop H15E01 I 14. juni 2015 VEDLEGG B. FLYTSKJEMA SLETTING Start Press delete Are you sure? False True Call deleteUser() Response == success False True Set register = true Notify Notify Start activity Close current activity Stop H15E01 III 14. juni 2015 VEDLEGG C. FLYTSKJEMA RUNDETELLING Start Count == true False True Exit region? False True Calculate lap Lap > 30.0 False True Update = true Send query Response e nous r ds onse resp Roun r d e e h t t c o Any Corre ds roun Sent Update info locally Corrected rounds = response Notify Stop H15E01 V 14. juni 2015 VEDLEGG D. KILDEKODE FOR UPDATEINFO Kodeopplisting D.1: UpdateInfo.java 1 2 // Importerer klassene som trengs 3 4 ... 5 6 public class UpdateInfo extends AppCompatActivity { 7 8 // DEKLARERING AV VARIBALE 9 10 11 // Deklarerer tekstfelt og knapper i registreringsskjemaet private EditText editTextName , editTextSurname , editTextAge , editTextWeight , editTextMail; 12 private RadioGroup radioGroupSex; 13 private RadioButton radioButtonSex; 14 private Button registerButton , exitButton; 15 16 17 // Deklarerer variable knyttet til registreringen String id, name, surname , sex, alder, email, weight; 18 19 20 // Variable som holder styr på om det skal registreres eller oppdateres Boolean update , register; 21 22 23 // Deklarerer en editor som skal kunne lagre variable permanent SharedPreferences.Editor editor; 24 25 26 //Variabel til bruk under debugging og utskrift til konsoll protected static final String TAG = "DEBUG:"; 27 28 29 // Denne funksjonen kjører når aktiviteten åpner. 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_update_info); 35 36 // Knytter de forskjellige tekstboksene opp mot de lagrede id som er opprettet i layout (activity_update_info.xml) 37 editTextName = (EditText) findViewById(R.id.Name); 38 39 editTextSurname = (EditText) findViewById(R.id.Surname); 40 editTextAge = (EditText) findViewById(R.id.Age); 41 editTextAge.addTextChangedListener(datewatcher); 42 editTextMail = (EditText) findViewById(R.id.Email); 43 editTextWeight = (EditText) findViewById(R.id.Weight); 44 radioGroupSex = (RadioGroup) findViewById(R.id.radioGroupSex); H15E01 VII VIII 45 registerButton = (Button) findViewById(R.id.button); 46 exitButton = (Button) findViewById(R.id.buttonexit); 47 48 // Finner den unike android IDen til enheten id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); 49 50 51 // Laster inn de lagrede variablene og henter de oppp SharedPreferences settings = PreferenceManager. 52 getDefaultSharedPreferences(this); 53 54 // Henter verdien til "update" og "register". Om de ikke finnes blir verdien til update og register satt til false. 55 update = settings.getBoolean("update", false); 56 register = settings.getBoolean("register", false); 57 58 // Gjør det mulig for editor å endre på settings. editor = settings.edit(); 59 60 } 61 62 // Funksjon som tar for seg registreringen av bruker. Selve prosessen krever at alt som blir tatt imot og sendt er strenger. Dette for å gjøre kodingen lettere og for å forhindre feil 63 64 private void register(String name, String surname , String id, String sex, String alder, String email, String weight) { 65 66 67 // Starter AsyncTask som er en bakgrunnsprosess i egen tråd class LoginAsync extends AsyncTask <String, Void, String> { 68 69 70 //Initialiserer dialogboks private Dialog loadingDialog; 71 72 @Override 73 protected void onPreExecute() { super.onPreExecute(); 74 75 76 //Før blir utført kommer denne opp med melding loadingDialog = ProgressDialog.show(UpdateInfo.this, " 77 Registrerer bruker", "Vennligst vent"); 78 } 79 80 @Override 81 82 // Selve Bakgrunnsprosessen 14. juni 2015 VEDLEGG D. KILDEKODE FOR UPDATEINFO protected String doInBackground(String... params) { 83 84 85 // Her blir variablene hentet inn en etter en, slik de står oppført i funksjonen når den blir kalt 86 String uname = params[0]; 87 String pass = params[1]; 88 String idn = params[2]; 89 String sexe = params[3]; 90 String aldern = params[4]; 91 String mailen = params[5]; 92 String vekta = params[6]; 93 94 // Her kan hver variabel settes som par. fornavn kobles opp mot uname osv. 95 InputStream is = null; 96 List<NameValuePair > nameValuePairs = new ArrayList < 97 nameValuePairs.add(new BasicNameValuePair("fornavn", NameValuePair >(); uname)); nameValuePairs.add(new BasicNameValuePair("etternavn", 98 pass)); nameValuePairs.add(new BasicNameValuePair("unikid", idn 99 )); nameValuePairs.add(new BasicNameValuePair("sex", sexe)) 100 ; 101 nameValuePairs.add(new BasicNameValuePair("alder", 102 nameValuePairs.add(new BasicNameValuePair("email", aldern)); mailen)); nameValuePairs.add(new BasicNameValuePair("vekt", vekta 103 )); String result = null; 104 105 106 // Åpner en forbindelse med server. Denne delen av koden er kopiert fra fungerende eksempler på nettet. try { 107 HttpClient httpClient = new DefaultHttpClient(); 108 109 HttpPost httpPost = new HttpPost( 110 "http://baastad.duckdns.org/insertValue.php 111 "); 112 httpPost.setEntity(new UrlEncodedFormEntity( 113 nameValuePairs , "UTF-8")); 114 HttpResponse response = httpClient.execute(httpPost 115 ); H15E11 IX X 116 HttpEntity entity = response.getEntity(); 117 118 is = entity.getContent(); 119 120 BufferedReader reader = new BufferedReader(new 121 InputStreamReader(is, "UTF-8"), 8); StringBuilder sb = new StringBuilder(); 122 123 124 String line = null; 125 while ((line = reader.readLine()) != null) { sb.append(line + "\n"); 126 127 } 128 result = sb.toString(); } catch (ClientProtocolException e) { 129 e.printStackTrace(); 130 } catch (UnsupportedEncodingException e) { 131 e.printStackTrace(); 132 } catch (IOException e) { 133 e.printStackTrace(); 134 135 } 136 return result; 137 } 138 139 // Når alt har blitt sendt og en respons fra nettsiden har blitt mottatt , kjøres denne 140 @Override 141 protected void onPostExecute(String result) { 142 143 // Trimmer resultatet String s = result.trim(); 144 145 146 // Stenger dialogboksen loadingDialog.dismiss(); 147 148 149 // Hvis resultatet fra serveren er sucesss , så åpnes hovedsiden. if (s.equalsIgnoreCase("success")) { 150 Toast.makeText(getApplicationContext(), "Bruker 151 opprettet", Toast.LENGTH_SHORT).show(); 152 launchIntent(); 153 finish(); 154 155 // Hvis det kommer en annen melding betyr det at bruker allerede er registrert. 156 } else { 14. juni 2015 VEDLEGG D. KILDEKODE FOR UPDATEINFO Toast.makeText(getApplicationContext(), "Du er 157 allerede registrert , velkommen tilbake", Toast. LENGTH_SHORT).show(); 158 launchIntent(); 159 finish(); } 160 } 161 } 162 163 164 LoginAsync la = new LoginAsync(); 165 la.execute(name, surname , id, sex, alder, email, weight); 166 167 } 168 169 170 // Denne følger samme fremgangsmåte som register metoden. Eneste unntaket er at man får en feilmelding og forblir i aktiviteten om oppdateringen ikke lykkes. 171 private void update(final String name, String surname , String id, String sex, String alder, String email, String weight) { 172 class LoginAsync extends AsyncTask <String , Void, String> { 173 174 private Dialog loadingDialog; 175 176 177 @Override 178 protected void onPreExecute() { 179 super.onPreExecute(); 180 loadingDialog = ProgressDialog.show(UpdateInfo.this, " Oppdaterer bruker","Vennligst vent"); } 181 182 183 @Override 184 protected String doInBackground(String... params) { 185 String uname = params[0]; 186 String pass = params[1]; 187 String idn = params[2]; 188 String sexe = params[3]; 189 String aldern = params[4]; 190 String mailen = params[5]; 191 String vekta = params[6]; 192 193 InputStream is = null; 194 List<NameValuePair > nameValuePairs = new ArrayList < NameValuePair >(); nameValuePairs.add(new BasicNameValuePair("fornavn", 195 uname)); H15E11 XI XII 196 nameValuePairs.add(new BasicNameValuePair("etternavn", pass)); 197 nameValuePairs.add(new BasicNameValuePair("unikid", idn )); 198 nameValuePairs.add(new BasicNameValuePair("sex", sexe)) 199 nameValuePairs.add(new BasicNameValuePair("alder", ; aldern)); 200 nameValuePairs.add(new BasicNameValuePair("email", 201 nameValuePairs.add(new BasicNameValuePair("vekt", vekta mailen)); )); 202 String result = null; 203 204 205 try { HttpClient httpClient = new DefaultHttpClient(); 206 207 HttpPost httpPost = new HttpPost( "http://baastad.duckdns.org/updateInfo.php" 208 ); 209 210 httpPost.setEntity(new UrlEncodedFormEntity( nameValuePairs , "UTF-8")); 211 212 HttpResponse response = httpClient.execute(httpPost ); 213 214 HttpEntity entity = response.getEntity(); 215 216 is = entity.getContent(); 217 218 BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF8"), 8); 219 StringBuilder sb = new StringBuilder(); 220 221 String line = null; 222 while ((line = reader.readLine()) != null) { sb.append(line + "\n"); 223 224 } 225 result = sb.toString(); 226 227 228 229 230 } catch (ClientProtocolException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { 14. juni 2015 VEDLEGG D. KILDEKODE FOR UPDATEINFO e.printStackTrace(); 231 } 232 return result; 233 } 234 235 236 @Override 237 protected void onPostExecute(String result) { 238 String s = result.trim(); 239 System.out.println(result); 240 loadingDialog.dismiss(); 241 if (s.equalsIgnoreCase("success")) { Toast.makeText(getApplicationContext(), " 242 Brukerinformasjon oppdatert", Toast.LENGTH_LONG).show(); 243 launchIntent(); 244 finish(); } else { 245 Toast.makeText(getApplicationContext(), "Det 246 skjedde en feil, vennligst prøv igjen", Toast.LENGTH_LONG).show(); } 247 } 248 } 249 250 251 LoginAsync la = new LoginAsync(); 252 la.execute(name, surname , id, sex, alder, email, weight); 253 254 } 255 256 // Denne funksjonen holder styr på menyen og alle klikkbare objekter på skjermen 257 258 @Override 259 public boolean onCreateOptionsMenu(Menu menu) { 260 261 // Inflate the menu; this adds items to the action bar if it is present . getMenuInflater().inflate(R.menu.menu_update_info , menu); 262 263 264 // En funksjon som ser etter om registrer knappen har blitt trykket registerButton.setOnClickListener(new OnClickListener() { 265 266 267 // Hvis den blir klikket 268 @Override 269 public void onClick(View view) { 270 271 // Konverter informasjonen i alle felt til strenger H15E11 XIII XIV 272 name = editTextName.getText().toString(); 273 surname = editTextSurname.getText().toString(); 274 alder = editTextAge.getText().toString(); 275 email = editTextMail.getText().toString(); 276 weight = editTextWeight.getText().toString(); 277 278 279 // Sjekker om noen av feltene er fylt inn feil eller mangler if (name.matches("")) { editTextName.setError("Vennligst oppgi navn"); 280 return; 281 282 } else if (surname.matches("")) { 283 editTextSurname.setError("Vennligst oppgi etternavn 284 return; "); 285 } else if (!isEmailValid(email)) { 286 editTextMail.setError("Vennligst oppgi en 287 return; emailaddresse"); 288 } else if (radioGroupSex.getCheckedRadioButtonId() == -1) { Toast.makeText(UpdateInfo.this, "Vennligst velg 289 kjønn", Toast.LENGTH_SHORT).show(); return; 290 291 292 // Hvis ingen av feltene mangler eller har feil, så sendes registreringen 293 294 } else { int selectedId = radioGroupSex. getCheckedRadioButtonId(); 295 radioButtonSex = (RadioButton) findViewById( selectedId); 296 sex = radioButtonSex.getText().toString(); 297 298 // Lagrer navn og android ID permanent i appen 299 editor.putString("navn", name); 300 editor.putString("idn", id); 301 editor.commit(); 302 303 // Hvis lagret verdi for update er true, kjør update funksjonen. Ellers kjør registrer funskjonen. 304 305 if (update.equals(true)) { update(name, surname , id, sex, alder, email, weight); 306 editor.putBoolean("update", false); 307 editor.commit(); 308 } else { 14. juni 2015 VEDLEGG D. KILDEKODE FOR UPDATEINFO register(name, surname , id, sex, alder, email, 309 weight); 310 editor.putBoolean("register", false); 311 editor.commit(); } 312 313 } 314 315 } 316 317 }); 318 319 320 // Sjekk om avbrytknappen har blitt klikket og lukk appen helt 321 exitButton.setOnClickListener(new OnClickListener() { 322 323 @Override 324 public void onClick(View view ) { 325 326 finish(); 327 System.exit(0); 328 } 329 330 } 331 332 ); 333 334 return true; 335 336 } 337 338 // Denne funksjonen holder styr på menyen og objekter der. 339 @Override 340 public boolean onOptionsItemSelected(MenuItem item) { // Hvis avbryt i menyen har blitt klikket på, avslutt og lukk 341 appen helt switch (item.getItemId()) { 342 case R.id.action_settings: 343 344 finish(); 345 System.exit(0); break; 346 default: 347 return super.onOptionsItemSelected(item); 348 } 349 350 return true; 351 352 } H15E11 XV XVI 353 354 // Åpne funksjoner som gjør det mulig for å flytte kode inn under de forskjellige states i appen 355 @Override 356 public void onResume() { super.onResume(); 357 358 } 359 360 @Override 361 public void onPause() { super.onPause(); 362 363 } 364 365 @Override 366 public void onDestroy() { super.onDestroy(); 367 368 } 369 370 // Overstyrer tilbakeknappen på hardwaresiden , slik at det ikke er mulig å falle ut av appen når man registrerer seg. Dette for å forhindre frustrasjon. 371 @Override 372 public void onBackPressed() { 373 } 374 375 // Starter en ny aktivtet , hovedsiden åpner automatisk. 376 private void launchIntent() { 377 Intent intent = new Intent(this, UserProfile.class); 378 this.startActivity(intent); 379 } 380 381 // Denne funksjonen sørger for at input av fødselsdato foregår korrekt. Denne koden er tatt fra brukerbidrag på stackexchange. Den har blitt modifisert med noen tester og tilhørende feilmeldinger 382 383 private TextWatcher datewatcher = new TextWatcher() { 384 private String current = ""; 385 private String ddmmyyyy = "DDMMÅÅÅÅ"; 386 private Calendar cal = Calendar.getInstance(); 387 388 @Override 389 public void onTextChanged(CharSequence s, int start, int before , int count) { 390 if (!s.toString().equals(current)) { 391 String clean = s.toString().replaceAll("[^\\d.]", ""); 392 String cleanC = current.replaceAll("[^\\d.]", ""); 393 14. juni 2015 VEDLEGG D. KILDEKODE FOR UPDATEINFO 394 int cl = clean.length(); 395 int sel = cl; 396 for (int i = 2; i <= cl && i < 6; i += 2) { sel++; 397 398 } 399 if (clean.equals(cleanC)) sel--; 400 if (clean.length() < 8) { 401 clean = clean + ddmmyyyy.substring(clean.length()); 402 } else { 403 404 405 int day = Integer.parseInt(clean.substring(0, 2)); 406 int mon = Integer.parseInt(clean.substring(2, 4)); 407 int year = Integer.parseInt(clean.substring(4, 8)); 408 int thisYear = Calendar.getInstance().get(Calendar. YEAR); 409 if (mon > 12) { 410 editTextAge.setError("Oppgi korrekt måned"); 411 } else { 412 cal.set(Calendar.MONTH, mon - 1); 413 } 414 415 if ((year < 1900) || (year > thisYear)) { 416 editTextAge.setError("Oppgi korrekt år"); 417 } else { 418 cal.set(Calendar.YEAR, year); 419 } 420 421 if ((day > cal.getActualMaximum(Calendar.DATE) || ( 422 day == 0))) { editTextAge.setError("Oppgi korrekt dag"); 423 } 424 425 clean = String.format("%02d%02d%02d", day, mon, 426 year); } 427 428 alder = clean; 429 430 clean = String.format("%s/%s/%s", clean.substring(0, 2) 431 , 432 clean.substring(2, 4), 433 clean.substring(4, 8)); 434 435 sel = sel < 0 ? 0 : sel; 436 H15E11 XVII XVIII 437 current = clean; 438 editTextAge.setText(current); 439 editTextAge.setSelection(sel < current.length() ? sel : current.length()); } 440 } 441 442 ; 443 444 445 @Override 446 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 447 448 } 449 450 451 @Override 452 public void afterTextChanged(Editable s) { 453 } 454 }; 455 456 457 // Denne funksjonen sjekker om emailen har riktig format. boolean isEmailValid(CharSequence email) { 458 return android.util.Patterns.EMAIL_ADDRESS.matcher(email). 459 matches(); } 460 461 } 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE Kodeopplisting E.1: UserProfile.java 1 2 / Importerer klasser 3 4 .... 5 6 public class UserProfile extends AppCompatActivity implements BeaconConsumer { 7 8 9 // Deklarerer tekstfelt som skal vise tekst og start/stopp knapper. private TextView printText; 10 private TextView printGreeting; 11 private Button startButton; 12 private Button stopButton; 13 14 // Deklarerer variable til bruk i beregning av rundetid og telling og sending av informasjon til server 15 int rounds = 0; 16 long startTime , lapTime , stopTime; 17 double bestTime , showLapTime , checkLapTime; 18 String sendLapTime , sendRounds , sendBestTime , correctRounds , 19 int intCorrectRounds , intCorrection; 20 Boolean startCounting = false; 21 Boolean update = false; sendCorrectRounds , checkCorrection; 22 23 // Deklarerer variable til sjekk av lagrede variable og ID 24 String id; 25 SharedPreferences.Editor editor; 26 SharedPreferences settings; 27 String nameSaved , idSaved; 28 Boolean delete; 29 30 // Deklarerer variable som er relevante til beacon 31 private BeaconManager beaconManager; 32 Region region1 = new Region("m1", null, null, null); 33 Region region2 = new Region("m2", Identifier.parse("144e71a8-e817dd8e -488f-29c742921b49"), Identifier.parse("11070"), null); 34 Long FScanPeriod = 100L; 35 Long FScanBetweenPeriod = 0L; 36 Long BScanPeriod = 100L; 37 Long BScanBetweenPeriod = 0L; 38 Boolean isBound; 39 40 41 //Variabel til bruk under debugging og utskrift til konsoll protected static final String TAG = "DEBUG:"; 42 H15E01 XIX XX 43 // Funksjon som starter ved oppstart av aktivitet 44 @Override 45 protected void onCreate(Bundle savedInstanceState) { 46 super.onCreate(savedInstanceState); 47 setContentView(R.layout.activity_user_profile); 48 49 // Kobler sammen knapper opp mot layout 50 startButton = (Button) findViewById(R.id.startime); 51 stopButton = (Button) findViewById(R.id.stoptime); 52 53 // Finner den unike android ID id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); 54 55 56 // Henter opp lagrede variable , og setter de de verdier om de ikke eksisterer. 57 settings = PreferenceManager.getDefaultSharedPreferences(this); 58 isBound = settings.getBoolean("isbound", false); 59 delete = settings.getBoolean("delete", false); 60 nameSaved = settings.getString("navn", null); 61 idSaved = settings.getString("idn", null); 62 63 // Starter en beaconManager. Denne gjør det mulig for å kjøre ekstrafunksjoner i programmet beaconManager = BeaconManager.getInstanceForApplication(this); 64 65 66 // Sjekker at Bluetooth er på eller er støttet. verifyBluetooth(); 67 68 69 // Gjør det mulig å kjøre kommandoer på beaconManager beaconManager.bind(this); 70 71 72 // Setter variable som scanneperiode o.l. samt formatet på UUID appen skal lete etter setBeaconVariables(isBound); 73 74 75 // Sjekker om bruker er registrert checkRegister(id, idSaved); 76 77 78 // Viser et ikon i statusbar 79 getSupportActionBar().setDisplayShowHomeEnabled(true); 80 getSupportActionBar().setIcon(R.mipmap.ic_launcher); 81 82 } 83 84 // Kjører når aktiviteten er avsluttet og skal fjernes 85 @Override 86 protected void onDestroy() { 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE 87 super.onDestroy(); 88 // Lagrer isbound = false, og stopper beaconManager 89 editor = settings.edit(); 90 editor.putBoolean("isbound", false); 91 editor.commit(); beaconManager.unbind(this); 92 93 } 94 95 @Override 96 protected void onRestart() { super.onRestart(); 97 98 } 99 100 // Denne funksjonen holder styr på vinduet og alle klikkbare objekter på skjermen 101 @Override 102 public boolean onCreateOptionsMenu(Menu menu) { 103 104 getMenuInflater().inflate(R.menu.menu_user_profile , menu); 105 106 // Skriv ut velkomstmelding printGreeting = (TextView) UserProfile.this 107 .findViewById(R.id.velkommen); 108 109 String showGreeting = getString(R.string.Velkommen , nameSaved); 110 printGreeting.setText(showGreeting); 111 112 // Hvis startknappen er trykket inn, start telling og skriv ut til skjerm startButton.setOnClickListener(new OnClickListener() { 113 114 @Override 115 public void onClick(View view) { 116 startCounting = true; 117 Log.i(TAG, "Startknappen trykket , start rundetelling"); logToDisplay("START"); 118 } 119 120 }); 121 122 123 // Hvis stoppknappen er trykket inn, stopp telling og skriv ut til skjerm stopButton.setOnClickListener(new OnClickListener() { 124 125 @Override 126 public void onClick(View view) { 127 startCounting = false; 128 Log.i(TAG, "Stoppknappen trykket , stopp rundetelling"); 129 logToDisplay("STOP"); } 130 H15E11 XXI XXII 131 }); 132 return true; 133 } 134 135 // Denne funksjonen holder styr på menyen og objekter der. 136 @Override 137 public boolean onOptionsItemSelected(MenuItem item) { 138 switch (item.getItemId()) { 139 140 // Hvis det blir trykket på "omregistrer", oppdater lagrede variabler og åpne skjema 141 case R.id.action_settings: 142 editor = settings.edit(); 143 editor.putBoolean("update", true); 144 editor.commit(); 145 launchIntent(); 146 break; 147 148 149 // Hvis bruekr vil slette seg selv case R.id.delete: 150 151 152 // Spør om bekreftelse AlertDialog.Builder alertDialogBuilder = new AlertDialog. Builder(UserProfile.this); 153 alertDialogBuilder.setMessage("Er du sikker på at du vil slette din bruker?"); 154 155 156 // Hvis bruker trykker ja, lagre variable og avslutt aktiviteten alertDialogBuilder.setPositiveButton("yes", new DialogInterface.OnClickListener() { 157 @Override 158 public void onClick(DialogInterface dialog , int which) { 159 deleteUser(id); 160 editor = settings.edit(); 161 editor.putBoolean("delete", true); 162 editor.commit(); 163 finish(); 164 } 165 166 167 }); 168 169 // Hvis bruker trykker nei, fortsett som før. 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE alertDialogBuilder.setNegativeButton("No", new 170 DialogInterface.OnClickListener() { 171 @Override 172 public void onClick(DialogInterface dialog , int which) { } 173 }); 174 175 176 AlertDialog alertDialog = alertDialogBuilder.create(); 177 alertDialog.show(); 178 break; 179 default: 180 return super.onOptionsItemSelected(item); 181 } 182 183 return true; 184 185 } 186 187 // Funksjon som tar seg av sletting av bruker. Den følger samme oppsett som registrer og update funksjonen i UpdateInfo 188 public void deleteUser(String id) { 189 class deleteUser extends AsyncTask <String , Void, String> { 190 191 192 @Override 193 protected void onPreExecute() { super.onPreExecute(); 194 } 195 196 197 @Override 198 protected String doInBackground(String... params) { String iden = params[0]; 199 200 201 InputStream is = null; 202 List<NameValuePair > nameValuePairs = new ArrayList < 203 nameValuePairs.add(new BasicNameValuePair("unikid", NameValuePair >(); iden)); String result = null; 204 205 try { 206 207 HttpClient httpClient = new DefaultHttpClient(); 208 HttpPost httpPost = new HttpPost( "http://baastad.duckdns.org/deleteUser.php" 209 ); 210 H15E11 XXIII XXIV httpPost.setEntity(new UrlEncodedFormEntity( 211 nameValuePairs , "UTF-8")); 212 HttpResponse response = httpClient.execute(httpPost 213 ); 214 HttpEntity entity = response.getEntity(); 215 216 is = entity.getContent(); 217 218 BufferedReader reader = new BufferedReader(new 219 InputStreamReader(is, "UTF8"), 8); StringBuilder sb = new StringBuilder(); 220 221 222 String line = null; 223 while ((line = reader.readLine()) != null) { sb.append(line + "\n"); 224 } 225 result = sb.toString(); 226 } catch (ClientProtocolException e) { 227 e.printStackTrace(); 228 } catch (UnsupportedEncodingException e) { 229 e.printStackTrace(); 230 } catch (IOException e) { 231 e.printStackTrace(); 232 233 } 234 return result; 235 } 236 237 // Hvis forespørselen lykkes , oppdater variable og lukk aktiviteten. 238 @Override 239 protected void onPostExecute(String result) { 240 String s = result.trim(); 241 System.out.println(result); 242 if (s.equalsIgnoreCase("success")) { 243 editor = settings.edit(); 244 editor.clear(); 245 editor.putBoolean("register", true); 246 editor.commit(); 247 Toast.makeText(getApplicationContext(), "Bruker slettet", Toast.LENGTH_SHORT ).show(); 248 launchIntent(); 249 finish(); 250 } else { 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE Toast.makeText(getApplicationContext(), "Det 251 oppstod en feil, prøv igjen.", Toast. LENGTH_SHORT).show(); } 252 } 253 } 254 255 256 deleteUser du = new deleteUser(); 257 du.execute(id); 258 259 } 260 261 262 // Funksjon som sjekker om en bruker er registrert fra før. private void checkRegister(final String Id, final String savedId) { 263 // Hvis android ID er lik den lagrede IDen, så skal ingenting 264 skje. Hvis ikke skal aktiviteten lukkes, og bruker sendes til registreringsskjema 265 if (Id.equals(savedId)) { 266 } else { Toast.makeText(getApplicationContext(), "Vennligst 267 registrer deg", Toast.LENGTH_LONG).show() ; 268 editor = settings.edit(); 269 editor.putBoolean("register", true); 270 editor.commit(); 271 launchIntent(); 272 finish(); } 273 274 } 275 276 277 // Starter en ny aktivtet , registreringsskjema åpner automatisk. private void launchIntent() { 278 Intent intent = new Intent(this, UpdateInfo.class); 279 this.startActivity(intent); 280 } 281 282 // Sjekker om bruker har bluetooth. Denne er tatt fra Altbecons eksempelapp , og har blitt 283 modifisert. private void verifyBluetooth() { 284 try { 285 if (!BeaconManager.getInstanceForApplication(this). 286 checkAvailability()) { Intent turnOnIntent = new Intent(BluetoothAdapter. 287 ACTION_REQUEST_ENABLE); startActivityForResult(turnOnIntent , 1); 288 H15E11 XXV XXVI } 289 290 } catch (RuntimeException e) { 291 final AlertDialog.Builder builder = new AlertDialog.Builder 292 (this); 293 builder.setTitle("Bluetooth LE ikke tilgjengelig"); 294 builder.setMessage("Beklager , enheten støtter ikke Bluetooth LE"); 295 builder.setPositiveButton(android.R.string.ok, null); 296 builder.setOnDismissListener(new DialogInterface. OnDismissListener() { 297 298 @Override 299 public void onDismiss(DialogInterface dialog) { 300 finish(); 301 System.exit(0); } 302 303 }); 304 builder.show(); 305 } 306 307 } 308 309 // Skriver ut enten start eller stopp til skjermen 310 private void logToDisplay(final String line) { runOnUiThread(new Runnable() { 311 public void run() { 312 printText = (TextView) UserProfile.this 313 .findViewById(R.id.printRounds); 314 printText.setText(line); 315 } 316 }); 317 318 } 319 320 // Setter beaconvariable. Hvis beaconManager ikke er bundet, så skal også formatet på UUID settes. 321 private void setBeaconVariables(Boolean checkBound) { 322 beaconManager.setForegroundScanPeriod(FScanPeriod); 323 beaconManager.setForegroundBetweenScanPeriod(FScanBetweenPeriod ); 324 beaconManager.setBackgroundScanPeriod(BScanPeriod); 325 beaconManager.setBackgroundBetweenScanPeriod(BScanBetweenPeriod ); 326 327 328 if (!checkBound) { beaconManager.getBeaconParsers().add(new BeaconParser(). 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23, 329 p:24-24")); } 330 331 beaconManager.setAndroidLScanningDisabled(true); 332 333 334 editor = settings.edit(); 335 editor.putBoolean("isbound", true); 336 editor.commit(); 337 } 338 339 // Sender notifikasjon til bruker i statusbar og vises i lockscreen. Denne er hentet fra Google sine hjelpesider og eksempler 340 private void sendNotification(String showBestTime , int rounds) { 341 NotificationCompat.Builder builder = 342 new NotificationCompat.Builder(this); 343 344 345 String updatetext; 346 int numMessages = 0; 347 updatetext = "Beste rundetid: " + showBestTime + " Antall 348 runder: " + rounds; 349 builder.setContentTitle("Beste rundetid og antall runder") 350 351 .setContentText(updatetext) 352 .setSmallIcon(R.mipmap.ic_notification) 353 .setNumber(++numMessages); 354 355 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 356 stackBuilder.addNextIntent(new Intent(this, UserProfile.class)) ; PendingIntent resultPendingIntent = 357 stackBuilder.getPendingIntent( 358 359 0, 360 PendingIntent.FLAG_UPDATE_CURRENT ); 361 362 363 builder.setContentIntent(resultPendingIntent); 364 NotificationManager notificationManager = 365 (NotificationManager) this.getSystemService(Context. 366 NOTIFICATION_SERVICE); notificationManager.notify(3, builder.build()); 367 368 } 369 H15E11 XXVII XXVIII 370 // Denne følger samme oppsett som register , update og deleteUser funksjonene. 371 public void updateRoundTime(String iden, String rundetid , String runder , String besterundetid) { 372 373 class updateRoundTime extends AsyncTask <String, Void, String > { 374 375 @Override 376 protected void onPreExecute() { super.onPreExecute(); 377 378 } 379 380 @Override 381 protected String doInBackground(String... params) { 382 String iden = params[0]; 383 String rundetiden = params[1]; 384 String rundertot = params[2]; 385 String bestetid = params[3]; 386 387 InputStream is = null; 388 List<NameValuePair > nameValuePairs = new ArrayList < NameValuePair >(); 389 nameValuePairs.add(new BasicNameValuePair("androidID", 390 nameValuePairs.add(new BasicNameValuePair("time", iden)); rundetiden)); 391 nameValuePairs.add(new BasicNameValuePair("rounds", rundertot)); 392 nameValuePairs.add(new BasicNameValuePair("besttime", 393 String result = null; bestetid)); 394 395 try { 396 HttpClient httpClient = new DefaultHttpClient(); 397 HttpPost httpPost = new HttpPost( "http://baastad.duckdns.org/passering.php") 398 ; 399 400 httpPost.setEntity(new UrlEncodedFormEntity( nameValuePairs , "UTF-8")); 401 402 HttpResponse response = httpClient.execute(httpPost ); 403 404 HttpEntity entity = response.getEntity(); 405 406 is = entity.getContent(); 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE 407 BufferedReader reader = new BufferedReader(new 408 InputStreamReader(is, "UTF8"), 8); StringBuilder sb = new StringBuilder(); 409 410 411 String line = null; 412 while ((line = reader.readLine()) != null) { sb.append(line + "\n"); 413 414 } 415 result = sb.toString(); } catch (ClientProtocolException e) { 416 e.printStackTrace(); 417 } catch (UnsupportedEncodingException e) { 418 e.printStackTrace(); 419 } catch (IOException e) { 420 e.printStackTrace(); 421 422 } 423 return result; } 424 425 426 // Denne følger nedre del av flytskjema. Denne fungerer ved at den korrigerer antall runder på klientsiden 427 @Override 428 protected void onPostExecute(String result) { 429 String s = result.trim(); 430 if (s.equals(sendRounds)) { Log.i(TAG, "Oppdatering av rundetid er vellykket!") 431 ; Log.i(TAG, "Rundetiden var: " + sendLapTime + " Du 432 har gått: " + s + " runder"); rounds++; 433 } else if (s.equals(checkCorrection)) { 434 435 checkCorrection = null; 436 Log.i(TAG, "Feilkorrigeringen lykkes"); 437 Log.i(TAG, "Rundetiden var: " + sendLapTime + " Du har gått: " + intCorrection + " runder"); rounds = intCorrection; 438 } else if (s.equalsIgnoreCase("nouser")) { 439 Log.i(TAG, "Ingen bruker registrert i 440 brukertabellen"); } else if (s.equalsIgnoreCase("success")) { 441 Log.i(TAG, "Oppdatering av rundetid er vellykket!") 442 ; Log.i(TAG, "Rundetiden var: " + sendLapTime + " Du 443 har gått: " + s + " H15E11 runder"); XXIX XXX rounds++; 444 } else { 445 Log.i(TAG, "Feil rundetall sendt, " + result + " 446 står oppført. Prøver å korrigere."); 447 correctRounds = s; 448 intCorrectRounds = Integer.parseInt(correctRounds); 449 intCorrection = intCorrectRounds + 1; 450 checkCorrection = String.valueOf(intCorrection); 451 sendCorrectRounds = String.valueOf(intCorrection); 452 updateRoundTime(id, sendLapTime , sendCorrectRounds , sendBestTime); } 453 } 454 455 } 456 updateRoundTime update = new updateRoundTime(); update.execute(id, rundetid , runder , besterundetid); 457 458 } 459 460 461 // Denne funksjonen slår inn når beaconManager er startet. 462 @Override 463 public void onBeaconServiceConnect() { 464 465 // Denne funksjonen åpner for mulighet til å avgjøre avstanden til hver beacon. Det er også denne som blir brukt for å finne verdiene på de forskjellige beacon. 466 467 beaconManager.setRangeNotifier(new RangeNotifier() { 468 @Override 469 public void didRangeBeaconsInRegion(Collection <Beacon > beacons , Region region) { 470 if (beacons.size() > 0) { 471 472 for (Beacon beacon : beacons) { 473 Log.i(TAG, "Ser en beacon med UUID " + beacon.getId1() + 474 } " og Major: " + } 475 476 beacon.getId2()); }}); 477 478 try { 479 480 beaconManager.startRangingBeaconsInRegion(region1); 481 // beaconManager.startRangingBeaconsInRegion(region2); 482 } catch (RemoteException e) { 483 } 14. juni 2015 VEDLEGG E. KILDEKODE FOR USERPROFILE 484 485 // Denne funksjonen sjekker etter om en bruker har gått inn eller ut av en region beaconManager.setMonitorNotifier(new MonitorNotifier() { 486 487 488 // Når en bruker går inn en region sendes det en notifikasjon til bruker med beste rundetid og antall runder 489 490 @Override 491 public void didEnterRegion(Region region) { 492 String showBestTime = String.format("%.2f", bestTime); 493 sendNotification(showBestTime , rounds); Log.i(TAG, "Bruker har gått inn i sone"); 494 } 495 496 497 // Når bruekr går ut av en region følger den samme flyt som i flytskjemaet for rundetelling. Notifikasjon sendes også. 498 @Override 499 public void didExitRegion(Region region) { 500 calculateResults(); 501 if (update && startCounting) { updateRoundTime(id, sendLapTime , sendRounds , 502 sendLapTime); 503 } 504 String showBestTime = String.format("%.2f", bestTime); 505 sendNotification(showBestTime , rounds); Log.i(TAG, "Bruker har gått ut av sone"); 506 } 507 508 // Funksjon som slår inn hver gang en bruker enten går inn 509 eller ut av region 510 @Override 511 public void didDetermineStateForRegion(int state, Region region) { 512 } 513 }); 514 515 try { 516 beaconManager.startMonitoringBeaconsInRegion(region1); 517 // beaconManager.startMonitoringBeaconsInRegion(region2); 518 519 } catch (RemoteException e) { 520 } 521 } 522 523 // Funksjon for å beregne rundetid , bestetid , og om rundetiden er godkjent. H15E11 XXXI XXXII private void calculateResults() { 524 525 if (startTime == 0) { 526 startTime = System.nanoTime(); 527 } 528 529 stopTime = System.nanoTime(); 530 lapTime = stopTime - startTime; 531 checkLapTime = (lapTime / 1000000000.0) - 10.0; 532 if ((checkLapTime > 30.0)) { 533 showLapTime = checkLapTime; 534 if (bestTime == 0) { bestTime = showLapTime; 535 } 536 537 if (showLapTime < bestTime) { 538 bestTime = showLapTime; 539 } 540 541 542 DecimalFormat df = new DecimalFormat("#.00"); 543 sendLapTime = df.format(showLapTime); 544 DecimalFormat ds = new DecimalFormat("#.00"); 545 sendBestTime = df.format(bestTime); 546 sendRounds = String.valueOf(rounds + 1); 547 startTime = stopTime; 548 update = true; } else { 549 update = false; 550 } 551 } 552 553 } 14. juni 2015 VEDLEGG F. KILDEKODE FOR DELETEUSER.PHP Kodeopplisting F.1: deleteUser.php 1 <?php 2 3 // Setter variable relevant til database og tabell 4 $servername = "localhost"; 5 $username = "pi"; 6 $password = "raspberry"; 7 $dbname = "BaastadIL"; 8 $table = "users"; 9 10 // Lager forbindelse til database 11 $conn = new mysqli($servername , $username , $password , $dbname); 12 // Sjekker forbindelse for feil 13 if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); 14 15 } 16 17 // Leser inn den unike android ID 18 $unikid = $_POST['unikid']; 19 20 // Kjører SQL setning på database for å slette 21 $sql = "DELETE FROM $table WHERE androidID LIKE '%$unikid%'"; 22 23 // Hvis det var vellykket send success i respons , ellers send fail. 24 if ($conn->query($sql) === TRUE) { echo "success"; 25 26 } else { echo "fail"; 27 28 } 29 30 // Lukker forbindelsen til databasen 31 $conn->close(); 32 ?> H15E01 XXXIII 14. juni 2015 VEDLEGG G. KILDEKODE FOR INSERTVALUE.PHP Kodeopplisting G.1: insertValue.php 1 <?php 2 3 // Setter variable relevant til database og tabell 4 $servername = "localhost"; 5 $username = "pi"; 6 $password = "raspberry"; 7 $dbname = "BaastadIL"; 8 $table = "users"; 9 10 // Lager forbindelse til database 11 $conn = new mysqli($servername , $username , $password , $dbname); 12 // Sjekker forbindelse for feil 13 if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); 14 15 } 16 17 // Leser inn variable sendt fra brukeren 18 $fornavn = $_POST['fornavn']; 19 $etternavn = $_POST['etternavn']; 20 $unikid = $_POST['unikid']; 21 $sex = $_POST['sex']; 22 $birthday = $_POST['alder']; 23 24 // Kjører SQL setning for å sette all informasjon inn i server. 25 $sql = "INSERT INTO $table (androidID , name, lastname , gender, birthday ) VALUES ('$unikid', '$fornavn', '$etternavn', '$sex', '$birthday')" ; 26 27 // Hvis det var vellykket send success i respons , ellers send fail. 28 if ($conn->query($sql) === TRUE) { echo "success"; 29 30 } else { echo "fail"; 31 32 } 33 34 // Lukker forbindelsen til databasen 35 $conn->close(); 36 ?> H15E01 XXXV 14. juni 2015 VEDLEGG H. KILDEKODE FOR UPDATEINFO.PHP Kodeopplisting H.1: updateInfo.php 1 <?php 2 // Setter variable relevant til database og tabell 3 $servername = "localhost"; 4 $username = "pi"; 5 $password = "raspberry"; 6 $dbname = "BaastadIL"; 7 $table = "users"; 8 9 // Lager forbindelse til database 10 $conn = new mysqli($servername , $username , $password , $dbname); 11 // Sjekker forbindelse for feil 12 if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); 13 14 } 15 16 // Leser inn variable sendt fra brukeren 17 $fornavn = $_POST['fornavn']; 18 $etternavn = $_POST['etternavn']; 19 $unikid = $_POST['unikid']; 20 $sex = $_POST['sex']; 21 $birthday = $_POST['alder']; 22 23 // Kjører SQL setning på server for å oppdatere informasjonen om en bruker 24 $sql = "UPDATE $table SET name='$fornavn', lastname='$etternavn', gender='$sex' , birthday='$alder' WHERE androidID ='$unikid'"; 25 26 // Hvis det var vellykket send success i respons , ellers send fail. 27 if ($conn->query($sql) === TRUE) { echo "success"; 28 29 } else { echo "fail"; 30 31 } 32 33 // Lukker forbindelsen til databasen 34 $conn->close(); 35 ?> H15E01 XXXVII 14. juni 2015 VEDLEGG I. KILDEKODE FOR PASSERING.PHP Kodeopplisting I.1: passering.php 1 <?php 2 // ======================================= 3 // 4 // ======================================= KOBLER TIL DATABASE 5 6 // Sjekker om vi har noe å gjøre 7 8 if (empty($_POST['androidID'])) { 9 die("Ingen Adnroid -ID gitt"); 10 } else { $androidID = $_POST['androidID']; 11 12 } 13 14 if (empty($_POST['time'])) { $time = 0; 15 16 } else { $time = $_POST['time']; 17 18 } 19 20 if (empty($_POST['rounds'])) { $rounds = 0; 21 22 } else { $rounds = (int)$_POST['rounds']; 23 24 } 25 26 if (empty($_POST['besttime'])) { $besttime = 0; 27 28 } else { $besttime = (int)$_POST['besttime']; 29 30 } 31 32 // ======================================= 33 // 34 // ====================================== 35 // 36 $DBServer = 'localhost'; 37 $DBUser = 'pi'; 38 $DBPass = 'raspberry'; 39 $DBName = 'BaastadIL'; KOBLER TIL DATABASE === VARIABLER 40 41 // Create connection 42 if (($con = new mysqli($DBServer , $DBUser , $DBPass , $DBName)) == false) { die("fail"); 43 44 } 45 H15E01 XXXIX XL 46 if (($result_users = $con->query( "SELECT * FROM users WHERE androidID = '$androidID'" 47 48 )) == false) { die("fail"); 49 50 } 51 52 if (($result_runder = $con->query( "SELECT * FROM Rundeteller where androidID = '$androidID'" 53 54 )) == false) { die("fail"); 55 56 } 57 58 while ($row = $result_runder ->fetch_assoc()) { $oldRounds = $row['rounds']; 59 60 } 61 62 // SJEKKER OM BRUKER EKSISTERER I USERS-TABELL , HVIS IKKE RETURNER " nouser" 63 if ($result_users ->num_rows != 1) { die("nouser"); 64 65 } 66 67 // En liten hack 68 if ($result_runder ->num_rows == 0) { 69 $oldRounds = -1; 70 $rounds = 0; 71 } 72 73 // Sjekker hva tilsendt rundetall er og kjører SQL setning. Returnerer 74 75 if ($oldRounds == $rounds - 1) { 76 $newRounds = $rounds; 77 $con->query( 78 "INSERT INTO Rundeteller (androidID , time, rounds,besttime) VALUES ( 79 80 '$androidID','$time','$newRounds','$besttime' )" // VALUES 81 ); // query 82 echo $newRounds; 83 84 85 86 } else if($oldRounds == $rounds) { $newRounds = $rounds + 1; $con->query( "INSERT INTO Rundeteller (androidID , time, rounds,besttime) VALUES ( 87 88 89 '$androidID','$time','$newRounds','$besttime' )" // VALUES ); // query 14. juni 2015 VEDLEGG I. KILDEKODE FOR PASSERING.PHP echo "success"; 90 91 }else{ echo $oldRounds; 92 93 } 94 95 $con->close(); H15E11 XLI 14. juni 2015 VEDLEGG J. POST-INSTALLERINGSSKRIPT ARCH LINUX Kodeopplisting J.1: post_install.sh 1 #!/bin/bash 2 3 # install version 0.1 ( 2015/05/22 ) 4 # 5 # 6 # 7 # ------ 8 # Dette skriptet innstallerer alle nødvendige programmer for 9 # serverløsningen til 'Mobilt tidtakersystem '. 10 # 11 # Installasjonsfil for Raspberry Pi med Arch Linux (ARM) 12 13 14 # === Sjekker om skriptet blir kjørt som root. 15 if [[ $EUID -ne 0 ]]; then echo -e "Skriptet må kjøres som root\nAvslutter" 1>&2 16 exit 1 17 18 fi 19 20 echo "Starter med å opprette bruker." 21 echo -e "Skriv inn navn på bruker.\nSkriver du ingenting blir brukern ' pi' valgt" 22 23 read NEW_USER 24 25 if [ -z "$NEW_USER" ]; then NEW_USER=pi 26 27 fi 28 echo "Ny bruker er $NEW_USER" 29 30 useradd -m -G wheel -s /bin/bash 31 passwd $NEW_USER $NEW_USER 32 33 34 # ==================================== 35 # === Installerer nødvendindige pakker 36 37 # === Oppdaterer systemet 38 pacman -Syu --noconfirm 39 40 # === Installerer pakker 41 pacman -S dialog wpa_supplicant wpa_actiond xf86-video-fbdev xorgserver slim matchbox -window -manager chromium apache mysql php phpapache samba avahi --noconfirm 42 43 H15E01 XLIII XLIV 44 # ==================================== 45 # === Aktiverer tjenester 46 47 # === Automatisk kobling til nett 48 systemctl enable netctl -auto@wlan0.service 49 50 # === Tjeneste for å logge inn bruker 51 systemctl enable slim.service 52 53 # === Apache 54 systemctl enable httpd.service 55 56 # === mySQL 57 systemctl enable mysqld.service 58 59 # === Bonjour 60 systemctl enable avahi-daemon.service 61 62 # === Samba 63 systemctl enable smbd.service nmbd.service 64 65 66 # ==================================== 67 # === Norsk oppsett 68 69 # === Laster inn norsk tastaturoppsett. 70 loadkeys no-latin1 71 # === Skriver det til fil, så det holder ved oppstart. 72 echo KEYMAP=no-latin1 > /etc/vconsole.conf 73 74 # === Aktiverer norsk og engelsk. 75 sed -i 's/\#en_US.UTF-8/en_US.UTF-8/g' /etc/locale.gen 76 sed -i 's\#nb_NO.UTF-8/nb_NO.UTF-8/g' /etc/locale.gen 77 78 # === Oppdaterer språkbanken. 79 locale -gen 80 # === Setter norsk som standard ved oppstart. 81 echo LANG=nb_NO.UTF-8 > /etc/locale.conf 82 # === Setter norsk språk i gjeldene økt. 83 export LANG=nb_NO.UTF-8 84 85 # === Endre til norsk tidsone. 86 rm /etc/localtime && ln -s /usr/share/zoneinfo/Europe/Oslo /etc/ localtime 87 88 89 # ==================================== 14. juni 2015 VEDLEGG J. POST-INSTALLERINGSSKRIPT ARCH LINUX 90 # === Diverse endringer 91 92 # === /etc/slim.conf 93 echo "default_user 94 echo "auto_login $NEW_USER" >> /etc/slim.conf yes" >> /etc/slim.conf 95 96 # === mySQL 97 mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql 98 mysql_secure_installation 99 mysql>create user ' $NEW_USER '@'%' identified by ' $NEW_USER '; 100 101 # === Apache 102 echo "LoadModule php5_module modules/libphp5.so" >> /etc/httpd/conf/ httpd.conf 103 echo "Include conf/extra/php5_module.conf" >> /etc/httpd/conf/httpd. conf 104 sed -i 's/LoadModule\ mpm_event_module modules\/mod_mpm_event\.so/ LoadModule\ mpm_prefork_module modules\/mod_mpm_prefork.so/g' /etc/ locale.gen 105 # 106 chown -R http:http /srv/http Gir bruker og gruppe http rettigheter til /srv/http 107 chmod -R 108 # Legg til brukeren i gruppen http 109 gpasswd --add 775 /srv/http $NEW_USER http 110 111 # === Samba 112 cp /etc/samba/smb.conf.default /etc/samba/smb.conf 113 echo "[HTTP]" >> /etc/samba/smb.conf 114 echo " comment = HTTP Root" >> /etc/samba/smb.conf 115 echo " path = /srv/http" >> /etc/samba/smb.conf 116 echo " browsable = yes" >> /etc/samba/smb.conf 117 echo " public = no" >> /etc/samba/smb.conf 118 echo " security = user" >> /etc/samba/smb.conf 119 echo " guest ok = no" >> /etc/samba/smb.conf 120 echo " read only = no" >> /etc/samba/smb.conf 121 echo " writeable = yes" >> /etc/samba/smb.conf 122 echo " create mask = 0775" >> /etc/samba/smb.conf 123 echo " directory mask = 0775" >> /etc/samba/smb.conf 124 125 pdbedit -a -u pi 126 127 128 # === xinitrc 129 echo "#!/bin/sh" > /home/$NEW_USER/.xinitrc 130 echo "" >> /home/$NEW_USER/.xinitrc 131 echo "if [ -d /etc/X11/xinit/xinitrc.d ] ; then" >> /home/$NEW_USER/. xinitrc H15E11 XLV XLVI 132 echo " for f in /etc/X11/xinit/xinitrc.d/?* ; do" >> /home/$NEW_USER/. xinitrc 133 echo ' 134 echo " done" >> /home/$NEW_USER/.xinitrc [ -x "\$f" ] && . "\$f"' >> /home/$NEW_USER/.xinitrc 135 echo " unset f" >> /home/$NEW_USER/.xinitrc 136 echo "fi" >> /home/$NEW_USER/.xinitrc 137 echo "" >> /home/$NEW_USER/.xinitrc 138 echo "# Skru av skjermbeskytter" >> /home/$NEW_USER/.xinitrc 139 echo "xset -dpms" >> /home/$NEW_USER/.xinitrc 140 echo "xset s off" >> /home/$NEW_USER/.xinitrc 141 echo "" >> /home/$NEW_USER/.xinitrc 142 echo "while true; d" >> /home/$NEW_USER/.xinitrc 143 echo "" >> /home/$NEW_USER/.xinitrc 144 echo "# Renske tidligere programmer" >> /home/$NEW_USER/.xinitrc 145 echo " killall -TERM chromium 2>/dev/null;" >> /home/$NEW_USER/. xinitrc 146 echo " killall -TERM matchbox -window -manager 2>/dev/null;" >> /home/ $NEW_USER/.xinitrc 147 echo " sleep 2;" >> /home/$NEW_USER/.xinitrc 148 echo " killall -9 chromium 2>/dev/null;" >> /home/$NEW_USER/.xinitrc 149 echo " killall -9 matchbox -window-manager 2>/dev/null;" >> /home/ $NEW_USER/.xinitrc 150 echo "" >> /home/$NEW_USER/.xinitrc 151 echo " # Gjem musepeker; ved å flytte den nede til høyre" >> /home/ $NEW_USER/.xinitrc 152 echo " xwit -root -warp \$( cat /sys/module/*fb*/parameters/fbwidth ) 153 echo "" >> /home/$NEW_USER/.xinitrc 154 echo " # Starte vindusbehandler." >> /home/$NEW_USER/.xinitrc 155 echo " matchbox -window -manager -use_titlebar no -use_cursor no &" >> / \$( cat /sys/module/*fb*/parameters/fbheight )" >> testt.txt home/$NEW_USER/.xinitrc 156 echo "" >> /home/$NEW_USER/.xinitrc 157 echo " # Starte nettleser" >> /home/$NEW_USER/.xinitrc 158 echo " chromium --noerrdialogs --incognito --kiosk http://localhost" >> /home/$NEW_USER/.xinitrc 159 echo "" >> /home/$NEW_USER/.xinitrc 160 echo "done;" >> /home/$NEW_USER/.xinitrc 161 162 163 # === Gi bruker eierskap over xinitrc. 164 chown $NEW_USER:$NEW_USER /home/$NEW_USER/.xinitrc 14. juni 2015
© Copyright 2024