Gps


We just need to follow the 1 and 2 steps, except in Pocket PC that we will need also following the step 3.
To add GPS support to any application, we advise COPYING AND PASTING the next code with the DB structure we already have working in other projects and that it can be seen at the following collections definition:


iOS EXCLUSIVE NODES

By default, iOS uses its own Apple location services, if we want to use those from the Google ones, we must specify the two attributes which are described below. THEY ARE ATTRIBUTES OF THE APP NODE..

ATTRIBUTEDESCRIPTION
google-api-enabletrue or false. By default, iOS uses the Apple service to locate the coordinates we are going to show in a contents of mapview type. If we want to use the Google APIs to show a better location and that the location be exactly the same than in Android, we should put this attribute to true.
google-api-keyHere, we will put the API key value that Google provides us to be able to use its services, if the previous attribute is to true, here, a value we will have to specify .



Definition of the collections.

<!-- La SQL no se mira, simplemente hay que tener una puesta.  -->	
<coll name="ConectarGPS" title="el conector" sql="SELECT t1.* FROM ##PREF##empresa t1" objname="ConectarGPS"
	updateobj="ConectarGPS" progid="ASData.CASBasicDataObj" stringkey="true"
	idfieldname="LONGITUD" connection="transmision" useextdata="true">
	<group name="General" id="1"/>
	<connection name="transmision" connstring="Provider=CGSoft Remote Provider;Data Source=127.0.0.1;Port=4242;ProgID=CGSSocketCE.ConnectCE"/>
	<prop name="LONGITUD" visible="0" type="T" size="12"/>
	<prop name="LATITUD" visible="0" type="T" size="12"/>
	<prop name="RUMBO" visible="0" type="T" size="12"/>
	<prop name="FGPS" visible="0" type="T" size="12"/>
	<prop name="HGPS" visible="0" type="T" size="12"/>
	<prop name="STATUS" visible="0" type="T" size="12"/>
</coll>
 
<!-- Esta segunda colección, si los datos se graban en otra tabla, no es necesaria  -->	
<coll name="CoordenadasGPS" title="la Coordenada" sql="SELECT c.*,
	u.NOMBRE AS MAP_USUARIO
	FROM ##PREF##coordenadasgps c
	LEFT OUTER JOIN ##PREF##usuarios u ON c.IDUSUARIO=u.ID" 
	objname="coordenadasgps" updateobj="coordenadasgps" progid="ASData.CASBasicDataObj"
	show-map="true" sort="FECHAHORAGPS" nostopreplica="true" check-owner="false" dependent="false">
	<group name="General" id="1"></group>
	<prop name="IDEMPRESA" visible="0" type="N" mapcol="Empresas" mapfld="ID"></prop>
	<prop name="IDUSUARIO" visible="0" type="N" mapcol="Usuarios" mapfld="ID"></prop>
	<prop name="ADDRESS" visible="7" type="T" fieldsize="30" size="100" mapview-address="true">Dirección:</prop>
	<prop name="DESCRIPCION" visible="7" type="T" fieldsize="30" size="100" mapview-description="true">Descripción:</prop>
	<prop name="LATITUDGPS" visible="0" group="1" type="N6" fieldsize="10" mapview-latitude="true" showmap-latitud="true"></prop>
	<prop name="LONGITUDGPS" visible="7" group="1" type="N6" fieldsize="10" mapview-longitude="true" showmap-longitud="true"></prop>
	<prop name="RUMBOGPS" visible="7" group="1" type="N6" fieldsize="10"></prop>
	<prop name="FECHAHORAGPS" visible="7" group="1" type="D" fieldsize="10" showmap-datetime="true"></prop>
	<prop name="FECHAHORAPDA" visible="7" group="1" type="D" fieldsize="10"></prop>
	<!-- no visibles -->
	<prop name="OPCIONES" labelwidth="7" visible="0" group="1" type="N" fieldsize="14"></prop>
	<prop name="OP1" visible="0" group="1" type="N" fieldsize="5">DIAS</prop>
	<create>
		<action name="setval" field="IDEMPRESA" value="##ENTID##"></action>
		<action name="setval" field="IDUSUARIO" value="##USERID##"></action>
		<action name="setval" field="FECHAHORAPDA" value="##NOW_TIME##"></action>
		<action name="setval" field="OPCIONES" value="0"></action>
	</create>
