Heb je nog iets gevonden ?Complete code heb ik op dit moment niet. Ik zal in het weekend wel even kijken of ik iets kan vinden (wat bij mij werkt).
Want wat ik ook probeer ik kom helaas geen stap verder...
Heb je nog iets gevonden ?Complete code heb ik op dit moment niet. Ik zal in het weekend wel even kijken of ik iets kan vinden (wat bij mij werkt).
Want wat ik ook probeer ik kom helaas geen stap verder...
Last edited by MMSoft; 30-Oct-16 at 13:51.
Nee, de satallites (SENSOR_DATA_TYPE_SATELLITES_USED_COUNT) krijg ik niet uitgelezen.
Ik heb wel gemerkt dat, als je de SensorManager gebruikt om de LocationSensor uit te lezen, de Altitude NaN is als de GPS geen fix heeft. Ik weet niet of TLocationSensor ook Altitude heeft maar op die manier kun je wel zien of je een fix via de GPS hebt of via de GSM-torens/Wifi netwerken.
Ik heb deze regel erbij gezet
En deze geeft waardes van ca. 33,xxxx .... 63,xxxx.Code:Label6.Text := Format('%2.7f', [LocationSensor1.Sensor.Altitude]);
In het begin begreep ik niets van deze waardes, maar later leek het er steeds meer op dat deze de hoogte aan geeft.
Als ik een "berg op" rijdt wordt deze waarde namelijk hoger en "berg af" weer lager.
Ik heb niet het idee dat ik met deze waarde kan bepalen of er wel/geen GPS ontvangst is.
Ik neem aan dat als je geen gps-ontvangst hebt dat altitude NaN is. Want ik kan me geen sensor voorstellen die anders altitude terug geeft.
Ik ben ben wel al wat verder om de echte aantal satellites te tellen (met nmea-listener) maar mijn test-projectje crasht elke keer.
Het lijkt wel alsof je echt de enige bent die dit nodig heeft (en met Delphi doet)
In een tunnel bleef volgens mij de laatste waarde staan, maar heb dat helaas niet betrouwbaar kunnen zien (het was erg druk en had mijn aandacht op de weg nodig).Ik neem aan dat als je geen gps-ontvangst hebt dat altitude NaN is. Want ik kan me geen sensor voorstellen die anders altitude terug geeft.
Edit:
Maar had nog wel even tijd op om de toets 'Screen (shot)' te drukken
Hier ben ik in de Heinenoordtunnel, en de waarde is 36,4 (zie links onder).
Last edited by MMSoft; 31-Oct-16 at 20:52.
Ja, dat kan natuurlijk ook dat de laatste waarde blijft staan. Dan heb je echt de methode nodig om de satellieten weer te geven.
Welke SDK gebruik je in XE8?
In SDK 24 zijn wat dingen gewijzigd en JGPSStatus is deprecated.
Ik denk dat dat ook de reden is waarom ik de satellieten niet binnen kan halen.
Alternatief is JGnnsStatus (maar daar zie ik geen definities in Delphi voor) of NmeaListener (maar die geeft de data raw terug).
SDK 24.0.2 32 BitsWelke SDK gebruik je in XE8?
Ok. Dan zul je waarschijnlijk nieuwe android header files moeten gebruiken (waar gnss_status in staat). In SDK 24 is nogal wat gewijzigd en ik zag dus dat gpsstatus deprecated was.
Ik heb nieuwe headers gevonden op github van fmxexpress die zouden moeten werken maar ik ben nog aan het kijken hoe ik die in moet passen.
Was je hier nog iets verder mee gekomen ?
Ik krijg de android-n header files niet aan de gang in Delphi. Ik blijf een probleem met de interface hebben. Ik heb nog wel een andere methode gevonden en die ga ik straks even proberen.
Anders zal ik even verder kijken naar de nmea-listener methode om de satellieten in een string te krijgen (want die werkte wel bij mij maar is wat lastiger).
Hoor je vanmiddag meer over.
Wel... Ik krijg de JGpsStatus.getSatellites (iterator) niet aan de gang. Het lijkt wel of deze functie gewoon niet meer gebruikt kan worden (ondanks dat ie er nog wel in zit voor compatibiliteit maar in SDK 24 depreacated is).
De nieuwe methode voor SDK 24 via de JGnssStatus.getNumSatellites krijg ik ook niet aan de gang. De FMXExpress android-object-pascal-wrapper voor SDK 24 (android-n) zijn niet bepaald compatible met Delphi 10.1 Berlin. En in 10.1 en ouder zit die hele Gnns nog helemaal niet. Die krijg ik dus niet aan de praat. Dan zie je dus hoe belangrijk het zou zijn om je Delphi up-to-date te houden en dan zelfs nog heb je oude header-files.
Blijven 2 methodes over. De eerste is alleen de tijd van de laatst geldende fix oproepen. Dit is vrij simpel en wanneer je laatste fix ouder dan bijvoorbeeld een minuut is kun je zeker zijn dat je de fix echt verloren hebt. De tweede methode is een NmeaListener die raw-regels teruggeeft over de GPS positie en satellieten.
Hieronder een form-unit die beide methodes doet:
Je ziet een dummy TLocationListener die eigenlijk niets doet maar volgens mij is die nodig om de GPS aan te slingeren en om gegevens daarvan terug te krijgen. Alleen een NmeaListener aan de FLocationManager hangen werkte bij mij niet.
Daarna hangen we de NmeaListener aan de FLocationManager om de raw-regels van de GPS te krijgen.
In de timer halen we een getLastKnownLocation van de FLocationManager op om alleen puur het tijdstip van de laatste fix op te halen. Als je dus helemaal niets met de satallieten wilt doen dan kun je de hele NmeaListener eruit slopen.
Ik kreeg helaas bij de laatste keer testen alleen een GPRMC-message binnen. Je zou eigenlijk ook andere GPGSV-messages moeten krijgen waar de satellieten zelf in staan. Dat had ik met een ander test-programma wel voor elkaar maar hier lukte dat niet. Als je de satellieten zelf wilt hebben dan kan ik daar nog wel even naar kijken. Ik heb ook code om die GPGSV te parsen naar echte satelliet-data.
Delphi Code:
unit Unit5; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo; type TForm5 = class(TForm) Panel1: TPanel; Button1: TButton; Memo1: TMemo; Timer1: TTimer; procedure Button1Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form5: TForm5; implementation {$R *.fmx} uses StrUtils, Androidapi.JNI.JavaTypes, Androidapi.JNIBridge, Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android, Androidapi.JNI.Os, Androidapi.JNI.Location; type TLocationListener = class(TJavaLocal, JLocationListener) public procedure onLocationChanged(Location: JLocation); cdecl; procedure onProviderDisabled(Provider: JString); cdecl; procedure onProviderEnabled(Provider: JString); cdecl; procedure onStatusChanged(Provider: JString; status: Integer; extras: JBundle); cdecl; end; TNmeaListener = class(TJavaLocal, JGpsStatus_NmeaListener) public procedure onNmeaReceived(timestamp: Int64; nmea: JString); cdecl; end; var FLocationManager: JLocationManager; LocationListener: JLocationListener; NmeaListener: JGpsStatus_NmeaListener; SharedString: String = ''; procedure TForm5.Button1Click(Sender: TObject); var LocationManagerService: JObject; Location: JLocation; begin Memo1.Lines.Clear; LocationManagerService := SharedActivityContext.getSystemService(TJContext.JavaClass.LOCATION_SERVICE); FLocationManager := TJLocationManager.Wrap((LocationManagerService as ILocalObject).GetObjectID); LocationListener := TLocationListener.Create; NmeaListener := TNmeaListener.Create; FLocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 1000, 1, LocationListener, TJLooper.JavaClass.getMainLooper); try CallInUIThreadAndWaitFinishing( procedure begin FLocationManager.addNmeaListener(NmeaListener); end); except // message : "java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()" on E: Exception do Memo1.Lines.Add(E.Message); end; Location := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER); end; procedure TLocationListener.onLocationChanged(Location: JLocation); cdecl; begin end; procedure TLocationListener.onProviderDisabled(Provider: JString); cdecl; begin end; procedure TLocationListener.onProviderEnabled(Provider: JString); cdecl; begin end; procedure TLocationListener.onStatusChanged(Provider: JString; status: Integer; extras: JBundle); cdecl; begin end; procedure TNmeaListener.onNmeaReceived(timestamp: Int64; nmea: JString); cdecl; begin SharedString := JStringToString(nmea); end; procedure TForm5.Timer1Timer(Sender: TObject); var Location: JLocation; lastFixTimeMillis: Int64; begin if SharedString <> '' then begin Memo1.Lines.Add(SharedString); Memo1.GoToTextEnd; SharedString := ''; end; if Assigned(FLocationManager) then begin Location := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER); lastFixTimeMillis := Location.getTime(); Memo1.Lines.Add('Last fix: ' + DateTimeToStr(lastFixTimeMillis / 86400000.0 + 25569.0)); Memo1.GoToTextEnd; end; end; end.
Eindelijk heb ik de JGpsStatus.getSatellites ook aan de gang gekregen (ondanks het feit dat die deprecated is en in toekomstige versies zal verwijnen).
Ik weet niet of je dus ook echt de locatie van de satellieten nodig hebt (en welke in de fix gebruikt worden) of dat de lastFix-tijdstip voldoende is.
Die lastFix tijdstip geeft natuurlijk wel aan dat als je de resolutie op 1000 ms zet (voor requestupdates) zoals in het voorbeeld, je elke 1000ms ook een nieuwe fix moet hebben. Mocht je dus een paar seconden geen fix krijgen dan weet je al dat er wat aan de hand is.
Hier nogmaals de code met de JGpsStatus.getSatellites.
(Ik heb gewerkt met globale variabele omdat ik niet wilde knoeien met GUIThreads e.d. Niet zo mooi maar het werkt wel)
Die hele NmeaListener kun je er dan uit slopen want die is niet meer nodig als je via JGpsStatus bij de satellieten kunt.
Delphi Code:
unit Unit5; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo; type TForm5 = class(TForm) Panel1: TPanel; Button1: TButton; Memo1: TMemo; Timer1: TTimer; procedure Button1Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form5: TForm5; implementation {$R *.fmx} uses StrUtils, Androidapi.JNI.JavaTypes, Androidapi.JNIBridge, Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android, Androidapi.JNI.Os, Androidapi.JNI.App, Androidapi.JNI.Location; type TLocationListener = class(TJavaLocal, JLocationListener) public procedure onLocationChanged(Location: JLocation); cdecl; procedure onProviderDisabled(Provider: JString); cdecl; procedure onProviderEnabled(Provider: JString); cdecl; procedure onStatusChanged(Provider: JString; status: Integer; extras: JBundle); cdecl; end; TGpsListener = class(TJavaLocal, JGpsStatus_Listener) public procedure onGpsStatusChanged(event: Integer); cdecl; end; TNmeaListener = class(TJavaLocal, JGpsStatus_NmeaListener) public procedure onNmeaReceived(timestamp: Int64; nmea: JString); cdecl; end; var FLocationManager: JLocationManager; LocationListener: JLocationListener; NmeaListener: JGpsStatus_NmeaListener; GpsListener: JGpsStatus_Listener; SharedString: String = ''; cnt1, cnt2: Integer; procedure TForm5.Button1Click(Sender: TObject); var LocationManagerService: JObject; Location: JLocation; LPendingIntent: JPendingIntent; begin Memo1.Lines.Clear; LocationManagerService := SharedActivityContext.getSystemService(TJContext.JavaClass.LOCATION_SERVICE); FLocationManager := TJLocationManager.Wrap((LocationManagerService as ILocalObject).GetObjectID); LocationListener := TLocationListener.Create; GpsListener := TGpsListener.Create; NmeaListener := TNmeaListener.Create; // LPendingIntent := TJPendingIntent.JavaClass.init(SharedActivityContext.getPackageName(), StringToJString(Application.Name)); // FLocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 1000, 1, LPendingIntent); FLocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 1000, 1, LocationListener, TJLooper.JavaClass.getMainLooper); try CallInUIThreadAndWaitFinishing( procedure begin FLocationManager.addGpsStatusListener(GpsListener); FLocationManager.addNmeaListener(NmeaListener); end); except // message : "java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()" on E: Exception do Memo1.Lines.Add(E.Message); end; Location := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER); end; procedure TLocationListener.onLocationChanged(Location: JLocation); cdecl; begin end; procedure TLocationListener.onProviderDisabled(Provider: JString); cdecl; begin end; procedure TLocationListener.onProviderEnabled(Provider: JString); cdecl; begin end; procedure TLocationListener.onStatusChanged(Provider: JString; status: Integer; extras: JBundle); cdecl; begin end; procedure TGpsListener.onGpsStatusChanged(event: Integer); cdecl; var _GpsStatus: JGpsStatus; iter: JIterator; sat: JGpsSatellite; begin if event = 4 then begin _GpsStatus := FLocationManager.getGpsStatus(nil); cnt1 := 0; cnt2 := 0; iter := _GpsStatus.getSatellites.iterator; while iter.hasNext do begin inc(cnt1); sat := TJGpsSatellite.Wrap((iter.next as ILocalObject).GetObjectID); if (sat.usedInFix()) then Inc(cnt2); end; end; // [url]http://stackoverflow.com/questions/9924747/how-many-satellite-are-used-in-my-every-time-gps-fix[/url] end; procedure TNmeaListener.onNmeaReceived(timestamp: Int64; nmea: JString); cdecl; begin SharedString := JStringToString(nmea); end; procedure TForm5.Timer1Timer(Sender: TObject); var Location: JLocation; lastFixTimeMillis: Int64; numsat: String; LIntent: JIntent; LExtras: JBundle; I: Integer; begin if SharedString <> '' then begin Memo1.Lines.Add(SharedString); Memo1.GoToTextEnd; SharedString := ''; end; if Assigned(FLocationManager) then begin Location := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER); lastFixTimeMillis := Location.getTime(); numsat := ''; LExtras := Location.getExtras(); if LExtras <> nil then begin numsat := format(' %d sats', [LExtras.getInt(StringToJString('satellites'))]); end; numsat := numsat + format(' (%d of %d)', [cnt2, cnt1]); Memo1.Lines.Add('Last fix: ' + DateTimeToStr(lastFixTimeMillis / 86400000.0 + 25569.0) + numsat); Memo1.GoToTextEnd; end; end; end.
Met al die code raak ik het spoor een beetje kwijt...
Ik heb alleen (tja makkelijk gezegd) een bitje nodig dat hoog of laag wordt als er geen betrouwbaar GPS ontvangst is.
En deze code mag voor mij zo klein (en eenvoudig) mogelijk zijn en moet later als ik ooit overstap op een nieuwere versie ook nog werken.
Je heb inmiddels al van alles geprobeerd en getest (daarvoor dank), welke manier lijkt je daarvoor het beste ?
Voor de route wordt een .itn bestand gebruikt, maar ik heb nu in de App ook een database(je) opgenomen waarin adressen staan waarvan ik "iets" wil onthouden.
Er zijn adressen bij waar ik soms lange tijd niet kom. Als ik op zo'n adres kom (er wordt daarbij naar de postcode gekeken), dan krijg ik de straat met huis nummer, en de opmerking te zien (zie links boven het compas).
Tevens moet ik nog wel eens op een andere plaats zijn dan bij de voordeur en heb ik nu ook de mogelijkheid om een GPS positie er in te zetten, en deze kan ik dan meteen als navigatie positie gebruiken door op de toets "GPS->NAV" te drukken (deze toets is alleen acties als er een GPS positie aanwezig is in de database).
Dit heb ik vandaag getest, en dit werkt goed.
Wat zou het geweldig zijn als er ooit nog een wegenkaart erbij geplaatst kan worden....
Last edited by MMSoft; 07-Nov-16 at 20:02.
Ik zal, wanneer ik even tijd heb, kijken of ik dit in een wat simpelere library te zetten zodat het met een paar regels gebruikt kan worden.
Wat betreft je plattegrond. Er zijn wel wat mogelijkheden maar de map-data gedetailleerd opslaan voor heel Nederland kan behoorlijk veel ruimte in beslag nemen. Tevens is het tekenen daarvan geen simpele opgave. Als je internet toegang hebt tijdens het rijden dan zou het makkelijker zijn om een google-map of openstreet-map binnen te halen.
Je zou op diezelfde manier ook een versimpelde route(-planner) weer kunnen geven.
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks