Mobilt tidtakersystem

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: [email protected]
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 [email protected]
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