</coll>


  • The conectargps collection, is an special collection which gets data from the internal GPS of the device and it shows them in the form of a collection, so that we can call it at any time.


  • The second collection coordenadasgps, is a collection that we use in some projects to save the data of the position, as we can see at the step 2, we use the maintenance node to save the data of the GPS position each minute in this collection, although as we have already said, we can call the conectargps collection at any time and taking its values when and how we want to, there is no reason to use this second collection or the maintenance node neither.



Before the data collection, we must start the GPS of the device, for this, we are going to use the onlong and onlogoff nodes of the Companies collection, so that the GPS will start when entering at the application and it stops when we leaving it.

<onlogon>
	<action name="runscript">
		<script language="VBScript">
			AppData.UserInterface.StartGPS
		</script>
	</action>
</onlogon>
 
<onlogoff>
	<action name="runscript">
		<script language="VBScript">
			AppData.UserInterface.StopGPS
		</script>
	</action>
</onlogoff>


Following, we are going to read the GPS data, for this, we are going to use the <maintenance> node, which will be within the Companies Collection .

This is an action to make the GPS reading that the PDA has, which coordinates will be saved in database.
This script is associated to the two collections described at the step 1.

Setting the period and frequency values to the desired values. .

<maintenance>
    <action name="Lectura GPS" type="runscript" period="X" frecuency="1" auto="true" show="false">
	<script language="VBScript">
		Dim collGPS,tablagps,obj
		Set collGPS =appdata.GetCollection("ConectarGPS")
		Set x =collGPS("LONGITUD")
		if not x is nothing then
			if x("STATUS")="1" then
		  	' si status vale 1 significa que no hay error de conexion con el servicio
		  		if x("HGPS")&lt;&gt;"" then
					appdata.CurrentEnterprise.Variables("GPSError")=0
					Set tablagps =appdata.GetCollection("CoordenadasGPS")
					Set obj =tablagps.CreateObject
					if x("LATITUD")&lt;&gt;"" then obj("LATITUDGPS") =CDbl(x("LATITUD"))
					if x("LONGITUD")&lt;&gt;"" then obj("LONGITUDGPS") =CDbl(x("LONGITUD"))
					if x("RUMBO")&lt;&gt;"" then obj("RUMBOGPS") =CDbl(x("RUMBO"))
					if x("FGPS")&lt;&gt;"" then obj("FECHAHORAGPS") =x("FGPS")+" "+x("HGPS")
					tablagps.AddItem Empty,obj
					obj.save
					set obj =nothing
					tablagps.Clear
				end if
			else
				'appdata.CurrentEnterprise.Variables("GPSError")=1
				'appdata.failwithmessage -11888, "Hay un problema con la configuración GPS, consulte con su proveedor antes de continuar trabajando."
			end if
		else
			'appdata.writeconsolestring "GPS ERROR, x es nada"
		end if
		Set x =nothing
		collGPS.Clear
	</script>
    </action> 
</maintenance>       


EXAMPLE WITH JAVASCRIPT


<maintenance>
	<action name="Lectura GPS" type="runscript" period="X" frecuency="1" auto="true" show="false">
		<script language="javascript">
		   var collGPS, objCollGPS;
		    collGPS = appData.getCollection("ConectarGPS");
		    collGPS.startBrowse();
		    try {
		        objCollGPS = collGPS.getCurrentItem();
		        if (!objCollGPS) {
		            throw  "GPS no disponible. objCollGPS es: " + objCollGPS;
		            throw "ERROR";
		        }
		        if (objCollGPS.STATUS != 1) {
		            throw "GPS no disponible. STATUS vale: " + objCollGPS.STATUS;
		        }
		        if (!objCollGPS.LONGITUD) {
		            throw "Sin cobertura GPS";
		        }
		        var collDataGPS = appData.getCollection("CoordenadasGPS");
		        var objDataGPS = collDataGPS.createObject();
 
				collDataGPS.addItem(objDataGPS);
 
				objDataGPS.LATITUDGPS=objCollGPS.LATITUD;
				objDataGPS.LONGITUDGPS=objCollGPS.LONGITUD;
				objDataGPS.RUMBOGPS=objCollGPS.RUMBO;
				objDataGPS.FECHAHORAGPS=objCollGPS.FGPS+" "+objCollGPS.HGPS;
 
				objDataGPS.save();
 
				/*
		        self.MAP_ALTITUD = objCollGPS.ALTITUD;
		        self.MAP_VELOCIDAD = objCollGPS.VELOCIDAD;
		        self.MAP_STATUS = objCollGPS.STATUS;
		        self.MAP_SATELITES = objCollGPS.SATELITES;
		        self.MAP_FUENTE = objCollGPS.FUENTE;
		        self.MAP_PRECISION = objCollGPS.PRECISION;
		        */
		    } finally {
		        collGPS.endBrowse();
		    }	
		</script>
	</action> 
