added files for 2016 workshop
1
2016/android/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.idea
|
9
2016/android/Geofence/.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
.gradle
|
||||
.idea
|
||||
*.iml
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
2
2016/android/Geofence/app/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/build
|
||||
src/main/gen
|
37
2016/android/Geofence/app/build.gradle
Normal file
|
@ -0,0 +1,37 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 17
|
||||
buildToolsVersion "22.0.1"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "esrlabs.com.geofence"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 17
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.returnDefaultValues = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile('org.robolectric:robolectric:3.0-rc2') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
||||
}
|
||||
testCompile 'org.mockito:mockito-core:1.9.5'
|
||||
testCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||
compile project(':headunitinterface')
|
||||
}
|
17
2016/android/Geofence/app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/andreibechet/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
16
2016/android/Geofence/app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="esrlabs.com.geofence" >
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name">
|
||||
<service
|
||||
android:name="com.esrlabs.geofence.GeofenceApp"
|
||||
android:enabled="true"
|
||||
android:exported="true" >
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,19 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
public class CircleGeofence implements Geofence {
|
||||
|
||||
final Location center;
|
||||
final float radiusInMeters;
|
||||
|
||||
public CircleGeofence(Location center, float radiusInMeters) {
|
||||
this.center = center;
|
||||
this.radiusInMeters = radiusInMeters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsLocation(Location location) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
public interface Geofence {
|
||||
|
||||
public boolean containsLocation(Location location);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.esrlabs.headunitinterface.HeadUnit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static android.location.LocationManager.NETWORK_PROVIDER;
|
||||
import static com.esrlabs.geofence.Utils.location;
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* - register to the location provider
|
||||
* - connect to the HeadUnitService
|
||||
* - build geofence object
|
||||
* - implement the exercise logic (when the user is outside of the geofence show popup; hide it otherwise)
|
||||
*
|
||||
* See:
|
||||
* - that tests are green
|
||||
* - that the notification appears in the emulator
|
||||
*/
|
||||
public class GeofenceApp extends Service implements LocationListener {
|
||||
|
||||
public static final String TAG = "GeofenceApp";
|
||||
|
||||
private LocationManager locationManager;
|
||||
private Geofence geofence;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Log.d(TAG, "onCreate");
|
||||
|
||||
if (locationManager == null) {
|
||||
locationManager = (LocationManager)
|
||||
this.getSystemService(Context.LOCATION_SERVICE);
|
||||
}
|
||||
|
||||
initLocationListener();
|
||||
initHeadUnitService();
|
||||
|
||||
if (geofence == null) {
|
||||
final int someRadiusInMeters = 25;
|
||||
final Location someCenterForTheGeofence = location(NETWORK_PROVIDER, 48.118920, 11.601057);
|
||||
geofence = new CircleGeofence(someCenterForTheGeofence, someRadiusInMeters);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PolygonGeofence implements Geofence {
|
||||
|
||||
final List<Location> polygonPoints;
|
||||
|
||||
public PolygonGeofence(Location... locations) {
|
||||
polygonPoints = new ArrayList<Location>(Arrays.asList(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* It implements the Ray casting algorithm, with the convention that the line is horizontal and
|
||||
* goes from left to right.
|
||||
* @param location The point to be checked if is inside the defined polygon shaped geofence
|
||||
* @return True if the location is inside the defined polygon.
|
||||
*/
|
||||
@Override
|
||||
public boolean containsLocation(Location location) {
|
||||
int numberOfCorners = polygonPoints.size();
|
||||
|
||||
//adding the first corner at the end so that we can count the edge between last and first corners too
|
||||
List<Location> corners = new ArrayList<Location>(polygonPoints);
|
||||
corners.add(polygonPoints.get(0));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static Location location(String provider, double latitude, double longitude) {
|
||||
Location location = new Location(provider);
|
||||
location.setLatitude(latitude);
|
||||
location.setLongitude(longitude);
|
||||
location.setTime(System.currentTimeMillis());
|
||||
return location;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 7.5 KiB |
|
@ -0,0 +1,6 @@
|
|||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
5
2016/android/Geofence/app/src/main/res/values/dimens.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
</resources>
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">Geofence</string>
|
||||
</resources>
|
5
2016/android/Geofence/app/src/main/res/values/styles.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,40 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import esrlabs.com.geofence.BuildConfig;
|
||||
|
||||
import static android.location.LocationManager.NETWORK_PROVIDER;
|
||||
import static com.esrlabs.geofence.Utils.location;
|
||||
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
@Config(constants = BuildConfig.class, emulateSdk = 17)
|
||||
public class CircleGeofenceTest extends TestCase {
|
||||
public static final double distanceSmallerThanRadiusInDeg = 0.0001;
|
||||
public static final double distanceLargerThanRadiusInDeg = 0.001;
|
||||
|
||||
private static final float someRadiusInMeters = 100;
|
||||
private static final Location someCenterForTheGeofence = location(NETWORK_PROVIDER, 48.118920, 11.601057);
|
||||
public static final CircleGeofence someCircleGeofence = new CircleGeofence(someCenterForTheGeofence, someRadiusInMeters);
|
||||
|
||||
@Test
|
||||
public void testContainsLocation() throws Exception {
|
||||
assertTrue(someCircleGeofence.containsLocation(someLocationInside()));
|
||||
assertFalse(someCircleGeofence.containsLocation(someLocationOutside()));
|
||||
}
|
||||
|
||||
private Location someLocationInside() {
|
||||
return location(NETWORK_PROVIDER, someCenterForTheGeofence.getLatitude() + distanceSmallerThanRadiusInDeg, someCenterForTheGeofence.getLongitude());
|
||||
}
|
||||
|
||||
private Location someLocationOutside() {
|
||||
return location(NETWORK_PROVIDER, someCenterForTheGeofence.getLatitude() + distanceLargerThanRadiusInDeg, someCenterForTheGeofence.getLongitude());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.esrlabs.headunitinterface.HeadUnit;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowLocationManager;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import esrlabs.com.geofence.BuildConfig;
|
||||
|
||||
import static android.location.LocationManager.NETWORK_PROVIDER;
|
||||
import static com.esrlabs.geofence.CircleGeofenceTest.someCircleGeofence;
|
||||
import static com.esrlabs.geofence.Utils.location;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
@Config(constants = BuildConfig.class, emulateSdk = 17)
|
||||
public class GeofenceAppTest extends TestCase {
|
||||
private final LocationManager locationManager = (LocationManager)
|
||||
RuntimeEnvironment.application.getSystemService(Context.LOCATION_SERVICE);
|
||||
private final ShadowLocationManager shadowLocationManager = shadowOf(locationManager);
|
||||
private final Location someLocation = Utils.location(NETWORK_PROVIDER, 12.0, 20.0);
|
||||
private final AtomicBoolean notificationVisibility = new AtomicBoolean(false);
|
||||
|
||||
|
||||
private GeofenceApp geofenceApp;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
initHeadUnitServiceMock();
|
||||
setupGeofenceApp();
|
||||
}
|
||||
|
||||
private void initHeadUnitServiceMock() {
|
||||
IBinder headUnitStub = newTestHeadUnitServerBinder();
|
||||
shadowOf(RuntimeEnvironment.application).setComponentNameAndServiceForBindService(
|
||||
new ComponentName("com.esrlabs.headunitinterface", "HeadUnit"), headUnitStub);
|
||||
}
|
||||
|
||||
private IBinder newTestHeadUnitServerBinder() {
|
||||
return new HeadUnit.Stub() {
|
||||
@Override
|
||||
public void showNotification(String text) throws RemoteException {
|
||||
notificationVisibility.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideAllNotifications() throws RemoteException {
|
||||
notificationVisibility.set(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setupGeofenceApp() {
|
||||
GeofenceApp service = new GeofenceApp(locationManager, someCircleGeofence);
|
||||
service.onCreate();
|
||||
geofenceApp = service;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
geofenceApp.onDestroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReceiveTheLatestLocation() throws Exception {
|
||||
simulateNewLocation(someLocation);
|
||||
assertTrue(someLocation.equals(geofenceApp.latestLocation()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldShowPopupWhenTheCurrentLocationIsOutsideTheGeofence() throws Exception {
|
||||
Location locationInside = location(NETWORK_PROVIDER, someCircleGeofence.center.getLatitude() + CircleGeofenceTest.distanceSmallerThanRadiusInDeg,
|
||||
someCircleGeofence.center.getLongitude());
|
||||
simulateNewLocation(locationInside);
|
||||
assertTrue(locationInside.equals(geofenceApp.latestLocation()));
|
||||
assertFalse(notificationVisibility.get());
|
||||
|
||||
Location locationOutside = location(NETWORK_PROVIDER, someCircleGeofence.center.getLatitude() + CircleGeofenceTest.distanceLargerThanRadiusInDeg,
|
||||
someCircleGeofence.center.getLongitude());
|
||||
simulateNewLocation(locationOutside);
|
||||
assertTrue(locationOutside.equals(geofenceApp.latestLocation()));
|
||||
assertTrue(notificationVisibility.get());
|
||||
|
||||
Location nextLocationInside = location(NETWORK_PROVIDER, someCircleGeofence.center.getLatitude() + CircleGeofenceTest.distanceSmallerThanRadiusInDeg,
|
||||
someCircleGeofence.center.getLongitude());
|
||||
simulateNewLocation(nextLocationInside);
|
||||
assertTrue(nextLocationInside.equals(geofenceApp.latestLocation()));
|
||||
assertFalse(notificationVisibility.get());
|
||||
}
|
||||
|
||||
private void simulateNewLocation(Location someLocation) {
|
||||
shadowLocationManager.simulateLocation(someLocation);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
public class HeadUnitServiceMock extends Service {
|
||||
public static final String TAG = "HeadUnitServiceMockTest";
|
||||
|
||||
final IBinder headUnitStub;
|
||||
|
||||
public HeadUnitServiceMock(IBinder headUnitStub) {
|
||||
this.headUnitStub = headUnitStub;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
Log.i(TAG, "onBind");
|
||||
return headUnitStub;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.esrlabs.geofence;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import esrlabs.com.geofence.BuildConfig;
|
||||
|
||||
import static android.location.LocationManager.NETWORK_PROVIDER;
|
||||
import static com.esrlabs.geofence.CircleGeofenceTest.distanceLargerThanRadiusInDeg;
|
||||
import static com.esrlabs.geofence.Utils.location;
|
||||
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
@Config(constants = BuildConfig.class, emulateSdk = 17)
|
||||
public class PolygonGeofenceTest extends TestCase {
|
||||
// Test polygon defined physically like:
|
||||
// 48.119033, 11.601664 48.119051, 11.601766
|
||||
// 48.117726, 11.602404 48.117758, 11.602543
|
||||
public static final Location testPolygonTopRightCorner = location(NETWORK_PROVIDER, 48.119033, 11.601664);
|
||||
public static final Location testPolygonTopLeftCorner = location(NETWORK_PROVIDER, 48.119051, 11.601966);
|
||||
public static final Location testPolygonBottomRightCorner = location(NETWORK_PROVIDER, 48.116726, 11.602404);
|
||||
public static final Location testPolygonBottomLeftCorner = location(NETWORK_PROVIDER, 48.116758, 11.602743);
|
||||
public static final PolygonGeofence testGeofence = new PolygonGeofence(testPolygonTopRightCorner, testPolygonTopLeftCorner,
|
||||
testPolygonBottomRightCorner, testPolygonBottomLeftCorner);
|
||||
|
||||
@Test
|
||||
public void testContainsLocation() throws Exception {
|
||||
assertTrue(testGeofence.containsLocation(someLocationInside()));
|
||||
assertFalse(testGeofence.containsLocation(someLocationOutside()));
|
||||
}
|
||||
|
||||
private Location someLocationInside() {
|
||||
return location(NETWORK_PROVIDER, testPolygonTopRightCorner.getLatitude() - 0.001, testPolygonTopRightCorner.getLongitude() - 0.001);
|
||||
}
|
||||
|
||||
private Location someLocationOutside() {
|
||||
return location(NETWORK_PROVIDER, testPolygonTopRightCorner.getLatitude() + distanceLargerThanRadiusInDeg, testPolygonTopRightCorner.getLongitude());
|
||||
}
|
||||
}
|
22
2016/android/Geofence/build.gradle
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter {
|
||||
jcenter()
|
||||
//url "http://jcenter.bintray.com/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
18
2016/android/Geofence/gradle.properties
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
BIN
2016/android/Geofence/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
2016/android/Geofence/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
#Sun Jul 03 23:08:01 CEST 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
|
164
2016/android/Geofence/gradlew
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
90
2016/android/Geofence/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
1
2016/android/Geofence/headunitinterface/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
23
2016/android/Geofence/headunitinterface/build.gradle
Normal file
|
@ -0,0 +1,23 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 17
|
||||
buildToolsVersion "22.0.1"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 17
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
17
2016/android/Geofence/headunitinterface/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/flo/android-sdks/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -0,0 +1,13 @@
|
|||
package com.esrlabs.headunitinterface;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.esrlabs.headunitinterface">
|
||||
|
||||
<application android:allowBackup="true" android:label="@string/app_name">
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,9 @@
|
|||
// HeadUnit.aidl
|
||||
package com.esrlabs.headunitinterface;
|
||||
|
||||
interface HeadUnit {
|
||||
|
||||
void showNotification(String text);
|
||||
|
||||
void hideAllNotifications();
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">HeadUnitInterface</string>
|
||||
</resources>
|
1
2016/android/Geofence/headunitservicemock/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
27
2016/android/Geofence/headunitservicemock/build.gradle
Normal file
|
@ -0,0 +1,27 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "22.0.1"
|
||||
defaultConfig {
|
||||
applicationId 'com.esrlabs.headunitservice'
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
productFlavors {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:22.2.0'
|
||||
compile project(':headunitinterface')
|
||||
}
|
17
2016/android/Geofence/headunitservicemock/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/flo/android-sdks/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -0,0 +1,13 @@
|
|||
package com.esrlabs.headunitservice;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.esrlabs.headunitservice" >
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<service
|
||||
android:name=".HeadUnitService"
|
||||
android:enabled="true"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="com.esrlabs.headunitinterface.HeadUnit" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,52 @@
|
|||
package com.esrlabs.headunitservice;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.esrlabs.headunitinterface.HeadUnit;
|
||||
|
||||
/**
|
||||
* A test implementation of the HeadUnit interface
|
||||
*
|
||||
* Provides a way to run against the interface without the presence of a real headunit
|
||||
*
|
||||
* Will use the Android UI instead
|
||||
*/
|
||||
public class HeadUnitService extends Service {
|
||||
|
||||
public static final String TAG = "HeadUnitServiceMock";
|
||||
|
||||
public HeadUnitService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
Log.i(TAG, "onBind");
|
||||
return binder;
|
||||
}
|
||||
|
||||
private final HeadUnit.Stub binder = new HeadUnit.Stub() {
|
||||
@Override
|
||||
public void showNotification(String text) throws RemoteException {
|
||||
Log.i(TAG, "showNotification '" + text + "'");
|
||||
Notification.Builder builder = new Notification.Builder(getBaseContext()).setContentText(text).setSmallIcon(R.drawable.tum_logo);
|
||||
notificationService().notify(0,builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideAllNotifications() throws RemoteException {
|
||||
Log.i(TAG, "hideAllNotifications");
|
||||
notificationService().cancelAll();
|
||||
}
|
||||
};
|
||||
|
||||
private NotificationManager notificationService() {
|
||||
return (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 7.5 KiB |
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">HeadUnitServiceMock</string>
|
||||
</resources>
|
|
@ -0,0 +1,8 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
1
2016/android/Geofence/settings.gradle
Normal file
|
@ -0,0 +1 @@
|
|||
include ':app', ':headunitinterface', ':headunitservicemock'
|
|
@ -6,3 +6,71 @@ To be able to develop for android and run it in the simulator, you will need the
|
|||
- latest android sdk
|
||||
|
||||
You can find both [here](https://developer.android.com/studio/index.html)
|
||||
|
||||
# Display a notification on the headunit
|
||||
|
||||
In this task you have to create an android application which will use a geofence and the current location data in order to open/close a popup on the headunit.
|
||||
|
||||
## Receive the current location
|
||||
|
||||
Use the [android location manager](http://developer.android.com/reference/android/location/LocationManager.html) to request location updates. If the location is retrieved correctly, then the following test will pass.
|
||||
|
||||
```java
|
||||
GeofenceAppTest.shouldReceiveTheLatestLocation()
|
||||
```
|
||||
|
||||
## Bind to a remote service to be able to display notifications
|
||||
|
||||
Use the [AIDL](http://developer.android.com/guide/components/aidl.html) to allow interprocess communication between your app and another service which will allow you to display notifications. The AIDL you will use is *HeadUnit.aidl*. You are on the client side. You will need to bind to the service using an intent and a [ServiceConnection](http://developer.android.com/reference/android/content/ServiceConnection.html) object (see [here](http://developer.android.com/guide/components/aidl.html#Expose)).
|
||||
|
||||
```java
|
||||
Intent headUnitServiceIntent = new Intent(HeadUnit.class.getName());
|
||||
headUnitServiceIntent.setPackage("com.esrlabs.headunitservice");
|
||||
bindService(headUnitServiceIntent, serviceConnection_object, BIND_AUTO_CREATE);
|
||||
```
|
||||
|
||||
## Implement a circle geofence object to tell if the current is inside a designated area or not
|
||||
|
||||
The first step is to implement a circle geofence. You cannot use the google API because that is part of the play API, and it is not supported by our android controller. You have included in the test suite a test class for the circle geofence to help you.
|
||||
|
||||
The second step is to display a popup if the current location is outside of a given geofence (alternatively to close if the location is inside). If this is correctly implemented than all the tests should be green (**Note** that unless you are going for the bonus you should disable the test in the *PolygonGeofenceTest* class with *@Ignore* in front of the *@Test*).
|
||||
|
||||
For the circle geofence you should use this location as the center and radius of :
|
||||
|
||||
(48.262596, 11.668720) and radius of 25 meters
|
||||
|
||||
|
||||
## Observations
|
||||
|
||||
In order to ease testing dependancy injection has been used. That means to pass the objects our class will use via a constructor. In android, services are not constructed by the user, instead they are built internally. The needed things for the service to run are instantated during the *onCreate()* call. The constructor in the code is there just for testing purposes. For the functioning of the service you should do the following:
|
||||
|
||||
```java
|
||||
if (locationManager == null) {
|
||||
locationManager = (LocationManager)
|
||||
this.getSystemService(Context.LOCATION_SERVICE);
|
||||
}
|
||||
```
|
||||
and
|
||||
```java
|
||||
if (geofence == null) {
|
||||
geofence = myGeofence(...);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## **Bonus** Implement a polygon geofence instead
|
||||
|
||||
You can use the [Ray-casting algorithm](https://en.wikipedia.org/wiki/Point_in_polygon).
|
||||
|
||||
#### HINT
|
||||
|
||||
Use the slope of a straight line in order to tell if the ray starting from the given point and going in a fixed direction, intersects an edge of the polygon. Take care that *Math.atan()* return radians, and you will have to correct a negative angle:
|
||||
|
||||
```java
|
||||
90 + (90 - Math.abs(angle))
|
||||
```
|
||||
|
||||
For the polygon geofence you should use the following locations as the polygon's cornerns:
|
||||
|
||||
(48.262739, 11.668393), (48.262674, 11.668956), (48.262100, 11.668419), (48.262324, 11.670174)
|
||||
|
|
3
2016/ppc/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
gps/UnitTest
|
||||
.bake
|
||||
build_UnitTest
|
1
2016/ppc/.ruby-gemset
Normal file
|
@ -0,0 +1 @@
|
|||
inga
|
1
2016/ppc/.ruby-version
Normal file
|
@ -0,0 +1 @@
|
|||
2.1
|
|
@ -10,3 +10,91 @@ To be able to compile your solutions and execute the tests, you will need the fo
|
|||
|
||||
see https://esrlabs.github.io/bake/
|
||||
|
||||
# GPS on CAN
|
||||
|
||||
In this task you will need to receive Can-frames on the can-bus that contain the GPS location of the
|
||||
vehicle. The raw data has to be converted to arc-milliseconds
|
||||
|
||||
1°2'5" == (1*3600+ 2*60 + 5)*1000
|
||||
|
||||
**Beware that the system you are running your code on will not support floating point operations.
|
||||
Use only unsigned and signed integers!**
|
||||
Still the precision of your calculations has to be +-100 milli-arc-seconds
|
||||
|
||||
Dynamic allocation is not supported on the system.
|
||||
|
||||
You will have to complete the *GpsConverter.cpp* (and .h).
|
||||
|
||||
|
||||
## Conversion to Arc-Degree
|
||||
|
||||
inDegree hex = 180/(2^31-1) * (hex) [°]
|
||||
|
||||
#### HINT 1
|
||||
|
||||
Try to use constants as much as possible, isntead of computing stuff on the go.
|
||||
|
||||
#### HINT 2
|
||||
|
||||
In order to aviod losing decimals first multiply with a large factor and then divide to get the result in ms.
|
||||
|
||||
## GPS Datalayout in CAN Message
|
||||
|
||||
Byte7 ST_LAT_NAVI
|
||||
Byte6 ST_LAT_NAVI
|
||||
Byte5 ST_LAT_NAVI
|
||||
Byte4 ST_LAT_NAVI
|
||||
Byte3 ST_LONG_NAVI
|
||||
Byte2 ST_LONG_NAVI
|
||||
Byte1 ST_LONG_NAVI
|
||||
Byte0 ST_LONG_NAVI
|
||||
|
||||
## Byteorder
|
||||
|
||||
Little Endian (Least Significant Byte is at lowest address)
|
||||
|
||||
## Status Longitude Navigation
|
||||
|
||||
ST_LONG_NAVI
|
||||
|
||||
### Possible Values
|
||||
|
||||
-180° ... +180°
|
||||
|
||||
### Signal type
|
||||
|
||||
32 Bit Signed Integer (Byte 0 ... Byte 3)
|
||||
|
||||
### Invalid Data
|
||||
|
||||
Invalid-Value: 80 00 00 00
|
||||
|
||||
Signal not available value: 7F FF FF FF and FF FF FF FF
|
||||
|
||||
**Do not forget to check for these values**
|
||||
|
||||
## Status Latitude Navigation
|
||||
|
||||
ST_LAT_NAVI
|
||||
|
||||
### Possible Values
|
||||
|
||||
-180° ... +180°
|
||||
|
||||
### Signal type
|
||||
|
||||
32 Bit Signed Integer (Byte 4 ... Byte 7)
|
||||
|
||||
### Invalid Data
|
||||
|
||||
Invalid-Value: 80 00 00 00
|
||||
|
||||
Signal not available value: 7F FF FF FF and FF FF FF FF
|
||||
|
||||
## Send the data over to the AC
|
||||
|
||||
Use the *IGpsACPusher*.
|
||||
|
||||
## Running the tests
|
||||
|
||||
execute `rake run` from this directory
|
32
2016/ppc/common/include/commonTypes.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_TYPES_H
|
||||
#define COMMON_TYPES_H
|
||||
|
||||
/* standard types file to be used for
|
||||
* all C++ basic software components */
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long long int uint64;
|
||||
|
||||
typedef signed char sint8;
|
||||
typedef signed short sint16;
|
||||
typedef signed int sint32;
|
||||
typedef signed long long int sint64;
|
||||
|
||||
#else
|
||||
#include "Std_Types.h"
|
||||
|
||||
typedef volatile uint32 vuint32;
|
||||
typedef volatile uint32 vuint32_t;
|
||||
#endif
|
||||
|
||||
#endif /* COMMON_TYPES_H */
|
92
2016/ppc/common/include/util/CompileTimeConstraints.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef COMPILETIMECONSTRAINTS_H_
|
||||
#define COMPILETIMECONSTRAINTS_H_
|
||||
|
||||
#include "commonTypes.h"
|
||||
|
||||
#define ZGW_JOIN( X, Y ) ZGW_DO_JOIN( X, Y )
|
||||
#define ZGW_DO_JOIN( X, Y ) ZGW_DO_JOIN2(X,Y)
|
||||
#define ZGW_DO_JOIN2( X, Y ) X##Y
|
||||
|
||||
namespace common
|
||||
{
|
||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||
|
||||
# define ECU_STATIC_ASSERT( B ) \
|
||||
typedef char ZGW_JOIN(zgw_static_assert_typedef_, __LINE__) \
|
||||
[ ::common::STATIC_ASSERTION_FAILURE< (bool)( B ) >::value ]
|
||||
|
||||
template<bool Condition>
|
||||
struct CompileTimeError;
|
||||
|
||||
template<>
|
||||
struct CompileTimeError<false> {};
|
||||
|
||||
/**
|
||||
* STATIC_CHECK will fail when expr evaluates to true
|
||||
*/
|
||||
#define STATIC_CHECK(msg, expr) \
|
||||
{ common::CompileTimeError<(expr)> ERROR_##msg; (void)ERROR_##msg; }
|
||||
|
||||
/**
|
||||
* STATIC_ASSERT will fail when expr evaluates to false
|
||||
* simple usage: STATIC_ASSERT(too_bad_static_assert_failed, 2 > 3)
|
||||
*/
|
||||
#define STATIC_ASSERT(msg, expr) \
|
||||
{ common::CompileTimeError<!(expr)> ERROR_##msg; (void)ERROR_##msg; }
|
||||
|
||||
/**
|
||||
* another example-setup for compile-time-check: a class only has to inherit from this constraint,
|
||||
* so the constructor of this Constraint has to be compiled and the static check is executed
|
||||
* by the compiler.
|
||||
* will only compile if ACTUAL_SIZE <= ALLOWED_SIZE
|
||||
*
|
||||
* the argument passed to the STATIC_CHECK-macro can be any allowed C++-identifier,
|
||||
*/
|
||||
template<uint32 ACTUAL_SIZE, uint32 ALLOWED_SIZE>
|
||||
struct ValidSizeConstraint
|
||||
{
|
||||
static void constraint()
|
||||
{
|
||||
STATIC_CHECK(fuck_allowed_size_is_too_small,
|
||||
(ACTUAL_SIZE > ALLOWED_SIZE));
|
||||
}
|
||||
ValidSizeConstraint()
|
||||
{
|
||||
void (*p)() = constraint;
|
||||
(*p)();//call function, only to make compiler warning about unused variable go away, will get optimized away
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* static checks
|
||||
* usage:
|
||||
* struct B {}; struct D : B { };
|
||||
* ...Derived_from<D,B>();
|
||||
*/
|
||||
template<class T, class B> struct Derived_from
|
||||
{
|
||||
static void constraints(T* p) { B* pb = p; pb = pb;}
|
||||
Derived_from() { void(*p)(T*) = constraints; p = p;}
|
||||
};
|
||||
|
||||
template<class T1, class T2> struct Can_copy
|
||||
{
|
||||
static void constraints(T1 a, T2 b) { T2 c = a; b = a; c = a; b = a; }
|
||||
Can_copy() { void(*p)(T1,T2) = constraints;}
|
||||
};
|
||||
|
||||
template<class T1, class T2 = T1> struct Can_compare
|
||||
{
|
||||
static void constraints(T1 a, T2 b) { a==b; a!=b; a<b; }
|
||||
Can_compare() { void(*p)(T1,T2) = constraints;}
|
||||
};
|
||||
}//namespace common
|
||||
|
||||
#endif /*COMPILETIMECONSTRAINTS_H_*/
|
175
2016/ppc/common/include/util/SAlgorithm.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains STL like algorithms.
|
||||
* \file SAlgorithm.h
|
||||
* \ingroup sstl
|
||||
*/
|
||||
#ifndef SALGORITHM_H_
|
||||
#define SALGORITHM_H_
|
||||
|
||||
#include "SIteratorBaseTypes.h"
|
||||
|
||||
/**
|
||||
* returns minimum of two values
|
||||
* \param T type of values
|
||||
* \param t1 first value
|
||||
* \param t2 second value
|
||||
* \return minimum of t1 and t2
|
||||
*/
|
||||
template<typename T>
|
||||
inline const T& smin(const T& t1, const T& t2)
|
||||
{
|
||||
return (t1 < t2 ? t1 : t2);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns maximum of two values
|
||||
* \param T type of values
|
||||
* \param t1 first value
|
||||
* \param t2 second value
|
||||
* \return maximum of t1 and t2
|
||||
*/
|
||||
template<typename T>
|
||||
inline const T& smax(const T& t1, const T& t2)
|
||||
{
|
||||
return (t1 > t2 ? t1 : t2);
|
||||
}
|
||||
|
||||
/**
|
||||
* swaps two values
|
||||
* \param T type of values
|
||||
* \param t1 first value
|
||||
* \param t2 second value
|
||||
*/
|
||||
template<typename T>
|
||||
inline void sswap(T& t1, T& t2)
|
||||
{
|
||||
T t = t1;
|
||||
t1 = t2;
|
||||
t2 = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* finds a value in a given iterator range
|
||||
* \param InputIterator type of iterators
|
||||
* \param EqualityCompareable type of value to find
|
||||
* \param first begin of range
|
||||
* \param last and of range
|
||||
* \param value value to find in range
|
||||
* \return iterator to first element equal to value in range
|
||||
*/
|
||||
template<
|
||||
typename InputIterator,
|
||||
typename EqualityCompareable>
|
||||
inline InputIterator sfind(
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
const EqualityCompareable& value)
|
||||
{
|
||||
return sfind(
|
||||
first,
|
||||
last,
|
||||
value,
|
||||
typename SIteratorTraits<InputIterator>::iterator_category());
|
||||
}
|
||||
|
||||
/**
|
||||
* implementation of sfind for input iterators
|
||||
* \see sfind()
|
||||
*/
|
||||
template<
|
||||
typename InputIterator,
|
||||
typename EqualityCompareable>
|
||||
inline InputIterator sfind(
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
const EqualityCompareable& value,
|
||||
SInputIteratorTag)
|
||||
{
|
||||
while (!(first == last) && !(*first == value))
|
||||
{
|
||||
++first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes all elements equal to a value from a range and copies it to another
|
||||
* \param InputIterator type of input range iterators
|
||||
* \param OutputIterator type of result range iterator
|
||||
* \param EqualityCompareable type of value to remove from input range
|
||||
* \param first begin of input range
|
||||
* \param last end of input range
|
||||
* \param result begin iterator of result range
|
||||
* \param value value to remove
|
||||
* \return end of result range
|
||||
*/
|
||||
template<
|
||||
typename InputIterator,
|
||||
typename OutputIterator,
|
||||
typename EqualityCompareable>
|
||||
inline OutputIterator sremove_copy(
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator result,
|
||||
const EqualityCompareable& value)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
if (!(*first == value))
|
||||
{
|
||||
*result = *first;
|
||||
++result;
|
||||
}
|
||||
++first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes all elements of a given value from a range
|
||||
* \param ForwardIterator type of range iterator
|
||||
* \param EqualityCompareable type of value to remove
|
||||
* \param first begin of range
|
||||
* \param last end of range
|
||||
* \param value value to remove from range
|
||||
* \return iterator to result range
|
||||
*/
|
||||
template<
|
||||
typename ForwardIterator,
|
||||
typename EqualityCompareable>
|
||||
ForwardIterator sremove(
|
||||
ForwardIterator first,
|
||||
ForwardIterator last,
|
||||
const EqualityCompareable& value)
|
||||
{
|
||||
first = sfind(first, last, value);
|
||||
ForwardIterator i = first;
|
||||
return first == last ? first : sremove_copy(++i, last, first, value);
|
||||
}
|
||||
|
||||
template<
|
||||
typename InputIterator,
|
||||
typename EqualityComparable>
|
||||
typename SIteratorTraits<InputIterator>::difference_type scount(
|
||||
InputIterator first, InputIterator last,
|
||||
const EqualityComparable& value)
|
||||
{
|
||||
typename SIteratorTraits<InputIterator>::difference_type result = 0;
|
||||
while (first != last)
|
||||
{
|
||||
if (*first == value)
|
||||
{
|
||||
++result;
|
||||
}
|
||||
++first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /*SALGORITHM_H_*/
|
38
2016/ppc/common/include/util/SBaseTypes.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains basic type traits.
|
||||
* \file SBaseTypes.h
|
||||
* \ingroup sstl
|
||||
*/
|
||||
#ifndef SBASETYPES_H_
|
||||
#define SBASETYPES_H_
|
||||
|
||||
/**
|
||||
* type traits
|
||||
* \param T type to get traits from
|
||||
*
|
||||
* This class may be used to save some type work.
|
||||
*/
|
||||
template<typename T>
|
||||
struct STypeTraits
|
||||
{
|
||||
/** unsigned integral type */
|
||||
typedef unsigned int size_type;
|
||||
/** signed integral type */
|
||||
typedef signed int difference_type;
|
||||
/** type of T itsself */
|
||||
typedef T value_type;
|
||||
/** pointer to T */
|
||||
typedef T* pointer;
|
||||
/** reference to T */
|
||||
typedef T& reference;
|
||||
/** const reference to T */
|
||||
typedef const T& const_reference;
|
||||
};
|
||||
|
||||
#endif /*SBASETYPES_H_*/
|
141
2016/ppc/common/include/util/SIteratorBaseTypes.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains base types for iterators.
|
||||
* \file SIteratorBaseTypes.h
|
||||
* \ingroup sstl
|
||||
*/
|
||||
#ifndef SITERATORBASETYPES_H_
|
||||
#define SITERATORBASETYPES_H_
|
||||
|
||||
/**
|
||||
* input iterator
|
||||
*
|
||||
* \section Description
|
||||
* May advance through a iterator range. Reads each
|
||||
* value exactly one time.
|
||||
*/
|
||||
struct SInputIteratorTag {};
|
||||
|
||||
/**
|
||||
* output iterator
|
||||
*
|
||||
* \section Description
|
||||
* May advance through a iterator range and alter values.
|
||||
*/
|
||||
struct SOutputIteratorTag {};
|
||||
|
||||
/**
|
||||
* forward iterator
|
||||
*
|
||||
* \section Description
|
||||
* May advance through a iterator range and read each value
|
||||
* more than on time.
|
||||
*/
|
||||
struct SForwardIteratorTag : public SInputIteratorTag {};
|
||||
|
||||
/**
|
||||
* bidirectional iterator
|
||||
*
|
||||
* \section Description
|
||||
* May go through a iterator range in both directions and
|
||||
* read each value more than one time
|
||||
*/
|
||||
struct SBidirectionalIteratorTag : public SForwardIteratorTag {};
|
||||
|
||||
/**
|
||||
* random access iterator
|
||||
*
|
||||
* \section Description
|
||||
* May go through a iterator range like a pointer through an
|
||||
* array and read each value more than one time.
|
||||
*/
|
||||
struct SRandomAccessIteratorTag : public SBidirectionalIteratorTag {};
|
||||
|
||||
/**
|
||||
* optional base class for iterators
|
||||
* \param Category iterators category
|
||||
* \param T type iterator points to
|
||||
* \param Distance signed integral type
|
||||
* \param Pointer pointer to T
|
||||
* \param Reference reference to T
|
||||
*
|
||||
* Classes may subclass this class to save some typedef work.
|
||||
*/
|
||||
template<
|
||||
typename Category,
|
||||
typename T,
|
||||
typename Distance = signed int,
|
||||
typename Pointer = T*,
|
||||
typename Reference = T&>
|
||||
struct SIterator
|
||||
{
|
||||
/** the iterators category */
|
||||
typedef Category iterator_category;
|
||||
/** type of value iterator points to */
|
||||
typedef T value_type;
|
||||
/** signed integral type */
|
||||
typedef Distance difference_type;
|
||||
/** pointer to value type */
|
||||
typedef Pointer pointer;
|
||||
/** reference to value type */
|
||||
typedef Reference reference;
|
||||
};
|
||||
|
||||
/**
|
||||
* traits for iterators
|
||||
* \param Iterator iterator to generate traits for
|
||||
*/
|
||||
template<typename Iterator>
|
||||
struct SIteratorTraits
|
||||
{
|
||||
/** the iterators category */
|
||||
typedef typename Iterator::iterator_category iterator_category;
|
||||
/** type of value iterator points to */
|
||||
typedef typename Iterator::value_type value_type;
|
||||
/** signed integral type */
|
||||
typedef typename Iterator::difference_type difference_type;
|
||||
/** pointer to value */
|
||||
typedef typename Iterator::pointer pointer;
|
||||
/** reference to value */
|
||||
typedef typename Iterator::reference reference;
|
||||
};
|
||||
|
||||
/**
|
||||
* special implementation for pointers
|
||||
* \param T type of value for whose pointer traits are generated
|
||||
*
|
||||
* \see SIteratorTraits
|
||||
*/
|
||||
template<typename T>
|
||||
struct SIteratorTraits<T*>
|
||||
{
|
||||
typedef SRandomAccessIteratorTag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef signed int difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
};
|
||||
|
||||
/**
|
||||
* special implementation for const pointers
|
||||
* \param T type of value for whose const pointer traits are generated
|
||||
*
|
||||
* \see SIteratorTraits
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
struct SIteratorTraits<const T*>
|
||||
{
|
||||
typedef SRandomAccessIteratorTag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef signed int difference_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
};
|
||||
|
||||
#endif /*SITERATORBASETYPES_H_*/
|
441
2016/ppc/common/include/util/SLinkedListSet.h
Normal file
|
@ -0,0 +1,441 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef SLINKEDLIST_H_
|
||||
#define SLINKEDLIST_H_
|
||||
|
||||
#include "util/SBaseTypes.h"
|
||||
#include "util/SIteratorBaseTypes.h"
|
||||
#include "util/CompileTimeConstraints.h"
|
||||
#include <cassert>
|
||||
|
||||
template<typename T>
|
||||
class SLinkedListSetNode
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
SLinkedListSetNode() :
|
||||
fpNext(0L),
|
||||
fAddedToList(false)
|
||||
{}
|
||||
|
||||
T* getNext() const
|
||||
{
|
||||
return fpNext;
|
||||
}
|
||||
|
||||
void setNext(T* pNext)
|
||||
{
|
||||
fpNext = pNext;
|
||||
}
|
||||
|
||||
void addToList()
|
||||
{
|
||||
assert(!fAddedToList);
|
||||
fAddedToList = true;
|
||||
}
|
||||
|
||||
void removeFromList()
|
||||
{
|
||||
fAddedToList = false;
|
||||
}
|
||||
private:
|
||||
SLinkedListSetNode(const SLinkedListSetNode&);
|
||||
SLinkedListSetNode& operator=(const SLinkedListSetNode&);
|
||||
|
||||
T* fpNext;
|
||||
bool fAddedToList;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SLinkedListSetIterator;
|
||||
|
||||
template<typename T>
|
||||
class SLinkedListSet
|
||||
: common::Derived_from<T, SLinkedListSetNode<T> >
|
||||
{
|
||||
private:
|
||||
/** type of list itsself */
|
||||
typedef SLinkedListSet<T> self_type;
|
||||
public:
|
||||
/** type of values stored in vector */
|
||||
typedef typename STypeTraits<T>::value_type value_type;
|
||||
/** pointer to value */
|
||||
typedef typename STypeTraits<T>::pointer pointer;
|
||||
/** reference to value */
|
||||
typedef typename STypeTraits<T>::reference reference;
|
||||
/** const reference to value */
|
||||
typedef typename STypeTraits<T>::const_reference const_reference;
|
||||
/** unsigned integral type */
|
||||
typedef typename STypeTraits<T>::size_type size_type;
|
||||
/** signed integral type */
|
||||
typedef typename STypeTraits<T>::difference_type difference_type;
|
||||
/** iterator type */
|
||||
typedef SLinkedListSetIterator<T> iterator;
|
||||
/** const iterator type */
|
||||
typedef SLinkedListSetIterator<const T> const_iterator;
|
||||
|
||||
SLinkedListSet() :
|
||||
fpFirst(0L),
|
||||
fpLast(0L)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @note
|
||||
* O(n)!
|
||||
* @todo
|
||||
* Maybe a field would be better
|
||||
*/
|
||||
size_type size() const
|
||||
{
|
||||
size_type size = (fpFirst) ? 1 : 0;
|
||||
for (const T* pNode = fpFirst; pNode != fpLast; pNode = pNode->getNext())
|
||||
{
|
||||
++size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return (fpFirst == 0L);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
while (!empty())
|
||||
{
|
||||
pop_front();
|
||||
}
|
||||
fpFirst = 0L;
|
||||
fpLast = 0L;
|
||||
}
|
||||
|
||||
const_reference front() const
|
||||
{
|
||||
assert(fpFirst);
|
||||
return *fpFirst;
|
||||
}
|
||||
|
||||
reference front()
|
||||
{
|
||||
return const_cast<reference>(
|
||||
static_cast<const self_type&>(
|
||||
*this).front());
|
||||
}
|
||||
|
||||
const_reference back() const
|
||||
{
|
||||
assert(fpLast);
|
||||
return *fpLast;
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return const_cast<reference>(
|
||||
static_cast<const self_type&>(
|
||||
*this).back());
|
||||
}
|
||||
|
||||
void push_front(T& node)
|
||||
{
|
||||
if (contains_node(&node))
|
||||
{
|
||||
return;
|
||||
}
|
||||
node.addToList();
|
||||
node.setNext(fpFirst);
|
||||
fpFirst = &node;
|
||||
if (!fpLast)
|
||||
{//inserted first node
|
||||
fpLast = fpFirst;
|
||||
fpFirst->setNext(0L);
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(T& node)
|
||||
{
|
||||
if (empty())
|
||||
{//inserted first node
|
||||
fpFirst = &node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (contains_node(&node))
|
||||
{
|
||||
return;
|
||||
}
|
||||
fpLast->setNext(&node);
|
||||
}
|
||||
node.addToList();
|
||||
fpLast = &node;
|
||||
fpLast->setNext(0L);
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
if (!fpFirst)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fpFirst->removeFromList();
|
||||
fpFirst = fpFirst->getNext();
|
||||
if (!fpFirst)
|
||||
{//removed last element
|
||||
fpLast = 0L;
|
||||
}
|
||||
}
|
||||
|
||||
void pop_back();
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(fpFirst);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(fpFirst);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(0L);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(0L);
|
||||
}
|
||||
|
||||
iterator erase(iterator pos);
|
||||
|
||||
iterator insert(iterator pos, T& value);
|
||||
|
||||
void remove(const T& value);
|
||||
|
||||
bool contains(const T& value) const
|
||||
{
|
||||
return contains_node(&value);
|
||||
}
|
||||
private:
|
||||
SLinkedListSet(const SLinkedListSet&);
|
||||
SLinkedListSet& operator=(const SLinkedListSet&);
|
||||
|
||||
T* findPredecessor(const T* pNode) const
|
||||
{
|
||||
T* pResult = fpFirst;
|
||||
while ((pResult != 0L) && (pResult->getNext() != pNode))
|
||||
{
|
||||
pResult = pResult->getNext();
|
||||
}
|
||||
return pResult;
|
||||
}
|
||||
|
||||
bool contains_node(const T* pNodeToFind) const;
|
||||
|
||||
T* fpFirst;
|
||||
T* fpLast;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool SLinkedListSet<T>::contains_node(const T* pNodeToFind) const
|
||||
{
|
||||
T* pNode = fpFirst;
|
||||
while (pNode != 0L)
|
||||
{
|
||||
if (pNodeToFind == pNode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SLinkedListSet<T>::pop_back()
|
||||
{
|
||||
if (!fpLast)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fpLast->removeFromList();
|
||||
if (fpFirst == fpLast)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
fpLast = findPredecessor(fpLast);
|
||||
assert(fpLast);
|
||||
fpLast->setNext(0L);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename SLinkedListSet<T>::iterator SLinkedListSet<T>::erase(
|
||||
SLinkedListSet<T>::iterator pos)
|
||||
{
|
||||
if (!fpFirst)
|
||||
{
|
||||
return end();
|
||||
}
|
||||
iterator next = pos;
|
||||
++next;
|
||||
if (pos == begin())
|
||||
{//remove first element
|
||||
pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
pos->removeFromList();
|
||||
T* pNode = findPredecessor(pos.operator->());
|
||||
assert(pNode);
|
||||
if (pNode->getNext() == fpLast)
|
||||
{//removing last element
|
||||
fpLast = pNode;
|
||||
}
|
||||
pNode->setNext(pos->getNext());
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename SLinkedListSet<T>::iterator SLinkedListSet<T>::insert(
|
||||
SLinkedListSet<T>::iterator pos,
|
||||
T& value)
|
||||
{
|
||||
if (contains_node(&value))
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
if (empty() || (pos == begin()))
|
||||
{
|
||||
push_front(value);
|
||||
}
|
||||
else if (pos == end())
|
||||
{
|
||||
push_back(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.addToList();
|
||||
T* pNode = findPredecessor(pos.operator->());
|
||||
assert(pNode);
|
||||
value.setNext(pNode->getNext());
|
||||
pNode->setNext(&value);
|
||||
}
|
||||
return iterator(&value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SLinkedListSet<T>::remove(const T& value)
|
||||
{
|
||||
if (&value == fpFirst)
|
||||
{
|
||||
pop_front();
|
||||
}
|
||||
else if (&value == fpLast)
|
||||
{
|
||||
pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
const_cast<T&>(value).removeFromList();
|
||||
T* pNode = findPredecessor(&value);
|
||||
if (pNode)
|
||||
{
|
||||
pNode->setNext(value.getNext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(
|
||||
const SLinkedListSetIterator<T>& x,
|
||||
const SLinkedListSetIterator<T>& y);
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(
|
||||
const SLinkedListSetIterator<T>& x,
|
||||
const SLinkedListSetIterator<T>& y);
|
||||
|
||||
template<typename T>
|
||||
class SLinkedListSetIterator
|
||||
{
|
||||
public:
|
||||
/** the iterators category */
|
||||
typedef SForwardIteratorTag iterator_category;
|
||||
/** value type of iterator */
|
||||
typedef typename STypeTraits<T>::value_type value_type;
|
||||
/** reference to value */
|
||||
typedef typename STypeTraits<T>::reference reference;
|
||||
/** pointer to value */
|
||||
typedef typename STypeTraits<T>::pointer pointer;
|
||||
/** signed integral type */
|
||||
typedef typename STypeTraits<T>::difference_type difference_type;
|
||||
|
||||
SLinkedListSetIterator(T* pValue) :
|
||||
fpValue(pValue)
|
||||
{}
|
||||
|
||||
SLinkedListSetIterator(const SLinkedListSetIterator& rhs) :
|
||||
fpValue(rhs.fpValue)
|
||||
{}
|
||||
|
||||
SLinkedListSetIterator& operator=(const SLinkedListSetIterator& rhs)
|
||||
{
|
||||
fpValue = rhs.fpValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SLinkedListSetIterator& operator++()
|
||||
{
|
||||
fpValue = fpValue->getNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*()
|
||||
{
|
||||
return *fpValue;
|
||||
}
|
||||
|
||||
pointer operator->()
|
||||
{
|
||||
return fpValue;
|
||||
}
|
||||
|
||||
private:
|
||||
friend bool operator==<T>(
|
||||
const SLinkedListSetIterator<T>&,
|
||||
const SLinkedListSetIterator<T>&);
|
||||
friend bool operator!=<T>(
|
||||
const SLinkedListSetIterator<T>&,
|
||||
const SLinkedListSetIterator<T>&);
|
||||
T* fpValue;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(
|
||||
const SLinkedListSetIterator<T>& x,
|
||||
const SLinkedListSetIterator<T>& y)
|
||||
{
|
||||
return (x.fpValue == y.fpValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool operator!=(
|
||||
const SLinkedListSetIterator<T>& x,
|
||||
const SLinkedListSetIterator<T>& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
#endif /*SLINKEDLIST_H_*/
|
57
2016/ppc/common/include/util/Uncopyable.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains helpers to make C++ classes uncopyable, i.e. declare copy
|
||||
* constructor and assignment operator private.
|
||||
* \file Uncopyable.h
|
||||
*/
|
||||
#ifndef UNCOPYABLE_H_
|
||||
#define UNCOPYABLE_H_
|
||||
|
||||
/**
|
||||
* The macro MAKE_UNCOPYABLE expands to a declaration of copy constructor and
|
||||
* assignment operator.
|
||||
* \par Usage example
|
||||
* \code
|
||||
* class MyClass
|
||||
* {
|
||||
* MAKE_UNCOPYABLE(MyClass)
|
||||
* public:
|
||||
* //...
|
||||
* };
|
||||
* \endcode
|
||||
*/
|
||||
#ifdef MAKE_UNCOPYABLE
|
||||
#error "MAKE_UNCOPYABLE was already defined!"
|
||||
#endif
|
||||
// PRQA S 1030 3
|
||||
#define MAKE_UNCOPYABLE(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
TypeName& operator=(const TypeName&);
|
||||
|
||||
namespace common
|
||||
{
|
||||
|
||||
/**
|
||||
* Inheriting from Uncopyable makes sure that no copies of any subclass
|
||||
* are instantiated accidently because the C++ compiler will raise an error.
|
||||
*
|
||||
* \author oliver.mueller
|
||||
*/
|
||||
class Uncopyable
|
||||
{
|
||||
protected:
|
||||
Uncopyable(){}
|
||||
|
||||
private:
|
||||
Uncopyable(const Uncopyable&);
|
||||
Uncopyable& operator=(const Uncopyable&);
|
||||
};
|
||||
|
||||
}//namespace common
|
||||
|
||||
#endif /*UNCOPYABLE_H_*/
|
24
2016/ppc/gps/Project.meta
Normal file
|
@ -0,0 +1,24 @@
|
|||
Project {
|
||||
ExecutableConfig UnitTest {
|
||||
Files "src/**/*.cpp"
|
||||
ExcludeFiles "src/ac/*.cpp"
|
||||
Files "test/**/*.cpp"
|
||||
IncludeDir "include"
|
||||
IncludeDir "test/include"
|
||||
IncludeDir "common/include"
|
||||
ArtifactName "gpsTests.exe"
|
||||
PostSteps {
|
||||
CommandLine "$(OutputDir)/$(ArtifactName) -r xml --out $(OutputDir)/test_$(ArtifactName).xml", filter: run, default: off
|
||||
}
|
||||
DefaultToolchain GCC {
|
||||
Compiler CPP {
|
||||
Flags "-g -Wall -fpermissive -fmessage-length=0"
|
||||
Define "UNIT_TEST"
|
||||
}
|
||||
Compiler C {
|
||||
Flags "-g -Wall -fpermissive -fmessage-length=0"
|
||||
Define "UNIT_TEST"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
2016/ppc/gps/include/ac/GpsACPusher.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
#ifndef AC_PUSHER_H_
|
||||
#define AC_PUSHER_H_
|
||||
|
||||
#include "gps/IACPusher.h"
|
||||
|
||||
namespace android
|
||||
{
|
||||
class ICaimTransceiver;
|
||||
}
|
||||
|
||||
namespace gps
|
||||
{
|
||||
class GpsAcPusher : public IACPusher
|
||||
{
|
||||
public:
|
||||
virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs);
|
||||
private:
|
||||
uint8 fPosition[15];
|
||||
ICaimTransceiver& fCaimTransceiver;
|
||||
static const uint8 LONGITUDE_OFFSET = 0;
|
||||
static const uint8 LATITUDE_OFFSET = 4;
|
||||
static const uint8 HEADING_OFFSET = 8;
|
||||
|
||||
static const uint8 HEIGHT_OFFSET = 9;
|
||||
static const uint8 QUALITY_OFFSET = 11;
|
||||
static const uint8 SPEED_OFFSET = 13;
|
||||
};
|
||||
} // namespace gps
|
||||
|
||||
#endif /* end of include guard */
|
||||
|
21
2016/ppc/gps/include/ac/IGpsACPusher.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
#ifndef IAC_PUSHER_H_
|
||||
#define IAC_PUSHER_H_
|
||||
|
||||
#include "commonTypes.h"
|
||||
|
||||
namespace gps
|
||||
{
|
||||
class IGpsACPusher
|
||||
{
|
||||
public:
|
||||
virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs) = 0;
|
||||
|
||||
};
|
||||
} // namespace gps
|
||||
#endif /* end of include guard */
|
||||
|
236
2016/ppc/gps/include/busId/BusId.h
Normal file
|
@ -0,0 +1,236 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
#ifndef BUSID_H_
|
||||
#define BUSID_H_
|
||||
|
||||
#include "commonTypes.h"
|
||||
#include "util/Uncopyable.h"
|
||||
|
||||
//forward declarations
|
||||
class BusIdIterator;
|
||||
|
||||
/**
|
||||
* Abstraction for bus ids used throughout the system.
|
||||
* @author matthias.kessler
|
||||
*
|
||||
* BusId contains constants for all busses used and provides an iterator
|
||||
* to access them. Each BusId will have an index that is unique in the system.
|
||||
*/
|
||||
class BusId
|
||||
{
|
||||
public:
|
||||
enum { MAX_INDEX = 4 };
|
||||
/** iterator over BusIds */
|
||||
typedef BusIdIterator iterator;
|
||||
/** maximum number of busses, used to allocate static memory */
|
||||
static const uint8 MAX_NUMBER_OF_BUSSES = MAX_INDEX;
|
||||
static const uint8 NUMBER_OF_LIN_BUSSES = 1;
|
||||
|
||||
static const BusId BODYCAN;
|
||||
static const BusId LIN;
|
||||
static const BusId TAS;
|
||||
static const BusId SELFDIAG;
|
||||
static const BusId INVALID; //MUST be last BusId and is not part of MAX_NUMBER_OF_BUSSES
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param name string representation of BusId
|
||||
*/
|
||||
explicit BusId(const char* name);
|
||||
|
||||
/**
|
||||
* @return the BusIds name
|
||||
*/
|
||||
const char* getName() const
|
||||
{
|
||||
return fpName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the BusIds unique index
|
||||
*/
|
||||
uint8 toIndex() const
|
||||
{
|
||||
return fId;
|
||||
}
|
||||
|
||||
uint8 toCANIndex() const;
|
||||
|
||||
uint8 toLINIndex() const;
|
||||
|
||||
/**
|
||||
* @param index index of BusId to access
|
||||
* @return BusId at given index
|
||||
*/
|
||||
static const BusId& get(uint8 index);
|
||||
|
||||
/**
|
||||
* @return iterator to first BusId
|
||||
*/
|
||||
static iterator begin();
|
||||
|
||||
/**
|
||||
* @return iterator one past last BusId
|
||||
*/
|
||||
static iterator end();
|
||||
|
||||
/**
|
||||
* @return total number of busses (excluding INVALID)
|
||||
*/
|
||||
static uint8 numberOfBusses()
|
||||
{
|
||||
return sfIdCount;
|
||||
}
|
||||
private:
|
||||
MAKE_UNCOPYABLE(BusId)
|
||||
|
||||
//friends
|
||||
friend bool operator==(const BusId& x, const BusId& y);
|
||||
friend bool operator!=(const BusId& x, const BusId& y);
|
||||
friend class BusIdIterator;
|
||||
//fields
|
||||
uint8 fId;
|
||||
const char* fpName;
|
||||
//static fields
|
||||
static uint8 sfIdCount;
|
||||
static BusId* sfBusId[MAX_NUMBER_OF_BUSSES];
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares two given BusIds
|
||||
* @param x first BusId to compare
|
||||
* @param y second BusId to compare
|
||||
* @return
|
||||
* - true BusIds are equal
|
||||
* - false BusIds are not equal
|
||||
*/
|
||||
inline bool operator==(const BusId& x, const BusId& y)
|
||||
{
|
||||
return (x.fId == y.fId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two given BusIds
|
||||
* @param x first BusId to compare
|
||||
* @param y second BusId to compare
|
||||
* @return
|
||||
* - true BusIds are not equal
|
||||
* - false BusIds are equal
|
||||
*/
|
||||
inline bool operator!=(const BusId& x, const BusId& y)
|
||||
{
|
||||
return (x.fId != y.fId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator for BusIds.
|
||||
* @author matthias.kessler
|
||||
*/
|
||||
class BusIdIterator
|
||||
{
|
||||
public:
|
||||
/** pointer to a BusId */
|
||||
typedef BusId* pointer;
|
||||
/** reference to a BusId */
|
||||
typedef BusId& reference;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param pBusId pointer to BusId this iterator points initially to
|
||||
*/
|
||||
explicit BusIdIterator(BusId* pBusId) :
|
||||
fpBusId(pBusId)
|
||||
{}
|
||||
|
||||
/**
|
||||
* copy constructor
|
||||
* @param itr iterator to copy from
|
||||
*/
|
||||
BusIdIterator(const BusIdIterator& itr) :
|
||||
fpBusId(itr.fpBusId)
|
||||
{}
|
||||
|
||||
/**
|
||||
* assignment operator
|
||||
* @param itr iterator to copy from
|
||||
*/
|
||||
BusIdIterator& operator=(const BusIdIterator& itr)
|
||||
{
|
||||
if (&itr != this)
|
||||
{
|
||||
fpBusId = itr.fpBusId;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to BusId iterator currently points to
|
||||
*/
|
||||
pointer operator->() const
|
||||
{
|
||||
return fpBusId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return reference to BusId iterator currently points to
|
||||
*/
|
||||
reference operator*() const
|
||||
{
|
||||
return *fpBusId;
|
||||
}
|
||||
|
||||
/**
|
||||
* prefix increment operator
|
||||
* @return next iterator
|
||||
*/
|
||||
BusIdIterator& operator++()
|
||||
{
|
||||
if (fpBusId->toIndex() < BusId::sfIdCount-2)//-2 because of INVALID is last BusId
|
||||
{
|
||||
fpBusId = BusId::sfBusId[fpBusId->toIndex() + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
fpBusId = 0L;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
//friends
|
||||
friend bool operator==(const BusIdIterator& x, const BusIdIterator& y);
|
||||
friend bool operator!=(const BusIdIterator& x, const BusIdIterator& y);
|
||||
//fields
|
||||
BusId* fpBusId;
|
||||
};
|
||||
|
||||
/**
|
||||
* compares two BusIdIterators
|
||||
* @param x first BusIdIterators to compare
|
||||
* @param y second BusIdIterators to compare
|
||||
* @return
|
||||
* - true BusIdIterators are equal
|
||||
* - false BusIdIterators are not equal
|
||||
*/
|
||||
inline bool operator==(const BusIdIterator& x, const BusIdIterator& y)
|
||||
{
|
||||
return (x.fpBusId == y.fpBusId);
|
||||
}
|
||||
|
||||
/**
|
||||
* compares two BusIdIterators
|
||||
* @param x first BusIdIterators to compare
|
||||
* @param y second BusIdIterators to compare
|
||||
* @return
|
||||
* - true BusIdIterators are not equal
|
||||
* - false BusIdIterators are equal
|
||||
*/
|
||||
inline bool operator!=(const BusIdIterator& x, const BusIdIterator& y)
|
||||
{
|
||||
return (x.fpBusId != y.fpBusId);
|
||||
}
|
||||
|
||||
#endif /*BUSID_H_*/
|
18
2016/ppc/gps/include/busId/BusIdMask.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file BusIdMask.h
|
||||
*/
|
||||
#ifndef BUSIDMASK_H_
|
||||
#define BUSIDMASK_H_
|
||||
|
||||
#include "util/Mask.h"
|
||||
#include "busId/BusId.h"
|
||||
|
||||
typedef Mask<BusId, uint32> BusIdMask;
|
||||
|
||||
#endif /*BUSIDMASK_H_*/
|
44
2016/ppc/gps/include/can/ICANTransceiver.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef I_CAN_TRANSCEIVER_H_
|
||||
#define I_CAN_TRANSCEIVER_H_
|
||||
|
||||
#include "can/canframes/CANFrame.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
class ICANTransceiver
|
||||
{
|
||||
public:
|
||||
enum ErrorCode
|
||||
{
|
||||
CAN_ERR_OK,
|
||||
CAN_ERR_TX_FAIL
|
||||
};
|
||||
|
||||
virtual ErrorCode init() = 0;
|
||||
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual ErrorCode open() = 0;
|
||||
|
||||
virtual ErrorCode close() = 0;
|
||||
|
||||
virtual ErrorCode mute() = 0;
|
||||
|
||||
virtual ErrorCode unmute() = 0;
|
||||
|
||||
virtual ErrorCode write(const can::CANFrame& frame) = 0;
|
||||
|
||||
virtual uint32 getBaudrate() const = 0;
|
||||
|
||||
virtual uint16 getHwQueueTimeout() const = 0;
|
||||
|
||||
};
|
||||
} // namespace can
|
||||
#endif /* end of include guard */
|
||||
|
181
2016/ppc/gps/include/can/canframes/CANFrame.h
Normal file
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains Cpp2CAN CANFrame.
|
||||
* @file CANFrame.h
|
||||
* @ingroup cpp2can
|
||||
*/
|
||||
#ifndef CANFRAME_H
|
||||
#define CANFRAME_H
|
||||
|
||||
#include "commonTypes.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace can
|
||||
{
|
||||
|
||||
/**
|
||||
* Class representing a CANFrame.
|
||||
* @author matthias.kessler
|
||||
*
|
||||
* A object of type CANFrame does not provide any payload-buffer by default.
|
||||
* It has to be provided with buffers by using a certain constructor or the
|
||||
* setPayload() method.
|
||||
*
|
||||
* @note
|
||||
* CANFrame may be used as base class for special frame classes providing
|
||||
* the programmer with explicit methods to access the signals that are
|
||||
* encoded in the CANFrames payload.
|
||||
*/
|
||||
class CANFrame
|
||||
{
|
||||
public:
|
||||
/** bitmask to extract sender */
|
||||
static const uint8 SENDER_MASK = 0xFF;
|
||||
/** overhead of a CANFrame (in bit) */
|
||||
static const uint8 CAN_OVERHEAD_BITS = 47;
|
||||
/** maximum payload length of a CANFrame */
|
||||
static const uint8 MAX_FRAME_LENGTH = 8;
|
||||
/** maximum value of a CANFrame id */
|
||||
static const uint16 MAX_FRAME_ID = 0x7FF;
|
||||
|
||||
/**
|
||||
* @post getId() == 0x00
|
||||
* @post getPayload() == NULL
|
||||
* @post getPayloadLength() == 0
|
||||
* @post getTimestamp() == 0
|
||||
*/
|
||||
CANFrame();
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param frame CANFrame to copy content from
|
||||
*/
|
||||
CANFrame(const CANFrame& frame);
|
||||
|
||||
/**
|
||||
* Constructor initializing id, payload and length
|
||||
*
|
||||
* @pre id <= MAX_FRAME_ID
|
||||
* @pre length <= MAX_FRAME_LENGTH
|
||||
* @throws assertion
|
||||
*
|
||||
* The payload will not be copied, it is passed as a
|
||||
* reference and CANFrame will work on this payload!
|
||||
*/
|
||||
CANFrame(uint16 id, uint8 payload[], uint8 length);
|
||||
|
||||
uint16 getId() const
|
||||
{
|
||||
return fId;
|
||||
}
|
||||
|
||||
void setId(uint16 id)
|
||||
{
|
||||
this->fId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to modifiable payload of this CANFrame
|
||||
*/
|
||||
uint8* getPayload()
|
||||
{
|
||||
return fpPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to read only payload of this CANFrame
|
||||
*/
|
||||
const uint8* getPayload() const
|
||||
{
|
||||
return fpPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CANFrames payload and length
|
||||
*
|
||||
* @note
|
||||
* This method just sets a pointer to the payload and does not copy it!
|
||||
*
|
||||
* @post getPayload() == payload
|
||||
* @post getPayloadLength() == length
|
||||
* @post getMaxPayloadLength() == length
|
||||
*/
|
||||
void setPayload(uint8 payload[], uint8 length)
|
||||
{
|
||||
fpPayload = payload;
|
||||
fPayloadLength = length;
|
||||
fMaxPayloadLength = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre getPayload() != NULL
|
||||
* @pre length <= getMaxPayloadLength()
|
||||
* @throws assertion
|
||||
*/
|
||||
void setPayloadLength(uint8 length);
|
||||
|
||||
uint8 getPayloadLength() const
|
||||
{
|
||||
return fPayloadLength;
|
||||
}
|
||||
|
||||
uint8 getMaxPayloadLength() const
|
||||
{
|
||||
return fMaxPayloadLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns content of a CANFrame to another.
|
||||
* @param canFrame frame to copy from
|
||||
* @return reference to frame with new content
|
||||
* @pre getMaxPayloadLength() >= canFrame.getPayloadLength()
|
||||
* @throws assertion
|
||||
*/
|
||||
CANFrame& operator=(const CANFrame& canFrame);
|
||||
|
||||
/**
|
||||
* @return modifiable reference to timestamp
|
||||
*/
|
||||
uint64& getTimestamp()
|
||||
{
|
||||
return fTimestamp; // PRQA S 4024
|
||||
}
|
||||
|
||||
/**
|
||||
* @return read only access to timestamp
|
||||
*/
|
||||
const uint64& getTimestamp() const
|
||||
{
|
||||
return fTimestamp;
|
||||
}
|
||||
|
||||
bool isExtended() const { return false; } /* TODO: cleanup */
|
||||
|
||||
protected:
|
||||
friend bool operator==(const CANFrame& frame1, const CANFrame& frame2);
|
||||
|
||||
uint8* fpPayload;
|
||||
uint16 fId;
|
||||
uint8 fPayloadLength;
|
||||
uint8 fMaxPayloadLength;
|
||||
uint64 fTimestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares two CANFrames without considering the timestamp
|
||||
* @param frame1 first frame to compare
|
||||
* @param frame2 second frame to compare
|
||||
* @return
|
||||
* - true if frames are equal
|
||||
* - false if frames are not equal
|
||||
*/
|
||||
bool operator==(const CANFrame& frame1, const CANFrame& frame2);
|
||||
|
||||
} /* namespace can */
|
||||
|
||||
#endif /* CANFRAME_H */
|
79
2016/ppc/gps/include/can/filter/IFilter.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains IFilter interface.
|
||||
* @file IFilter.h
|
||||
* @ingroup filter
|
||||
*/
|
||||
#ifndef IFILTER_H_
|
||||
#define IFILTER_H_
|
||||
|
||||
#include "commonTypes.h"
|
||||
#include "util/Uncopyable.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
//forward declaration
|
||||
class IMerger;
|
||||
|
||||
/**
|
||||
* common interface for filter classes
|
||||
* @author matthias.kessler
|
||||
*/
|
||||
class IFilter
|
||||
{
|
||||
public:
|
||||
IFilter() {};
|
||||
|
||||
/**
|
||||
* adds a single id to the filter
|
||||
* @param id id to add
|
||||
* @post filter.match(id)
|
||||
*/
|
||||
virtual void add(uint16 id) = 0;
|
||||
|
||||
/**
|
||||
* adds a range of ids to the filter
|
||||
* @param from begin of range
|
||||
* @param to end of range
|
||||
* @post filter.match(from...to);
|
||||
*/
|
||||
virtual void add(uint16 from, uint16 to) = 0;
|
||||
|
||||
/**
|
||||
* checks if a given id matches the filter
|
||||
* @return
|
||||
* - true: id matches filter
|
||||
* - false: id does not match filter
|
||||
*/
|
||||
virtual bool match(uint16 id) const = 0;
|
||||
|
||||
/**
|
||||
* clears the filter so that nothing matches
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/**
|
||||
* opens the filters full range
|
||||
*/
|
||||
virtual void open() = 0;
|
||||
|
||||
/**
|
||||
* merges filter with a given merger
|
||||
* @param merger IMerger to merge filter to
|
||||
*
|
||||
* This is part of the visitor pattern that is used to
|
||||
* merge different kinds of filters.
|
||||
*/
|
||||
virtual void acceptMerger(IMerger& merger) = 0;
|
||||
private:
|
||||
MAKE_UNCOPYABLE(IFilter)
|
||||
};
|
||||
|
||||
} //namespace can
|
||||
|
||||
#endif /*IFILTER_H_*/
|
62
2016/ppc/gps/include/can/filter/IMerger.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains IMerger interface.
|
||||
* @file IMerger.h
|
||||
* @ingroup filter
|
||||
*/
|
||||
#ifndef _IMERGER_H_
|
||||
#define _IMERGER_H_
|
||||
|
||||
#include "util/Uncopyable.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
|
||||
//forward declarations
|
||||
class BitFieldFilter;
|
||||
class AbstractStaticBitFieldFilter;
|
||||
class IntervalFilter;
|
||||
|
||||
/**
|
||||
* interface for class that are able to merge with other filter classes
|
||||
* @class IMerger
|
||||
* @author gerd.schaefer
|
||||
*
|
||||
* @see BitFieldFilter
|
||||
* @see AbstractStaticBitFieldFilter
|
||||
* @see IntervalFilter
|
||||
*/
|
||||
class IMerger
|
||||
{
|
||||
public:
|
||||
IMerger() {}
|
||||
|
||||
/**
|
||||
* merges with a BitFieldFilter
|
||||
* @param filter BitFieldFilter to merge with
|
||||
*/
|
||||
virtual void mergeWithBitField(BitFieldFilter& filter) = 0;
|
||||
|
||||
/**
|
||||
* merges with a AbstractStaticBitFieldFilter
|
||||
* @param filter AbstractStaticBitFieldFilter to merge with
|
||||
*/
|
||||
virtual void mergeWithStaticBitField(AbstractStaticBitFieldFilter& filter) = 0;
|
||||
|
||||
/**
|
||||
* merges with a IntervalFilter
|
||||
* @param filter IntervalFilter to merge with
|
||||
*/
|
||||
virtual void mergeWithInterval(IntervalFilter& filter) = 0;
|
||||
private:
|
||||
MAKE_UNCOPYABLE(IMerger)
|
||||
};
|
||||
|
||||
} //namespace can
|
||||
|
||||
#endif //_IMERGER_H_
|
148
2016/ppc/gps/include/can/filter/IntervalFilter.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains IntervalFilter class.
|
||||
* @file IntervalFilter.h
|
||||
* @ingroup filter
|
||||
*/
|
||||
#ifndef _INTERVALFILTER_H_
|
||||
#define _INTERVALFILTER_H_
|
||||
|
||||
#include "commonTypes.h"
|
||||
#include "can/canframes/CANFrame.h"
|
||||
#include "can/filter/IFilter.h"
|
||||
#include "can/filter/IMerger.h"
|
||||
#include "util/Uncopyable.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
|
||||
/**
|
||||
* Cpp2CAN IntervalFilter
|
||||
* @author gerd.schaefer, matthias.kessler
|
||||
*
|
||||
* @see IFilter
|
||||
*/
|
||||
class IntervalFilter :
|
||||
public IFilter
|
||||
{
|
||||
public:
|
||||
/** maximum id the filter may take */
|
||||
static const uint16 MAX_ID = CANFrame::MAX_FRAME_ID;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @post getLowerBound() == MAX_ID
|
||||
* @post getUpperBound() == 0x0
|
||||
*
|
||||
* Nothing wil be accepted by default
|
||||
*/
|
||||
IntervalFilter();
|
||||
|
||||
/**
|
||||
* constructor initializing an interval
|
||||
* @param from first id that will be accepted
|
||||
* @param to last id that will be accepted
|
||||
* @pre from <= MAX_ID
|
||||
* @pre to <= MAX_ID
|
||||
* @post getLowerBound() == from
|
||||
* @post getUpperBound() == to
|
||||
*
|
||||
* @note
|
||||
* If from or to exceed MAX_ID, they will be set to MAX_ID.
|
||||
*/
|
||||
explicit IntervalFilter(uint16 from, uint16 to);
|
||||
|
||||
/**
|
||||
* @see IFilter::add()
|
||||
* @param id id to add to filter
|
||||
* @pre id <= MAX_ID, otherwise no effect
|
||||
* @post getLowerBound() == min(id, getLowerBound())
|
||||
* @post getUpperBound() == max(id, getUpperBound())
|
||||
*
|
||||
* @note
|
||||
* This call is equal to add(id, id).
|
||||
*/
|
||||
virtual void add(uint16 id)
|
||||
{
|
||||
if (id <= MAX_ID)
|
||||
{
|
||||
add(id, id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IFilter::add()
|
||||
* @param from lower bound of interval to add
|
||||
* @param to upper bound of interval to add
|
||||
* @pre from <= MAX_ID
|
||||
* @pre to <= MAX_ID
|
||||
* @post getLowerBound() == min(from, getLowerBound())
|
||||
* @post getUpperBound() == max(to, getUpperBound())
|
||||
*
|
||||
* If from or to exceed MAX_ID, they will be set to MAX_ID.
|
||||
*
|
||||
* This call will not replace the current filter configuration, but
|
||||
* adjust lower and upper bound of the filter according to the parameters.
|
||||
*/
|
||||
virtual void add(uint16 from, uint16 to);
|
||||
|
||||
/**
|
||||
* checks if an id matches the filter
|
||||
* @param id id to check
|
||||
* @return
|
||||
* - true: filter matches id
|
||||
* - false: id is not in filters range
|
||||
*/
|
||||
virtual bool match(uint16 id) const
|
||||
{
|
||||
return (id >= fFrom) && (id <= fTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IFilter::acceptMerger()
|
||||
*/
|
||||
virtual void acceptMerger(IMerger& merger)
|
||||
{
|
||||
merger.mergeWithInterval(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IFilter::clear();
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* @see IFilter::open();
|
||||
*/
|
||||
virtual void open();
|
||||
|
||||
/**
|
||||
* @return lower bound of filter
|
||||
*/
|
||||
uint16 getLowerBound() const
|
||||
{
|
||||
return fFrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return upper bound of filter
|
||||
*/
|
||||
uint16 getUpperBound() const
|
||||
{
|
||||
return fTo;
|
||||
}
|
||||
private:
|
||||
MAKE_UNCOPYABLE(IntervalFilter)
|
||||
//fields
|
||||
uint16 fFrom;
|
||||
uint16 fTo;
|
||||
};
|
||||
|
||||
} /*namespace can*/
|
||||
|
||||
#endif //_INTERVALFILTER_H_
|
50
2016/ppc/gps/include/can/framemgmt/ICANFrameListener.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains interface ICANFrameListener.
|
||||
* @file ICANFrameListener.h
|
||||
* @ingroup framemgmt
|
||||
*/
|
||||
#ifndef ICANFRAMELISTENER_H
|
||||
#define ICANFRAMELISTENER_H
|
||||
|
||||
#include "util/SLinkedListSet.h"
|
||||
#include "util/Uncopyable.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
class CANFrame;
|
||||
class IFilter;
|
||||
|
||||
/**
|
||||
* CANFrameListener interface
|
||||
* @author matthias.kessler
|
||||
*
|
||||
* An ICANFrameListener subclass is a class interested in the reception
|
||||
* of CANFrames. Therefore it needs to register at an AbstractCANTransceiver.
|
||||
*/
|
||||
class ICANFrameListener :
|
||||
public SLinkedListSetNode<ICANFrameListener>
|
||||
{
|
||||
MAKE_UNCOPYABLE(ICANFrameListener)
|
||||
public:
|
||||
ICANFrameListener() {}
|
||||
|
||||
/**
|
||||
* This method notifies the listener of a CANFrame reception.
|
||||
*/
|
||||
virtual void frameReceived(const CANFrame& canFrame) = 0;
|
||||
|
||||
/**
|
||||
* Returns the ICANFrameListeners filter.
|
||||
*/
|
||||
virtual IFilter& getFilter() = 0;
|
||||
};
|
||||
|
||||
} //namespace can
|
||||
|
||||
#endif // ICANFRAMELISTENER_H
|
48
2016/ppc/gps/include/gps/GpsConverter.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef GPSCONVERTER_H_
|
||||
#define GPSCONVERTER_H_
|
||||
|
||||
#include "commonTypes.h"
|
||||
#include "can/framemgmt/ICANFrameListener.h"
|
||||
#include "can/filter/IntervalFilter.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
class CANFrame;
|
||||
class ICANTransceiver;
|
||||
}
|
||||
namespace gps
|
||||
{
|
||||
class IGpsACPusher;
|
||||
|
||||
class GpsConverter :
|
||||
public can::ICANFrameListener
|
||||
{
|
||||
public:
|
||||
enum { GPS_FRAME_ID = 0x34a }; //NavGps1
|
||||
GpsConverter(can::ICANTransceiver& transceiver, IGpsACPusher& acPusher);
|
||||
|
||||
/* ICANFrameListener */
|
||||
virtual void frameReceived(const can::CANFrame& canFrame);
|
||||
virtual can::IFilter& getFilter()
|
||||
{
|
||||
return fCanFilter;
|
||||
}
|
||||
|
||||
private:
|
||||
can::ICANTransceiver& fCanTransceiver;
|
||||
can::IntervalFilter fCanFilter;
|
||||
|
||||
IGpsACPusher& fAcPusher;
|
||||
sint32 fLastLatInMs;
|
||||
sint32 fLastLongInMs;
|
||||
};
|
||||
|
||||
} // namespace gps
|
||||
#endif /* end of include guard */
|
||||
|
7
2016/ppc/gps/rakefile.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
desc "run unittests"
|
||||
task :runTests do
|
||||
sh "bake -b UnitTest -a black --include_filter run"
|
||||
end
|
||||
task :default => :run
|
||||
|
33
2016/ppc/gps/src/ac/GpsACPusher.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "gps/AcPusher.h"
|
||||
#include "android/caim/base/ICaimTransceiver.h"
|
||||
#include "util/endian.h"
|
||||
|
||||
namespace gps
|
||||
{
|
||||
|
||||
void GpsAcPusher::pushGPSCoordinates(sint32 latMs, sint32 longMs)
|
||||
{
|
||||
uint8 newPosition[sizeof(fPosition)];
|
||||
|
||||
writeMem32(newPosition + LONGITUDE_OFFSET, longMs);
|
||||
writeMem32(newPosition + LATITUDE_OFFSET, latMs);
|
||||
|
||||
writeMem16(newPosition + HEIGHT_OFFSET, 0);
|
||||
writeMem16(newPosition + SPEED_OFFSET, 0);
|
||||
newPosition[HEADING_OFFSET] = 0;
|
||||
writeMem16(newPosition + QUALITY_OFFSET, 0);
|
||||
|
||||
if (memcmp(newPosition, fPosition, sizeof(fPosition)))
|
||||
{
|
||||
memcpy(fPosition, newPosition, sizeof(fPosition));
|
||||
fCaimTransceiver.push(POSITION_COMMAND, fPosition, sizeof(fPosition));
|
||||
}
|
||||
}
|
||||
} // namespace gps
|
||||
|
99
2016/ppc/gps/src/can/canframes/CANFrame.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "can/canframes/CANFrame.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
|
||||
//define const variables for GCC
|
||||
#ifdef __GNUC__
|
||||
const uint8 CANFrame::SENDER_MASK;
|
||||
const uint8 CANFrame::CAN_OVERHEAD_BITS;
|
||||
const uint8 CANFrame::MAX_FRAME_LENGTH;
|
||||
const uint16 CANFrame::MAX_FRAME_ID;
|
||||
#endif
|
||||
|
||||
CANFrame::CANFrame() :
|
||||
fpPayload(0L),
|
||||
fId(0),
|
||||
fPayloadLength(0),
|
||||
fMaxPayloadLength(0),
|
||||
fTimestamp(0)
|
||||
{}
|
||||
|
||||
CANFrame::CANFrame(const CANFrame& frame) :
|
||||
fpPayload(frame.fpPayload),
|
||||
fId(frame.fId),
|
||||
fPayloadLength(frame.fPayloadLength),
|
||||
fMaxPayloadLength(frame.fMaxPayloadLength),
|
||||
fTimestamp(frame.fTimestamp)
|
||||
{
|
||||
}
|
||||
|
||||
CANFrame::CANFrame(uint16 id, uint8 payload[], uint8 length) :
|
||||
fpPayload(payload),
|
||||
fId(id),
|
||||
fPayloadLength(length),
|
||||
fMaxPayloadLength(length)
|
||||
{
|
||||
assert(id <= MAX_FRAME_ID);
|
||||
assert(length <= MAX_FRAME_LENGTH);
|
||||
}
|
||||
|
||||
CANFrame& CANFrame::operator=(const CANFrame& canFrame)
|
||||
{
|
||||
if (&canFrame != this)
|
||||
{
|
||||
if (fMaxPayloadLength < canFrame.fPayloadLength)
|
||||
{
|
||||
assert(fMaxPayloadLength >= canFrame.fPayloadLength);
|
||||
}
|
||||
fId = canFrame.fId;
|
||||
for (uint8 i = 0; i < canFrame.fPayloadLength; ++i)
|
||||
{
|
||||
fpPayload[i] = canFrame.fpPayload[i];
|
||||
}
|
||||
fPayloadLength = canFrame.fPayloadLength;
|
||||
fTimestamp = canFrame.fTimestamp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CANFrame::setPayloadLength(uint8 length)
|
||||
{
|
||||
if (!fpPayload)
|
||||
{
|
||||
assert(fpPayload != 0L);
|
||||
}
|
||||
if (length > fMaxPayloadLength)
|
||||
{
|
||||
assert(length <= fMaxPayloadLength);
|
||||
}
|
||||
fPayloadLength = length;
|
||||
}
|
||||
|
||||
bool operator==(const CANFrame& frame1, const CANFrame& frame2)
|
||||
{
|
||||
if (frame1.fId != frame2.fId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (frame1.fPayloadLength != frame2.fPayloadLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (uint8 i = 0; i < frame1.fPayloadLength; i++)
|
||||
{
|
||||
if (frame1.fpPayload[i] != frame2.fpPayload[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace can
|
69
2016/ppc/gps/src/can/filter/IntervalFilter.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "can/filter/IntervalFilter.h"
|
||||
#include "util/SAlgorithm.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
|
||||
#ifdef __GNUC__
|
||||
const uint16 IntervalFilter::MAX_ID;
|
||||
#endif
|
||||
|
||||
IntervalFilter::IntervalFilter()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
IntervalFilter::IntervalFilter(uint16 from, uint16 to) :
|
||||
fFrom(from),
|
||||
fTo(to)
|
||||
{
|
||||
if (from > MAX_ID)
|
||||
{
|
||||
fFrom = MAX_ID;
|
||||
}
|
||||
if (to > MAX_ID)
|
||||
{
|
||||
fTo = MAX_ID;
|
||||
}
|
||||
}
|
||||
|
||||
void IntervalFilter::add(uint16 from, uint16 to)
|
||||
{
|
||||
if (from > MAX_ID)
|
||||
{
|
||||
from = MAX_ID;
|
||||
}
|
||||
if (to > MAX_ID)
|
||||
{
|
||||
to = MAX_ID;
|
||||
}
|
||||
//assert order
|
||||
if (from > to)
|
||||
{
|
||||
sswap(from, to);
|
||||
}
|
||||
//adjust lower bound
|
||||
fFrom = smin(fFrom, from);
|
||||
//adjust upper bound
|
||||
fTo = smax(fTo, to);
|
||||
}
|
||||
|
||||
void IntervalFilter::clear()
|
||||
{
|
||||
fFrom = MAX_ID;
|
||||
fTo = 0;
|
||||
}
|
||||
|
||||
void IntervalFilter::open()
|
||||
{
|
||||
fFrom = 0x0;
|
||||
fTo = MAX_ID;
|
||||
}
|
||||
|
||||
} /*namespace can*/
|
48
2016/ppc/gps/src/gps/GpsConverter.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* \copyright
|
||||
* (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "gps/GpsConverter.h"
|
||||
#include "ac/IGpsACPusher.h"
|
||||
#include "can/canframes/CANFrame.h"
|
||||
#include "can/ICANTransceiver.h"
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace can;
|
||||
|
||||
namespace gps
|
||||
{
|
||||
|
||||
GpsConverter::GpsConverter(
|
||||
ICANTransceiver& transceiver,
|
||||
IGpsACPusher& acPusher)
|
||||
: fCanTransceiver(transceiver)
|
||||
, fCanFilter(GPS_FRAME_ID, GPS_FRAME_ID)
|
||||
, fAcPusher(acPusher)
|
||||
{
|
||||
}
|
||||
|
||||
void GpsConverter::frameReceived(const CANFrame& canFrame)
|
||||
{
|
||||
const uint8* payload = canFrame.getPayload();
|
||||
// TOOD implement conversion to arc-msec and call IGpsACPusher
|
||||
|
||||
sint32 latInMs = 0; // here add your converted lat
|
||||
sint32 longInMs = 0; // here add your converted long
|
||||
|
||||
|
||||
if (latInMs != fLastLatInMs || longInMs != fLastLongInMs)
|
||||
{
|
||||
// value changed
|
||||
fAcPusher.pushGPSCoordinates(latInMs, longInMs);
|
||||
fLastLatInMs = latInMs;
|
||||
fLastLongInMs = longInMs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace gps
|
||||
|
||||
|
53
2016/ppc/gps/test/CanTransceiverMock.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef CANTRANSCEIVER_MOCK_H_
|
||||
#define CANTRANSCEIVER_MOCK_H_
|
||||
|
||||
#include "can/ICANTransceiver.h"
|
||||
#include "busId/BusId.h"
|
||||
|
||||
namespace can
|
||||
{
|
||||
|
||||
class CanTransceiverMock
|
||||
: public ICANTransceiver
|
||||
{
|
||||
public:
|
||||
CanTransceiverMock()
|
||||
{}
|
||||
virtual ErrorCode init()
|
||||
{
|
||||
return CAN_ERR_OK;
|
||||
}
|
||||
virtual void shutdown() {}
|
||||
virtual ErrorCode open()
|
||||
{
|
||||
return CAN_ERR_OK;
|
||||
}
|
||||
virtual ErrorCode close()
|
||||
{
|
||||
return CAN_ERR_OK;
|
||||
}
|
||||
virtual ErrorCode mute()
|
||||
{
|
||||
return CAN_ERR_OK;
|
||||
}
|
||||
virtual ErrorCode unmute()
|
||||
{
|
||||
return CAN_ERR_OK;
|
||||
}
|
||||
virtual ErrorCode write(const can::CANFrame& frame)
|
||||
{
|
||||
return CAN_ERR_OK;
|
||||
}
|
||||
virtual uint32 getBaudrate() const
|
||||
{
|
||||
return 500000;
|
||||
}
|
||||
virtual uint16 getHwQueueTimeout() const
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
};
|
||||
} // namespace can
|
||||
#endif /* end of include guard */
|
||||
|
||||
|
110
2016/ppc/gps/test/GpsConverterTest.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "commonTypes.h"
|
||||
#include "can/canframes/CANFrame.h"
|
||||
#include "gps/GpsConverter.h"
|
||||
#include "ac/IGpsACPusher.h"
|
||||
#include "CanTransceiverMock.h"
|
||||
#include "busId/BusId.h"
|
||||
|
||||
using namespace gps;
|
||||
using namespace common;
|
||||
using namespace can;
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class GpsAcPusherMock : public gps::IGpsACPusher
|
||||
{
|
||||
public:
|
||||
GpsAcPusherMock()
|
||||
: gpsWasSet(false)
|
||||
{}
|
||||
virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs)
|
||||
{
|
||||
printf("pushGPSCoordinates received: %d and %d\n", latMs, longMs);
|
||||
gpsWasSet = true;
|
||||
latitudeMs = latMs;
|
||||
longitudeMs = longMs;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
gpsWasSet = false;
|
||||
latitudeMs = 0;
|
||||
longitudeMs = 0;
|
||||
}
|
||||
sint32 latitudeMs;
|
||||
sint32 longitudeMs;
|
||||
bool gpsWasSet;
|
||||
};
|
||||
class GpsConverterTest
|
||||
{
|
||||
public:
|
||||
GpsConverterTest()
|
||||
: canTransceiverMock()
|
||||
, converter(canTransceiverMock, acPusherMock)
|
||||
{}
|
||||
|
||||
virtual ~GpsConverterTest() {}
|
||||
|
||||
can::CanTransceiverMock canTransceiverMock;
|
||||
GpsAcPusherMock acPusherMock;
|
||||
GpsConverter converter;
|
||||
};
|
||||
|
||||
static bool withinTolerance(sint32 x1, sint32 x2, sint32 tolerance)
|
||||
{
|
||||
return abs(x1-x2) < tolerance;
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(GpsConverterTest, "london east calling", "[gps]")
|
||||
{
|
||||
uint8 payload[8] = { 0xDF, 0x48, 0xEA, 0xFF, 0x08, 0xC5, 0xA5, 0x24 };
|
||||
CANFrame gpsInfo(0x34a, payload, 8);
|
||||
converter.frameReceived(gpsInfo);
|
||||
CHECK(acPusherMock.gpsWasSet);
|
||||
CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
|
||||
CHECK(withinTolerance(acPusherMock.longitudeMs, -429429, 100));
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(GpsConverterTest, "london west calling", "[gps]")
|
||||
{
|
||||
uint8 payload[8] = { 0x1F, 0xB7, 0x15, 0x00, 0x08, 0xC5, 0xA5, 0x24 };
|
||||
CANFrame gpsInfo(0x34a, payload, 8);
|
||||
converter.frameReceived(gpsInfo);
|
||||
SECTION("receive once")
|
||||
{
|
||||
CHECK(acPusherMock.gpsWasSet);
|
||||
CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
|
||||
CHECK(withinTolerance(acPusherMock.longitudeMs, 429428, 100));
|
||||
}
|
||||
SECTION("receive twice same value, only propagate once")
|
||||
{
|
||||
CHECK(acPusherMock.gpsWasSet);
|
||||
CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
|
||||
CHECK(withinTolerance(acPusherMock.longitudeMs, 429428, 100));
|
||||
acPusherMock.clear();
|
||||
converter.frameReceived(gpsInfo);
|
||||
CHECK(!acPusherMock.gpsWasSet);
|
||||
}
|
||||
}
|
||||
TEST_CASE_METHOD(GpsConverterTest, "invalid data", "[gps]")
|
||||
{
|
||||
uint8 payload[8] = { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80 };
|
||||
CANFrame gpsInfo(0x34a, payload, 8);
|
||||
converter.frameReceived(gpsInfo);
|
||||
CHECK(!acPusherMock.gpsWasSet);
|
||||
}
|
||||
TEST_CASE_METHOD(GpsConverterTest, "no signal", "[gps]")
|
||||
{
|
||||
uint8 payload[8] = { 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F };
|
||||
CANFrame gpsInfo(0x34a, payload, 8);
|
||||
converter.frameReceived(gpsInfo);
|
||||
CHECK(!acPusherMock.gpsWasSet);
|
||||
}
|
||||
// 48.1172966,11.5913253
|
||||
// 48.1173275,11.591452
|
||||
|
||||
} // namespace test
|
||||
|
||||
|
9427
2016/ppc/gps/test/catch.hpp
Normal file
15
2016/ppc/rakefile.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
desc "build"
|
||||
task :build do
|
||||
sh "bake -m gps -b UnitTest -a black"
|
||||
end
|
||||
|
||||
desc "run"
|
||||
task :run => :build do
|
||||
sh "./gps/build_UnitTest/gpsTests.exe"
|
||||
end
|
||||
|
||||
desc "clean"
|
||||
task :clean do
|
||||
sh "bake -m gps -b UnitTest -a black -c"
|
||||
end
|