</maintenance>   	




The GPS module will be a xonegps.exe process. In order it boots when starting the device, or it is saved at the Start Up folder from Windows, or a direct access to that executable is created.


It is not necessary any key in the record for its configuration. Anyways, so that the application can be connected to the GPS module, it makes it through the ports by default, which are the 4242 for reading, and 4244 for stopping.

These can be modified from the record, but it is not necessary to modify them:


“HKLM”,“SOFTWARE\CGSoft\GPS”,“Port”,“0x00000000”,“4242” “HKLM”,“SOFTWARE\CGSoft\GPS”,“portstop”,“0x00000000”,“4244”



It would be a coll with the connection node, in which the connstring atribute is specified the port to read ( 4242 ) and the data source.

<coll name="ConectarGPS" stopreplica="3" sql="SELECT * FROM ##PREF##Empresa" objname="ConectarGPS" updateobj="ConectarGPS" progid="ASData.CASBasicDataObj" stringkey="true" idfieldname="LONGITUD" connection="transmision" loadall="false" withopen="true" useextdata="true" fontsize="9">
  <connection name="transmision" connstring="Provider=CGSoft Remote Provider;Data Source=127.0.0.1;Port=4242;ProgID=CGSSocketCE.ConnectCE"/>
  <prop name="LONGITUD" visible="3" type="T" size="12"/>
  <prop name="LATITUD" visible="3" type="T" size="12"/>
  <prop name="RUMBO" visible="3" type="T" size="12"/>
  <prop name="FGPS" visible="3" type="D" size="12"/>
  <prop name="HGPS" visible="3" type="T" size="12"/>
  <prop name="STATUS" visible="3" type="T" size="12"/>
  <prop name="SATELITES" visible="3" type="N" size="12"/>
  <prop name="VELOCIDAD" visible="3" type="T" size="12"/>
</coll>


Code from Script for the data capture:

     Set collGPS=appdata.GetCollection("ConectarGPS")
     Set x=collGPS("LONGITUD")
            . . .



In this case, another coll is defined, where the stopping port is specified, the 4244.


<coll name="stopGPS" stopreplica="3" sql="" objname="stopGPS" updateobj="stopGPS" progid="ASData.CASBasicDataObj" stringkey="true" idfieldname="STATUS" connection="tstop" loadall="false" withopen="true" useextdata="true" fontsize="9">
  <connection name="tstop" connstring="Provider=CGSoft Remote Provider;Data Source=127.0.0.1;Port=4244;ProgID=CGSSocketCE.ConnectCE"/>
  <prop name="STATUS" visible="3" type="T" size="12"/>
</coll>


Script code:

Set collGPS=appdata.GetCollection("stopGPS")
Set x=collGPS("STATUS")
      collGPS.clear
      collGPS = nothing
            . . .


Function to check the GPS status (only Android)


result = ui.CheckGPSStatus
if result = 0 then
	ui.MsgBox "El dispositivo no tiene características de localización", "Error", 0
end if
if result = 1 then
	ui.MsgBox "La localización precisa mediante GPS está habilitado", "Mensaje", 0
end if
if result = 2 then
	ui.MsgBox "La localización imprecisa mediante redes WiFi está habilitada", "Mensaje", 0
end if
if result = 3 then
	ui.MsgBox "No hay habilitado ningún método de localización", "Mensaje", 0
end if
if result = -1 then
	ui.MsgBox "Error inesperado al comprobar características de localización", "Mensaje", 0
end if


Functions of Position Cache (only Android)


Dim a
a = ui.GetLastKnownLocation

Si el GPS está activo, devuelve una cadena con la última posición conocida, la haya capturado el framework o cualquier otro programa.

Dim a
a = ui.GetLastKnownLocationLatitude
a = ui.GetLastKnownLocationLongitude
a = ui.GetLastKnownLocationAltitude
a = ui.GetLastKnownLocationAccuracy


Same than the previous one, but it returns only the latitude, longitude, height and the accuracy of each one of these methods.



Before saving any client address, for instance, we can make a validation to know if that address has a coordinates that can be get from the Google Maps API, so that we can save also the coordinates to be able to locate it easily in a map.


 var dirgoogle=self.MAP_valueDIRECCION; // Texto con la dirección
 dirgoogle=dirgoogle.replace(/ /g,"+");
 dirgoogle="https://maps.googleapis.com/maps/api/geocode/json?address=" + dirgoogle + "&key=TuAPIKeyGoogleMaps&language=es";
  $http.post(dirgoogle, function(sJson) {
  var objRespuesta = JSON.parse(sJson);
  //ui.showToast(sJson);
  if (objRespuesta["status"]=="OK") {
      self.MAP_DIRECCION=self.MAP_valueDIRECCION;
      self.MAP_LATITUD=objRespuesta.results[0].geometry.location.lat;
      self.MAP_LONGITUD=objRespuesta.results[0].geometry.location.lng;
      self.MAP_NOHAYDIR=0;
      self.save();
  }
  else {
      self.MAP_DIRECCION="DIRECCION-NO-VALIDA";
      self.MAP_NOHAYDIR=1;
      self.save();
  }
  }, function() {
  self.MAP_DIRECCION="DIRECCION-NO-VALIDA";
  self.MAP_NOHAYDIR=1;
  self.save();
 });




It indicates you the GPS current status in the device, the possible values that it return are:


value 0 There is no GPS, it cannot be enabled.
value 1 It is enabled the GPS location.
value 2 It is enabled the location by wifi and phone networks.
value 3 The GPS is not enabled nor the location by wifi and phone networks.
value 4 The GPS location is enabled and the location by wifi and phone networks.
value -1 Unexpected error.


Example:

	nStatus = ui.CheckGPSStatus
If nStatus = 0 then
            ui.ShowToast "No hay GPS, no se puede activar."
End If
If nStatus = 1 then
            ui.ShowToast "Está activada la localización por GPS."
End If
If nStatus = 2 then
            ui.ShowToast "Está activada la localización por redes wifi y de telefonía."
End If
If nStatus = 3 then
            ui.ShowToast "No está activado el GPS ni la ubicación por redes wifi y telefonía, a ver si nos lo activan."
            ui.AskUserForGPSPermission
End If
If nStatus = 4 then
            ui.ShowToast "Está activada la localización por GPS., a ver si nos lo activan y está activada la localización por redes wifi y de telefonía."
End If
If nStatus = -1 then
            ui.ShowToast "Error inesperado, compruebe la consola de mensajes."
End If



It is useful to launch the configuration window of the GPS location in the devices.


Example:

nStatus = ui.CheckGPSStatus
If nStatus = 0 then
            ui.ShowToast "No hay GPS, no se puede activar."
End If
If nStatus = 1 then
            ui.ShowToast "Está activada la localización por GPS."
End If
If nStatus = 2 then
            ui.ShowToast "Está activada la localización por redes wifi y de telefonía."
End If
If nStatus = 3 then
            ui.ShowToast "No está activado el GPS ni la ubicación por redes wifi y telefonía, a ver si nos lo activan."
            ui.AskUserForGPSPermission
End If
If nStatus = 4 then
            ui.ShowToast "Está activada la localización por GPS., a ver si nos lo activan y está activada la localización por redes wifi y de telefonía."
End If
If nStatus = -1 then
            ui.ShowToast "Error inesperado, compruebe la consola de mensajes."
End If



It starts the coordinates capture, another ways of activation have been added.

startGpsThey call to a node when a specified time is passed.
Parameter 1Name of the node that it will call. This node is defined in the companies collection.
Parameter 2Time that it will take in taking coordinates and call to the node (milliseconds).


It modifies the behaviour level:

value 0The most important thing is to capture the coordinates. It is of highest availability. Value by defautl (by default).
value 1It is a balance between capture and the battery. It tries to detect the best system for balancing reliability and battery.
value 2It is to save battery. Besides putting the configuration of battery saving, it only executes once the callback node and it has to be the one in charge of call again the stargps.


Example:

  ui.StartGPS "callbackgps", 10000, 0
  Definición del nodo en la colección empresas:
  <callbackgps>
        <action name="runscript">
        	<script language="vbscript">
             ui.showToast "callback..."
          </script>
        </action>
</callbackgps>


startGps when the last position differs from x km of the next one.
Parametersof JSON type, where the following properties are defined:
Property 1timeBetweenUpdates Time it will take to check again if the position has been changed.
Property 2minimumMetersDistanceRange Range of km that when exceeded the coordinates collect.


Example:

   ui.startGps({
                    timeBetweenUpdates : 0,
                    minimumMetersDistanceRange : 0
  });