First Commit
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,34 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
buildToolsVersion "29.0.1"
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "net.nigreon.blegps"
|
||||||
|
minSdkVersion 25
|
||||||
|
targetSdkVersion 25
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||||
|
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# 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 *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,24 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import android.support.test.InstrumentationRegistry
|
||||||
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
fun useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
val appContext = InstrumentationRegistry.getTargetContext()
|
||||||
|
assertEquals("net.nigreon.blegps", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="net.nigreon.blegps">
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
<activity android:name=".MainActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<service android:name=".BLEMockLocationService" ></service>
|
||||||
|
<service android:name=".BLEHRService" ></service>
|
||||||
|
<receiver android:name=".TaskerReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="net.nigreon.blegps.TASKER_COMMAND" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
|
@ -0,0 +1,224 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.Service
|
||||||
|
import android.bluetooth.BluetoothGatt
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Binder
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.support.v4.app.NotificationCompat
|
||||||
|
import android.support.v4.content.LocalBroadcastManager
|
||||||
|
import android.util.Log
|
||||||
|
import com.clj.fastble.BleManager
|
||||||
|
import com.clj.fastble.callback.BleGattCallback
|
||||||
|
import com.clj.fastble.callback.BleNotifyCallback
|
||||||
|
import com.clj.fastble.callback.BleWriteCallback
|
||||||
|
import com.clj.fastble.data.BleDevice
|
||||||
|
import com.clj.fastble.exception.BleException
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class BLEHRService : Service() {
|
||||||
|
private val LOG_TAG = "BLEHRService"
|
||||||
|
private val CHANNEL_ID = "NotifID2"
|
||||||
|
private val binder = sBinder()
|
||||||
|
|
||||||
|
val timerActivity = Timer()
|
||||||
|
|
||||||
|
private lateinit var bleDevice: BleDevice
|
||||||
|
private val serviceHeartRateUuid: String = "0000180d-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicHRControlPointUuid: String = "00002a39-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicHRMeasurementUuid: String = "00002a37-0000-1000-8000-00805f9b34fb"
|
||||||
|
|
||||||
|
private fun initNotificationHR() {
|
||||||
|
BleManager.getInstance().notify(
|
||||||
|
bleDevice,
|
||||||
|
serviceHeartRateUuid,
|
||||||
|
characteristicHRMeasurementUuid,
|
||||||
|
object : BleNotifyCallback() {
|
||||||
|
override fun onNotifySuccess() {
|
||||||
|
Log.v(LOG_TAG, "Notify HR Success")
|
||||||
|
//initNotificationPressure()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotifyFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify HR Failure $exception")
|
||||||
|
//initNotificationPressure()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCharacteristicChanged(data: ByteArray) {
|
||||||
|
//Log.v(LOG_TAG, "Notify Temperature Characteristic changed")
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
//texttemp.text = buffer.float.toString()
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBTHRM).putExtra(ServicesConstants.BROADCAST_KEY.KEYBTHRM, buffer.get(1))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startHRBLE() {
|
||||||
|
BleManager.getInstance().connect("CC:2C:24:71:9C:BC", object : BleGattCallback() {
|
||||||
|
override fun onStartConnect() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConnectFail(bleDevice: BleDevice, exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE HR Connection Failed $exception")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConnectSuccess(
|
||||||
|
bleDeviceConnect: BleDevice,
|
||||||
|
gattConnect: BluetoothGatt,
|
||||||
|
status: Int
|
||||||
|
) {
|
||||||
|
Log.v(LOG_TAG, "BLE HR Connection OK")
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBTHR).putExtra(
|
||||||
|
ServicesConstants.BROADCAST_KEY.KEYBTSTATUSHR,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
bleDevice = bleDeviceConnect
|
||||||
|
|
||||||
|
initNotificationHR()
|
||||||
|
|
||||||
|
val t = object : TimerTask() {
|
||||||
|
override fun run() {
|
||||||
|
startHRBLEActivity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timerActivity.scheduleAtFixedRate(t, 0, 9500)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisConnected(
|
||||||
|
isActiveDisConnected: Boolean,
|
||||||
|
bleDevice: BleDevice,
|
||||||
|
gatt: BluetoothGatt,
|
||||||
|
status: Int
|
||||||
|
) {
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBTHR).putExtra(
|
||||||
|
ServicesConstants.BROADCAST_KEY.KEYBTSTATUSHR,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
timerActivity.cancel()
|
||||||
|
Log.v(LOG_TAG, "BLE HR Disconnected")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopHRBLE() {
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBTHR).putExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUSHR, false)
|
||||||
|
)
|
||||||
|
|
||||||
|
BleManager.getInstance().disconnect(bleDevice)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startHRBLEActivity() {
|
||||||
|
val data: ByteArray = byteArrayOf(0x15,0x01,0x01)
|
||||||
|
BleManager.getInstance().write(
|
||||||
|
bleDevice,
|
||||||
|
serviceHeartRateUuid,
|
||||||
|
characteristicHRControlPointUuid,
|
||||||
|
data,
|
||||||
|
object : BleWriteCallback() {
|
||||||
|
override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
|
||||||
|
//Log.v(LOG_TAG, "Start Activity sended")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWriteFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "Start Activity Failure $exception")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopHRBLEActivity() {
|
||||||
|
val data: ByteArray = byteArrayOf(0x15,0x01,0x00)
|
||||||
|
BleManager.getInstance().write(
|
||||||
|
bleDevice,
|
||||||
|
serviceHeartRateUuid,
|
||||||
|
characteristicHRControlPointUuid,
|
||||||
|
data,
|
||||||
|
object : BleWriteCallback() {
|
||||||
|
override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Stop Activity sended")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWriteFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "Stop Activity send Failure $exception")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||||
|
if(intent.action == ServicesConstants.HRSERVICEACTION.STARTFOREGROUND_ACTION) {
|
||||||
|
Log.i(LOG_TAG, "Received Start Foreground Intent ")
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
// Create the NotificationChannel
|
||||||
|
val name = "ChannelName"
|
||||||
|
val descriptionText = "ChannelDescription"
|
||||||
|
val importance = NotificationManager.IMPORTANCE_DEFAULT
|
||||||
|
val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
|
||||||
|
mChannel.description = descriptionText
|
||||||
|
// Register the channel with the system; you can't change the importance
|
||||||
|
// or other notification behaviors after this
|
||||||
|
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
notificationManager.createNotificationChannel(mChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
var notification = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||||
|
.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||||
|
.setContentTitle("BLE HR")
|
||||||
|
.setContentText("BLE HR active")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
//.setContentIntent(pendingIntent)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
//pBLE = BLEProvider(application, baseContext)
|
||||||
|
startHRBLE()
|
||||||
|
|
||||||
|
startForeground(ServicesConstants.NOTIFICATION_ID.FOREGROUND_HR_SERVICE,notification)
|
||||||
|
} else if(intent.action == ServicesConstants.HRSERVICEACTION.STOPFOREGROUND_ACTION) {
|
||||||
|
Log.i(LOG_TAG, "Received Stop Foreground Intent ")
|
||||||
|
//pBLE.disconnectBLE()
|
||||||
|
stopHRBLE()
|
||||||
|
stopForeground(true)
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
Log.i(LOG_TAG, "In onDestroy")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
|
Log.v(LOG_TAG, "in onBind")
|
||||||
|
return binder
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRebind(intent: Intent) {
|
||||||
|
Log.v(LOG_TAG, "in onRebind")
|
||||||
|
super.onRebind(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUnbind(intent: Intent): Boolean {
|
||||||
|
Log.v(LOG_TAG, "in onUnbind")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class sBinder : Binder() {
|
||||||
|
// Return this instance of LocalService so clients can call public methods
|
||||||
|
fun getService(): BLEHRService = this@BLEHRService
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,378 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.location.LocationManager
|
||||||
|
import android.os.*
|
||||||
|
import android.support.v4.app.NotificationCompat
|
||||||
|
import android.support.v4.content.LocalBroadcastManager
|
||||||
|
import android.util.Log
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.experimental.or
|
||||||
|
|
||||||
|
|
||||||
|
class BLEMockLocationService : Service() {
|
||||||
|
private val LOG_TAG = "BLEMockLocationService"
|
||||||
|
private val CHANNEL_ID = "NotifID"
|
||||||
|
public val ACTIVATION_CHANGE = 1
|
||||||
|
private lateinit var pBLE: BLEProvider
|
||||||
|
private lateinit var mockGPS: MockLocationProvider
|
||||||
|
private var locationReceived = false
|
||||||
|
private var qualityReceived = false
|
||||||
|
private var gpsverbose = false
|
||||||
|
private var gpxopened = false
|
||||||
|
private var hrenable = false
|
||||||
|
private var tempenable = false
|
||||||
|
private lateinit var gpxoutputstream: FileOutputStream
|
||||||
|
|
||||||
|
var gpsConf: GPSConfiguration = GPSConfiguration()
|
||||||
|
|
||||||
|
// Location
|
||||||
|
private var currentLatitude: Double = -1.0
|
||||||
|
private var currentLongitude: Double = -1.0
|
||||||
|
private var currentElevation: Double = -1.0
|
||||||
|
private var currentSpeed: Float = -1.0f
|
||||||
|
private var currentHeading: Float = -1.0f
|
||||||
|
private var currentEHPE: Float = -1.0f
|
||||||
|
// Quality
|
||||||
|
private var currentEVPE: Float = -1.0f
|
||||||
|
private var currentHDOP: Float = -1.0f
|
||||||
|
private var currentVDOP: Float = -1.0f
|
||||||
|
private var currentSatview: Byte = -1
|
||||||
|
private var currentSatused: Byte = -1
|
||||||
|
private var currentElevationGPS: Double = -1.0
|
||||||
|
|
||||||
|
private var currentHR: Byte = 0
|
||||||
|
private var currentTemperature: Float = 0.0f
|
||||||
|
|
||||||
|
private val binder = sBinder()
|
||||||
|
|
||||||
|
fun locationChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
Log.v(LOG_TAG, "Latitude Service Broadcast received")
|
||||||
|
currentLatitude = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONLAT,-1.0)
|
||||||
|
currentLongitude = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONLON,-1.0)
|
||||||
|
currentEHPE = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONEHPE,-1.0f)
|
||||||
|
currentElevation = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONELE,-1.0)
|
||||||
|
currentSpeed = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONSPEED,-1.0f)
|
||||||
|
currentHeading = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONHEADING,-1.0f)
|
||||||
|
mockGPS.pushLocation(currentLatitude,currentLongitude,currentElevation, currentSpeed, currentHeading, currentEHPE)
|
||||||
|
locationReceived = true
|
||||||
|
storeGPX()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun qualityChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
//Log.v(LOG_TAG, "Latitude Service Broadcast received")
|
||||||
|
currentEHPE = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYEHPE,-1.0f)
|
||||||
|
currentEVPE = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYEVPE,-1.0f)
|
||||||
|
currentHDOP = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYHDOP,-1.0f)
|
||||||
|
currentVDOP = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYVDOP,-1.0f)
|
||||||
|
currentSatview = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYSATVIEW,-1)
|
||||||
|
currentSatused = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYSATUSED,-1)
|
||||||
|
currentElevationGPS = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYELEGPS,-1.0)
|
||||||
|
qualityReceived = true
|
||||||
|
storeGPX()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun HRChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
currentHR = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYBTHRM,-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bmpStatusChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
tempenable = intent.getBooleanExtra(ServicesConstants.BROADCAST_KEY.KEYBMPSTATUS, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tempChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
currentTemperature = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYTEMP, -1.0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun taskerChanged(bundle: Bundle) {
|
||||||
|
Log.v(LOG_TAG, "taskerChanged")
|
||||||
|
if(bundle.containsKey(ServicesConstants.BROADCAST_KEY.KEYBOOST)) {
|
||||||
|
/*if (bundle.getBoolean(ServicesConstants.BROADCAST_KEY.KEYBOOST)) {
|
||||||
|
//gpsConf.gpsBoost = intent.getBooleanExtra(ServicesConstants.BROADCAST_KEY.KEYBOOST, false)
|
||||||
|
gpsConf.gpsBoost = true
|
||||||
|
} else {
|
||||||
|
gpsConf.gpsBoost = false
|
||||||
|
}*/
|
||||||
|
gpsConf.gpsBoost = bundle.getBoolean(ServicesConstants.BROADCAST_KEY.KEYBOOST)
|
||||||
|
sendConfBLE(gpsConf)
|
||||||
|
Log.v(LOG_TAG, "Received Tasker Intent : Boost ${gpsConf.gpsBoost}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun storeGPX()
|
||||||
|
{
|
||||||
|
if(gpxopened) {
|
||||||
|
if(!gpsverbose and locationReceived)
|
||||||
|
{
|
||||||
|
//writeGPX("${SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date())} $currentLatitude $currentLongitude $currentElevation m\n")
|
||||||
|
writeGPX("<trkpt lat=\"$currentLatitude\" lon=\"$currentLongitude\"><ele>$currentElevation</ele><time>${SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date())}</time></trkpt>\n")
|
||||||
|
locationReceived = false
|
||||||
|
qualityReceived = false
|
||||||
|
} else if(gpsverbose and locationReceived and qualityReceived) {
|
||||||
|
//writeGPX("${SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date())} $currentLatitude $currentLongitude $currentElevation m\n")
|
||||||
|
//writeGPX("$currentEHPE m $currentEVPE m $currentHDOP $currentVDOP $currentSatused/$currentSatview $currentElevationGPS m\n")
|
||||||
|
//if(hrenable) { writeGPX("$currentHR bpm\n")}
|
||||||
|
//if(tempenable) { writeGPX("${currentTemperature}°C\n")}
|
||||||
|
writeGPX("<trkpt lat=\"$currentLatitude\" lon=\"$currentLongitude\"><ele>$currentElevation</ele><time>${SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date())}</time>\n" +
|
||||||
|
"<extensions>\n")
|
||||||
|
if(hrenable or tempenable)
|
||||||
|
{
|
||||||
|
writeGPX("<gpxtpx:TrackPointExtension>")
|
||||||
|
if(hrenable)
|
||||||
|
{
|
||||||
|
writeGPX("<gpxtpx:atemp>$currentHR</gpxtpx:atemp>")
|
||||||
|
}
|
||||||
|
if(tempenable)
|
||||||
|
{
|
||||||
|
writeGPX("<gpxtpx:atemp>$currentTemperature</gpxtpx:atemp>")
|
||||||
|
}
|
||||||
|
writeGPX("</gpxtpx:TrackPointExtension>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
writeGPX("<blegps:BLEGPSExtension><blegps:ehpe>$currentEHPE</blegps:ehpe><blegps:evpe>$currentEVPE</blegps:evpe><blegps:hdop>$currentHDOP</blegps:hdop><blegps:vdop>$currentVDOP</blegps:vdop><blegps:satused>$currentSatused</blegps:satused><blegps:satview>$currentSatview</blegps:satview><blegps:gpselevation>$currentElevationGPS</blegps:gpselevation></blegps:BLEGPSExtension>\n")
|
||||||
|
writeGPX("</extensions>\n</trkpt>\n")
|
||||||
|
locationReceived = false
|
||||||
|
qualityReceived = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeGPX(str: String)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
gpxoutputstream.write(str.toByteArray())
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
|
||||||
|
mockGPS = MockLocationProvider(LocationManager.GPS_PROVIDER, baseContext)
|
||||||
|
|
||||||
|
val brReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
when (intent?.action) {
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERLOCATION -> locationChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERQUALITY-> qualityChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERBTHRM-> HRChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERTEMP-> tempChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERBMP-> bmpStatusChanged(intent)
|
||||||
|
|
||||||
|
|
||||||
|
//BROADCAST_CHANGE_TYPE_CHANGED -> handleChangeTypeChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val manager = LocalBroadcastManager.getInstance(this)
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERLOCATION))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERQUALITY))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERBTHRM))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERTEMP))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERBMP))
|
||||||
|
//pBLE.registerBMP()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||||
|
if(intent.action == ServicesConstants.MOCKSERVICEACTION.STARTFOREGROUND_ACTION) {
|
||||||
|
Log.i(LOG_TAG, "Received Start Foreground Intent ")
|
||||||
|
|
||||||
|
// val intentNotif = Intent(this, MainActivity::class.java)
|
||||||
|
// intentNotif.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
// intentNotif.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACT
|
||||||
|
|
||||||
|
//val pendingIntent = PendingIntent.getActivity(this, 0, intentNotif, 0)
|
||||||
|
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
// Create the NotificationChannel
|
||||||
|
val name = "ChannelName"
|
||||||
|
val descriptionText = "ChannelDescription"
|
||||||
|
val importance = NotificationManager.IMPORTANCE_DEFAULT
|
||||||
|
val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
|
||||||
|
mChannel.description = descriptionText
|
||||||
|
// Register the channel with the system; you can't change the importance
|
||||||
|
// or other notification behaviors after this
|
||||||
|
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
notificationManager.createNotificationChannel(mChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
var notification = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||||
|
.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||||
|
.setContentTitle("BLE GPS")
|
||||||
|
.setContentText("BLE & Mock active")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
//.setContentIntent(pendingIntent)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
pBLE = BLEProvider(application, baseContext)
|
||||||
|
mockGPS.start()
|
||||||
|
startForeground(ServicesConstants.NOTIFICATION_ID.FOREGROUND_MOCK_SERVICE,notification)
|
||||||
|
} else if(intent.action == ServicesConstants.MOCKSERVICEACTION.STOPFOREGROUND_ACTION) {
|
||||||
|
Log.i(LOG_TAG, "Received Stop Foreground Intent ")
|
||||||
|
pBLE.disconnectBLE()
|
||||||
|
mockGPS.shutdown()
|
||||||
|
stopForeground(true)
|
||||||
|
stopSelf()
|
||||||
|
} else if(intent.action == ServicesConstants.MOCKSERVICEACTION.TASKER_ACTION){
|
||||||
|
Log.i(LOG_TAG, "intent action : ${intent.action}")
|
||||||
|
taskerChanged(intent.extras)
|
||||||
|
}
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
Log.i(LOG_TAG, "In onDestroy")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
|
Log.v(LOG_TAG, "in onBind")
|
||||||
|
return binder
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRebind(intent: Intent) {
|
||||||
|
Log.v(LOG_TAG, "in onRebind")
|
||||||
|
super.onRebind(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUnbind(intent: Intent): Boolean {
|
||||||
|
Log.v(LOG_TAG, "in onUnbind")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendCalibrateBLE(calibrateval: Int)
|
||||||
|
{
|
||||||
|
val buffer = ByteBuffer.allocate(4)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
buffer.putInt(calibrateval)
|
||||||
|
pBLE.sendCalibrate(buffer.array())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun HRStatusChanged(enable: Boolean)
|
||||||
|
{
|
||||||
|
hrenable = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openGPX(datefilename: String) {
|
||||||
|
//val datefilename: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
|
||||||
|
var gpxfilename = File(
|
||||||
|
Environment.getExternalStorageDirectory().path + File.separator + "BTGPS",
|
||||||
|
datefilename + ".gpx"
|
||||||
|
)
|
||||||
|
var gpxdir = File(Environment.getExternalStorageDirectory().path + File.separator + "BTGPS")
|
||||||
|
var success = true;
|
||||||
|
if (!gpxdir.exists()) {
|
||||||
|
success = gpxdir.mkdir();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
if(!gpxfilename.exists()) {
|
||||||
|
try {
|
||||||
|
gpxoutputstream = FileOutputStream(gpxfilename, true)
|
||||||
|
//val gpxheader = "GPX Header\n"
|
||||||
|
val gpxheader =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" +
|
||||||
|
"<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" version=\"1.1\" " +
|
||||||
|
"xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v1\" " +
|
||||||
|
"xmlns:blegps=\"https://www.nigreon.net\"" +
|
||||||
|
">\n" +
|
||||||
|
"<metadata>" +
|
||||||
|
"<name>${datefilename}</name>" +
|
||||||
|
"<desc>${datefilename}</desc>\n" +
|
||||||
|
"<time>${SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date())}</time>\n" +
|
||||||
|
"</metadata>\n" +
|
||||||
|
"<trk>\n" +
|
||||||
|
"<name>${datefilename}</name>\n" +
|
||||||
|
"<trkseg>\n"
|
||||||
|
writeGPX(gpxheader)
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
gpxoutputstream = FileOutputStream(gpxfilename, true)
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gpxopened = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeGPX()
|
||||||
|
{
|
||||||
|
//val gpxfooter = "GPX Footer\n"
|
||||||
|
val gpxfooter = "</trkseg></trk></gpx>\n"
|
||||||
|
writeGPX(gpxfooter)
|
||||||
|
gpxoutputstream.close()
|
||||||
|
gpxopened = false
|
||||||
|
}
|
||||||
|
|
||||||
|
//fun sendConfBLE(bmpnrf: Boolean, bmpble: Boolean, bmp2gps: Boolean, exttemp: Boolean, gpsble: Boolean, gpsbleverb: Boolean, gpsserial: Boolean, gpsmode: Int, gpspoller: Short, gpssendbt: Short, bmppoller: Short) {
|
||||||
|
fun sendConfBLE(gpsConfNew: GPSConfiguration) {
|
||||||
|
gpsConf = gpsConfNew
|
||||||
|
val buffer = ByteBuffer.allocate(8)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
var activateByte1: Byte = 0
|
||||||
|
var activateByte2: Byte = 0
|
||||||
|
|
||||||
|
if(gpsConf.bmpNrf) { activateByte1 = activateByte1.or(0x01) }
|
||||||
|
if(gpsConf.bmpBT) { activateByte1 = activateByte1.or(0x02) }
|
||||||
|
if(gpsConf.bmp2gps) { activateByte1 = activateByte1.or(0x04) }
|
||||||
|
if(gpsConf.extTemp) { activateByte1 = activateByte1.or(0x08) }
|
||||||
|
|
||||||
|
if(gpsConf.gpsBLE) { activateByte2 = activateByte2.or(0x01) }
|
||||||
|
if(gpsConf.gpsVerbose) { activateByte2 = activateByte2.or(0x02) }
|
||||||
|
if(gpsConf.gpsSerial) { activateByte2 = activateByte2.or(0x04) }
|
||||||
|
if(gpsConf.gpsMode == 1 || gpsConf.gpsBoost) {
|
||||||
|
activateByte2 = activateByte2.or(0x08)
|
||||||
|
} else if(gpsConf.gpsMode == 2) {
|
||||||
|
activateByte2 = activateByte2.or(0x10)
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.put(activateByte1)
|
||||||
|
buffer.put(activateByte2)
|
||||||
|
if(gpsConf.gpsBoost) {
|
||||||
|
buffer.putShort(4)
|
||||||
|
buffer.putShort(gpsConf.bmpPollerSend)
|
||||||
|
buffer.putShort(4)
|
||||||
|
} else {
|
||||||
|
buffer.putShort(gpsConf.gpsPollerSend)
|
||||||
|
buffer.putShort(gpsConf.bmpPollerSend)
|
||||||
|
buffer.putShort(gpsConf.gpsSendBTSend)
|
||||||
|
}
|
||||||
|
pBLE.sendConf(buffer.array())
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class sBinder : Binder() {
|
||||||
|
// Return this instance of LocalService so clients can call public methods
|
||||||
|
fun getService(): BLEMockLocationService = this@BLEMockLocationService
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,389 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
import android.app.Application
|
||||||
|
import android.bluetooth.BluetoothGatt
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.support.v4.content.LocalBroadcastManager
|
||||||
|
import android.util.Log
|
||||||
|
import com.clj.fastble.BleManager
|
||||||
|
import com.clj.fastble.data.BleDevice
|
||||||
|
import com.clj.fastble.exception.BleException
|
||||||
|
import com.clj.fastble.callback.BleGattCallback
|
||||||
|
import com.clj.fastble.callback.BleNotifyCallback
|
||||||
|
import com.clj.fastble.callback.BleReadCallback
|
||||||
|
import com.clj.fastble.callback.BleWriteCallback
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.os.Handler
|
||||||
|
|
||||||
|
|
||||||
|
class BLEProvider(val application: Application, val baseContext: Context)
|
||||||
|
{
|
||||||
|
private lateinit var bleDevice: BleDevice
|
||||||
|
|
||||||
|
private val serviceEnvironmentalSensingUuid: String = "0000181a-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val serviceLNUuid: String = "00001819-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicPressureUuid: String = "00002a6d-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicTemperatureUuid: String = "00002a6e-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicLSUuid: String = "00002a67-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicPQUuid: String = "00002a69-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val serviceWriteUuid: String = "00002000-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicSatUuid: String = "00002002-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicWriteUuid: String = "00002001-0000-1000-8000-00805f9b34fb"
|
||||||
|
private val characteristicCalibrateUuid: String = "00002003-0000-1000-8000-00805f9b34fb"
|
||||||
|
|
||||||
|
private var connected = false
|
||||||
|
private var reconnectcount = 0
|
||||||
|
|
||||||
|
|
||||||
|
private val LOG_TAG = "BLEProvider"
|
||||||
|
//private lateinit var baseContext: Context
|
||||||
|
|
||||||
|
|
||||||
|
init
|
||||||
|
{
|
||||||
|
connectBLE()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delayFunction(function: ()-> Unit, delay: Long) {
|
||||||
|
Handler().postDelayed(function, delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun connectBLE()
|
||||||
|
{
|
||||||
|
//BleManager.getInstance().init(application)
|
||||||
|
/*BleManager.getInstance()
|
||||||
|
.enableLog(true)
|
||||||
|
.setReConnectCount(10, 60000)*/
|
||||||
|
|
||||||
|
//BleManager.getInstance().operateTimeout = 5000
|
||||||
|
//BleManager.getInstance().connect("24:6F:28:16:C1:F2", object : BleGattCallback() {
|
||||||
|
BleManager.getInstance().connect("E9:8E:8A:12:6F:3F", object : BleGattCallback() {
|
||||||
|
override fun onStartConnect() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConnectFail(bleDevice: BleDevice, exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Connection Failed $exception")
|
||||||
|
if(reconnectcount <= 15) {
|
||||||
|
reconnectcount++
|
||||||
|
delayFunction( { connectBLE() }, 60000)
|
||||||
|
} else {
|
||||||
|
reconnectcount=0
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBT).putExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUS, false)
|
||||||
|
)
|
||||||
|
connected=false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConnectSuccess(bleDeviceConnect: BleDevice, gattConnect: BluetoothGatt, status: Int) {
|
||||||
|
Log.v(LOG_TAG, "BLE Connection OK")
|
||||||
|
connected = true
|
||||||
|
reconnectcount = 0
|
||||||
|
bleDevice = bleDeviceConnect
|
||||||
|
//initNotificationTemperature()
|
||||||
|
object : CountDownTimer(3000, 500) {
|
||||||
|
var tickCount = 0
|
||||||
|
override fun onFinish() {
|
||||||
|
// When timer is finished
|
||||||
|
// Execute your code here
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBT).putExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUS, true)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
|
//Log.v(LOG_TAG, "Tick: $millisUntilFinished")
|
||||||
|
when (tickCount) {
|
||||||
|
0 -> initNotificationTemperature()
|
||||||
|
1 -> initNotificationPQ()
|
||||||
|
2 -> initNotificationPressure()
|
||||||
|
3 -> initNotificationSat()
|
||||||
|
4 -> initNotificationLS()
|
||||||
|
}
|
||||||
|
tickCount++
|
||||||
|
/*if(millisUntilFinished == 5000L)
|
||||||
|
{
|
||||||
|
initNotificationTemperature()
|
||||||
|
} else if(millisUntilFinished == 4000L) {
|
||||||
|
initNotificationPQ()
|
||||||
|
} else if(millisUntilFinished == 3000L) {
|
||||||
|
initNotificationPressure()
|
||||||
|
} else if(millisUntilFinished == 2000L) {
|
||||||
|
initNotificationSat()
|
||||||
|
} else if(millisUntilFinished == 1000L) {
|
||||||
|
initNotificationLS()
|
||||||
|
}*/
|
||||||
|
// millisUntilFinished The amount of time until finished.
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
//initNotificationPressure()
|
||||||
|
//initNotificationLS()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisConnected(
|
||||||
|
isActiveDisConnected: Boolean,
|
||||||
|
bleDevice: BleDevice,
|
||||||
|
gatt: BluetoothGatt,
|
||||||
|
status: Int
|
||||||
|
) {
|
||||||
|
//connected = false
|
||||||
|
//LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
// Intent(ServicesConstants.BROADCAST_FILTER.FILTERBT).putExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUS, false)
|
||||||
|
//)
|
||||||
|
Log.v(LOG_TAG, "BLE Disconnected")
|
||||||
|
if(connected) {
|
||||||
|
connectBLE()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initNotificationPressure() {
|
||||||
|
BleManager.getInstance().notify(
|
||||||
|
bleDevice,
|
||||||
|
serviceEnvironmentalSensingUuid,
|
||||||
|
characteristicPressureUuid,
|
||||||
|
object : BleNotifyCallback() {
|
||||||
|
override fun onNotifySuccess() {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify Pressure Success")
|
||||||
|
//initNotificationLS()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotifyFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify Pressure Failure $exception")
|
||||||
|
//initNotificationLS()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCharacteristicChanged(data: ByteArray) {
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
Log.v(LOG_TAG, "BLE Notify Pressure Characteristic changed")
|
||||||
|
//textpressure.text = buffer.getInt().toString()
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERPRESSURE).putExtra(ServicesConstants.BROADCAST_KEY.KEYPRESSURE, buffer.int)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initNotificationTemperature() {
|
||||||
|
BleManager.getInstance().notify(
|
||||||
|
bleDevice,
|
||||||
|
serviceEnvironmentalSensingUuid,
|
||||||
|
characteristicTemperatureUuid,
|
||||||
|
object : BleNotifyCallback() {
|
||||||
|
override fun onNotifySuccess() {
|
||||||
|
Log.v(LOG_TAG, "Notify Temperature Success")
|
||||||
|
//initNotificationPressure()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotifyFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify Temperature Failure $exception")
|
||||||
|
//initNotificationPressure()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCharacteristicChanged(data: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Notify Temperature Characteristic changed")
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
//texttemp.text = buffer.float.toString()
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERTEMP).putExtra(ServicesConstants.BROADCAST_KEY.KEYTEMP, buffer.short/100f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initNotificationLS() {
|
||||||
|
BleManager.getInstance().notify(
|
||||||
|
bleDevice,
|
||||||
|
serviceLNUuid,
|
||||||
|
characteristicLSUuid,
|
||||||
|
object : BleNotifyCallback() {
|
||||||
|
override fun onNotifySuccess() {
|
||||||
|
Log.v(LOG_TAG, "Notify LS Success")
|
||||||
|
//initNotificationPQ()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotifyFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify LS Failure $exception")
|
||||||
|
//initNotificationPQ()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||||
|
override fun onCharacteristicChanged(data: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Notify LS Characteristic changed ${data.size}")
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
//val flags: UShort = buffer.short.toUShort()
|
||||||
|
val speed: Float = buffer.short.toUShort().toFloat()/100.0f
|
||||||
|
val latitude: Double = buffer.int/10000000.0
|
||||||
|
val longitude: Double = buffer.int/10000000.0
|
||||||
|
val ehpe: Float = buffer.int.toUInt().toFloat()/100.0f
|
||||||
|
//val ehpe: Float = 5.0f
|
||||||
|
val elevation: Double = buffer.int/100.0
|
||||||
|
val heading: Float = buffer.short.toUShort().toFloat()/100.0f
|
||||||
|
Log.v(LOG_TAG, "LS $latitude $longitude $speed $heading")
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERLOCATION).putExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONLAT, latitude)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONLON, longitude)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONEHPE, ehpe)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONELE, elevation)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONSPEED, speed)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONHEADING, heading)
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initNotificationPQ() {
|
||||||
|
BleManager.getInstance().notify(
|
||||||
|
bleDevice,
|
||||||
|
serviceLNUuid,
|
||||||
|
characteristicPQUuid,
|
||||||
|
object : BleNotifyCallback() {
|
||||||
|
override fun onNotifySuccess() {
|
||||||
|
Log.v(LOG_TAG, "Notify PQ Success")
|
||||||
|
//initNotificationSat()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotifyFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify PQ Failure $exception")
|
||||||
|
//initNotificationSat()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||||
|
override fun onCharacteristicChanged(data: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Notify PQ Characteristic changed")
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
//val flags = buffer.short
|
||||||
|
val sat_view: Byte = buffer.get().toUByte().toByte()
|
||||||
|
val sat_used: Byte = buffer.get().toUByte().toByte()
|
||||||
|
val ehpe: Float = buffer.int.toUInt().toFloat()/100.0f
|
||||||
|
val evpe: Float = buffer.int.toUInt().toFloat()/100.0f
|
||||||
|
val hdop: Float = buffer.get().toUByte().toByte()*2/10.0f
|
||||||
|
val vdop: Float = buffer.get().toUByte().toByte()*2/10.0f
|
||||||
|
val elevation_gps: Double = buffer.int/100.0
|
||||||
|
Log.v(LOG_TAG, "PQ $sat_view $sat_used $ehpe $evpe $hdop $vdop $elevation_gps")
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERQUALITY).putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYSATVIEW, sat_view)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYSATUSED, sat_used)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYEHPE, ehpe)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYEVPE, evpe)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYHDOP, hdop)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYVDOP, vdop)
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYELEGPS, elevation_gps)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initNotificationSat() {
|
||||||
|
BleManager.getInstance().notify(
|
||||||
|
bleDevice,
|
||||||
|
serviceWriteUuid,
|
||||||
|
characteristicSatUuid,
|
||||||
|
object : BleNotifyCallback() {
|
||||||
|
override fun onNotifySuccess() {
|
||||||
|
Log.v(LOG_TAG, "Notify Sat Success")
|
||||||
|
//initNotificationSat()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotifyFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "BLE Notify Sat Failure $exception")
|
||||||
|
//initNotificationSat()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCharacteristicChanged(data: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Notify Sat Characteristic changed")
|
||||||
|
val buffer = ByteBuffer.wrap(data)
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERSAT).putExtra(ServicesConstants.BROADCAST_KEY.KEYSATGPSALL, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATGPSUSED, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATSBASALL, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATSBASUSED, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATGLONASSALL, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATGLONASSUSED, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATGALILEOALL, buffer.get())
|
||||||
|
.putExtra(ServicesConstants.BROADCAST_KEY.KEYSATGALILEOUSED, buffer.get())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disconnectBLE()
|
||||||
|
{
|
||||||
|
if(connected) {
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBT).putExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUS, false)
|
||||||
|
)
|
||||||
|
connected = false
|
||||||
|
|
||||||
|
|
||||||
|
BleManager.getInstance().stopNotify(
|
||||||
|
bleDevice,
|
||||||
|
serviceEnvironmentalSensingUuid,
|
||||||
|
characteristicTemperatureUuid
|
||||||
|
)
|
||||||
|
BleManager.getInstance()
|
||||||
|
.stopNotify(bleDevice, serviceEnvironmentalSensingUuid, characteristicPressureUuid)
|
||||||
|
BleManager.getInstance().stopNotify(bleDevice, serviceLNUuid, characteristicLSUuid)
|
||||||
|
BleManager.getInstance().stopNotify(bleDevice, serviceLNUuid, characteristicPQUuid)
|
||||||
|
BleManager.getInstance().stopNotify(bleDevice, serviceWriteUuid, characteristicSatUuid)
|
||||||
|
BleManager.getInstance().disconnect(bleDevice)
|
||||||
|
//BleManager.getInstance().destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendCalibrate(data: ByteArray) {
|
||||||
|
if(connected) {
|
||||||
|
BleManager.getInstance().write(
|
||||||
|
bleDevice,
|
||||||
|
serviceWriteUuid,
|
||||||
|
characteristicCalibrateUuid,
|
||||||
|
data,
|
||||||
|
object : BleWriteCallback() {
|
||||||
|
override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Conf sended")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWriteFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "Conf send Failure $exception")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun sendConf(data: ByteArray) {
|
||||||
|
if (connected) {
|
||||||
|
BleManager.getInstance().write(
|
||||||
|
bleDevice,
|
||||||
|
serviceWriteUuid,
|
||||||
|
characteristicWriteUuid,
|
||||||
|
data,
|
||||||
|
object : BleWriteCallback() {
|
||||||
|
override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
|
||||||
|
Log.v(LOG_TAG, "Conf sended")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWriteFailure(exception: BleException) {
|
||||||
|
Log.v(LOG_TAG, "Conf send Failure $exception")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*fun registerBMP()
|
||||||
|
{
|
||||||
|
initNotificationPressure()
|
||||||
|
initNotificationTemperature()
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
class GPSConfiguration {
|
||||||
|
var bmpNrf: Boolean = false
|
||||||
|
var bmpBT: Boolean = false
|
||||||
|
var bmp2gps: Boolean = false
|
||||||
|
var extTemp: Boolean = false
|
||||||
|
var gpsBLE: Boolean = false
|
||||||
|
var gpsVerbose: Boolean = false
|
||||||
|
var gpsSerial: Boolean = false
|
||||||
|
var gpsMode: Int = 0
|
||||||
|
var gpsBoost: Boolean = false
|
||||||
|
var gpsPollerSend: Short = 0
|
||||||
|
var gpsSendBTSend: Short = 0
|
||||||
|
var bmpPollerSend: Short = 0
|
||||||
|
}
|
|
@ -0,0 +1,614 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import android.support.v7.app.AppCompatActivity
|
||||||
|
import android.os.Bundle
|
||||||
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.support.v4.content.LocalBroadcastManager
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.os.Handler
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.location.Location
|
||||||
|
import com.clj.fastble.BleManager
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.os.Environment
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
//https://stackoverflow.com/questions/1625249/android-how-to-bind-spinner-to-custom-object-list
|
||||||
|
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private val LOG_TAG = "MainActivity"
|
||||||
|
|
||||||
|
private lateinit var mBoundService: BLEMockLocationService
|
||||||
|
var mServiceBound = false
|
||||||
|
|
||||||
|
private lateinit var mBoundServiceHR: BLEHRService
|
||||||
|
var mServiceBoundHR = false
|
||||||
|
|
||||||
|
var currentPressure: Int = -1
|
||||||
|
var currentTemperature: Float = -1.0f
|
||||||
|
var BTConnected = false
|
||||||
|
var BTHRConnected = false
|
||||||
|
var lastLocation: Location = Location("LastLocation")
|
||||||
|
|
||||||
|
private lateinit var gpxfilename: String
|
||||||
|
private var gpxopened = false
|
||||||
|
|
||||||
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
|
||||||
|
/*override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
// Bind to LocalService
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fun delayFunction(function: ()-> Unit, delay: Long) {
|
||||||
|
Handler().postDelayed(function, delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disconnectBT()
|
||||||
|
{
|
||||||
|
Intent(this, BLEMockLocationService::class.java).also { intent ->
|
||||||
|
intent.action = ServicesConstants.MOCKSERVICEACTION.STOPFOREGROUND_ACTION
|
||||||
|
startService(intent)
|
||||||
|
}
|
||||||
|
unbindService(mServiceConnection)
|
||||||
|
mServiceBound = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disconnectBTHR()
|
||||||
|
{
|
||||||
|
Intent(this, BLEHRService::class.java).also { intent ->
|
||||||
|
intent.action = ServicesConstants.HRSERVICEACTION.STOPFOREGROUND_ACTION
|
||||||
|
startService(intent)
|
||||||
|
}
|
||||||
|
unbindService(mServiceConnectionHR)
|
||||||
|
mServiceBoundHR = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun filter01changed(intent: Intent)
|
||||||
|
{
|
||||||
|
Log.v(LOG_TAG, "Filter01 Broadcast received")
|
||||||
|
text01.text=intent.getIntExtra(ServicesConstants.BROADCAST_KEY.KEY01,-1).toString()
|
||||||
|
|
||||||
|
}
|
||||||
|
fun temperatureChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
Log.v(LOG_TAG, "Temperature Broadcast received")
|
||||||
|
currentTemperature = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYTEMP, -1.0f)
|
||||||
|
writeBMPText()
|
||||||
|
}
|
||||||
|
fun pressureChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
Log.v(LOG_TAG, "Pressure Broadcast received")
|
||||||
|
currentPressure = intent.getIntExtra(ServicesConstants.BROADCAST_KEY.KEYPRESSURE,-1)
|
||||||
|
writeBMPText()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BTChanged(intent: Intent)
|
||||||
|
{
|
||||||
|
val connected = intent.getBooleanExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUS,false)
|
||||||
|
if(connected) {
|
||||||
|
BTConnected=true
|
||||||
|
text01.text = "BT Connected"
|
||||||
|
Log.v(LOG_TAG, "BT Connected Broadcast received")
|
||||||
|
mBoundService.HRStatusChanged(BTHRConnected)
|
||||||
|
sendConfToBLEService()
|
||||||
|
if(swlog2file.isChecked())
|
||||||
|
{
|
||||||
|
mBoundService.openGPX(gpxfilename)
|
||||||
|
gpxopened = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text01.text = "BT Disconnected"
|
||||||
|
Log.v(LOG_TAG, "BT Disconnected Broadcast received")
|
||||||
|
BTConnected=false
|
||||||
|
swblepower.setChecked(false)
|
||||||
|
}
|
||||||
|
writeBMPText()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BTChangedHR(intent: Intent)
|
||||||
|
{
|
||||||
|
val connected = intent.getBooleanExtra(ServicesConstants.BROADCAST_KEY.KEYBTSTATUSHR,false)
|
||||||
|
if(connected) {
|
||||||
|
BTHRConnected=true
|
||||||
|
text01.text = "BT HR Connected"
|
||||||
|
Log.v(LOG_TAG, "BT HR Connected Broadcast received")
|
||||||
|
if(BTConnected) { mBoundService.HRStatusChanged(true) }
|
||||||
|
} else {
|
||||||
|
text01.text = "BT HR Disconnected"
|
||||||
|
Log.v(LOG_TAG, "BT HR Disconnected Broadcast received")
|
||||||
|
BTHRConnected=false
|
||||||
|
if(BTConnected) { mBoundService.HRStatusChanged(false) }
|
||||||
|
}
|
||||||
|
writeBMPText()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BTChangedHRM(intent: Intent)
|
||||||
|
{
|
||||||
|
texthr.text = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYBTHRM,0).toString() + " bpm"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertLatLon(latitude: Double, longitude: Double): String {
|
||||||
|
val builder = StringBuilder()
|
||||||
|
|
||||||
|
|
||||||
|
val latitudeDegrees = Location.convert(Math.abs(latitude), Location.FORMAT_MINUTES)
|
||||||
|
//val latitudeSplit1 = latitudeDegrees.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
if (latitude < 0) {
|
||||||
|
builder.append("S ")
|
||||||
|
} else {
|
||||||
|
builder.append("N ")
|
||||||
|
}
|
||||||
|
val latitudeSplit1 = latitudeDegrees.split(':')
|
||||||
|
builder.append(latitudeSplit1[0])
|
||||||
|
builder.append("°")
|
||||||
|
val latitudeSplit2 = latitudeSplit1[1].split(',')
|
||||||
|
builder.append(latitudeSplit2[0])
|
||||||
|
builder.append(".")
|
||||||
|
builder.append(latitudeSplit2[1])
|
||||||
|
builder.append(" ")
|
||||||
|
|
||||||
|
|
||||||
|
val longitudeDegrees = Location.convert(Math.abs(longitude), Location.FORMAT_MINUTES)
|
||||||
|
if (longitude < 0) {
|
||||||
|
builder.append("W ")
|
||||||
|
} else {
|
||||||
|
builder.append("E ")
|
||||||
|
}
|
||||||
|
val longitudeSplit1 = longitudeDegrees.split(':')
|
||||||
|
builder.append(longitudeSplit1[0])
|
||||||
|
builder.append("°")
|
||||||
|
val longitudeSplit2 = longitudeSplit1[1].split(',')
|
||||||
|
builder.append(longitudeSplit2[0])
|
||||||
|
builder.append(".")
|
||||||
|
builder.append(longitudeSplit2[1])
|
||||||
|
|
||||||
|
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeBMPText()
|
||||||
|
{
|
||||||
|
textbmp.text = "${currentPressure/100.0f} hPa $currentTemperature°C"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeLocationText(intent: Intent)
|
||||||
|
{
|
||||||
|
val currentLatitude = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONLAT,-1.0)
|
||||||
|
val currentLongitude = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONLON,-1.0)
|
||||||
|
val currentEHPE = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONEHPE,-1.0f)
|
||||||
|
val currentElevation = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONELE,-1.0)
|
||||||
|
val currentSpeed = (intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONSPEED,-1.0f))/1000.0f*3600.0f
|
||||||
|
val currentHeading = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYLOCATIONHEADING,-1.0f)
|
||||||
|
var currentLocation: Location = Location("CurrentLocation")
|
||||||
|
currentLocation.latitude = currentLatitude
|
||||||
|
currentLocation.longitude = currentLongitude
|
||||||
|
|
||||||
|
textlastfix.text = "${SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS").format(Date())}"
|
||||||
|
textlocation.text = "${convertLatLon(currentLatitude, currentLongitude)} $currentElevation m \n $currentLatitude $currentLongitude $currentElevation m"
|
||||||
|
textspeedheading.text = "$currentSpeed km/h $currentHeading° ${currentLocation.distanceTo(lastLocation)} m"
|
||||||
|
lastLocation = currentLocation
|
||||||
|
|
||||||
|
if(swblegpsverbose.isChecked == false) {
|
||||||
|
textquality.text = "$currentEHPE m"
|
||||||
|
textsatellites.text = "Satellites in verbose"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeQualityText(intent: Intent)
|
||||||
|
{
|
||||||
|
val currentEHPE = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYEHPE,-1.0f)
|
||||||
|
val currentEVPE = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYEVPE,-1.0f)
|
||||||
|
val currentHDOP = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYHDOP,-1.0f)
|
||||||
|
val currentVDOP = intent.getFloatExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYVDOP,-1.0f)
|
||||||
|
val sat_view = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYSATVIEW,-1)
|
||||||
|
val sat_used = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYSATUSED,-1)
|
||||||
|
val elevation_gps = intent.getDoubleExtra(ServicesConstants.BROADCAST_KEY.KEYQUALITYELEGPS,-1.0)
|
||||||
|
textquality.text = "$currentEHPE m $currentEVPE m $currentHDOP $currentVDOP $sat_used/$sat_view $elevation_gps m"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeSatText(intent: Intent)
|
||||||
|
{
|
||||||
|
val gpsall = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATGPSALL,-1)
|
||||||
|
val gpsused = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATGPSUSED,-1)
|
||||||
|
val sbasall = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATSBASALL,-1)
|
||||||
|
val sbasused = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATSBASUSED,-1)
|
||||||
|
val glonassall = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATGLONASSALL,-1)
|
||||||
|
val glonassused = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATGLONASSUSED,-1)
|
||||||
|
val galileoall = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATGALILEOALL,-1)
|
||||||
|
val galileoused = intent.getByteExtra(ServicesConstants.BROADCAST_KEY.KEYSATGALILEOUSED,-1)
|
||||||
|
textsatellites.text = "GPS: $gpsused/$gpsall SBAS: $sbasused/$sbasall GLONASS: $glonassused/$glonassall GALILEO: $galileoused/$galileoall"
|
||||||
|
}
|
||||||
|
private fun sendCalibrateToBLEService()
|
||||||
|
{
|
||||||
|
if(BTConnected) {
|
||||||
|
val calibrateval: Int = editcalibratebmp2gps.text.toString().toInt()*100
|
||||||
|
mBoundService.sendCalibrateBLE(calibrateval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private fun sendConfToBLEService()
|
||||||
|
{
|
||||||
|
if(BTConnected) {
|
||||||
|
val bmppollersend: Float = resources.getStringArray(R.array.pollerval)[spinbmp.selectedItemPosition].toFloat() * 4
|
||||||
|
var gpspollersend: Float
|
||||||
|
var gpssendbtsend: Float
|
||||||
|
var gpsmode: Int
|
||||||
|
|
||||||
|
/*if(swblegpsboost.isChecked)
|
||||||
|
{
|
||||||
|
gpspollersend = 4f
|
||||||
|
gpssendbtsend = 4f
|
||||||
|
gpsmode = 1
|
||||||
|
} else {*/
|
||||||
|
gpspollersend = resources.getStringArray(R.array.pollerval)[spingps.selectedItemPosition].toFloat() * 4
|
||||||
|
gpssendbtsend = resources.getStringArray(R.array.pollerval)[spingpssendbt.selectedItemPosition].toFloat() * 4
|
||||||
|
gpsmode = spingpsmode.selectedItemPosition
|
||||||
|
//}
|
||||||
|
|
||||||
|
var gpsConf: GPSConfiguration = GPSConfiguration()
|
||||||
|
|
||||||
|
gpsConf.bmpNrf = swbmpnrf.isChecked
|
||||||
|
gpsConf.bmpBT = swbmpbt.isChecked
|
||||||
|
gpsConf.bmp2gps = swbmp2gps.isChecked
|
||||||
|
gpsConf.extTemp = swexttemp.isChecked
|
||||||
|
gpsConf.gpsBLE = swgpsble.isChecked
|
||||||
|
gpsConf.gpsVerbose = swblegpsverbose.isChecked
|
||||||
|
//gpsConf.gpsBoost = swblegpsboost.isChecked
|
||||||
|
gpsConf.gpsSerial = swgpsserial.isChecked
|
||||||
|
gpsConf.gpsMode = gpsmode
|
||||||
|
gpsConf.gpsPollerSend = gpspollersend.toShort()
|
||||||
|
gpsConf.gpsSendBTSend = gpssendbtsend.toShort()
|
||||||
|
gpsConf.bmpPollerSend = bmppollersend.toShort()
|
||||||
|
|
||||||
|
mBoundService.sendConfBLE(gpsConf)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private fun sendStopConfToBLEService()
|
||||||
|
{
|
||||||
|
if(BTConnected) {
|
||||||
|
val gpspollersend: Float =
|
||||||
|
resources.getStringArray(R.array.pollerval)[spingps.selectedItemPosition].toFloat() * 4
|
||||||
|
val bmppollersend: Float =
|
||||||
|
resources.getStringArray(R.array.pollerval)[spinbmp.selectedItemPosition].toFloat() * 4
|
||||||
|
val gpssendbtsend: Float =
|
||||||
|
resources.getStringArray(R.array.pollerval)[spingpssendbt.selectedItemPosition].toFloat() * 4
|
||||||
|
|
||||||
|
var gpsConf: GPSConfiguration = GPSConfiguration()
|
||||||
|
|
||||||
|
gpsConf.bmpNrf = false
|
||||||
|
gpsConf.bmpBT = false
|
||||||
|
gpsConf.bmp2gps = false
|
||||||
|
gpsConf.extTemp = false
|
||||||
|
gpsConf.gpsBLE = false
|
||||||
|
gpsConf.gpsVerbose = false
|
||||||
|
gpsConf.gpsSerial = false
|
||||||
|
gpsConf.gpsMode = spingpsmode.selectedItemPosition
|
||||||
|
gpsConf.gpsPollerSend = gpspollersend.toShort()
|
||||||
|
gpsConf.gpsSendBTSend = gpssendbtsend.toShort()
|
||||||
|
gpsConf.bmpPollerSend = bmppollersend.toShort()
|
||||||
|
|
||||||
|
mBoundService.sendConfBLE(gpsConf)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
|
BleManager.getInstance().init(application)
|
||||||
|
BleManager.getInstance()
|
||||||
|
.enableLog(true)
|
||||||
|
.setReConnectCount(1, 5000)
|
||||||
|
|
||||||
|
BleManager.getInstance().operateTimeout = 5000
|
||||||
|
|
||||||
|
val brReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
|
||||||
|
when (intent?.action) {
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTER01 -> filter01changed(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERBT -> BTChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERBTHR -> BTChangedHR(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERBTHRM -> BTChangedHRM(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERTEMP -> temperatureChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERPRESSURE -> pressureChanged(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERLOCATION -> writeLocationText(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERQUALITY -> writeQualityText(intent)
|
||||||
|
ServicesConstants.BROADCAST_FILTER.FILTERSAT -> writeSatText(intent)
|
||||||
|
|
||||||
|
//BROADCAST_CHANGE_TYPE_CHANGED -> handleChangeTypeChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spinbmp.setSelection(11)
|
||||||
|
spingps.setSelection(3)
|
||||||
|
spingpsmode.setSelection(1)
|
||||||
|
spingpssendbt.setSelection(10)
|
||||||
|
|
||||||
|
lastLocation.latitude = 0.0
|
||||||
|
lastLocation.longitude = 0.0
|
||||||
|
|
||||||
|
sharedPreferences = baseContext.getSharedPreferences("blegps_config", MODE_PRIVATE)
|
||||||
|
|
||||||
|
/*sharedPreferences
|
||||||
|
.edit()
|
||||||
|
.putInt("inttest", 64)
|
||||||
|
.putString("stringtest", "24:6F:28:16:C1:F2")
|
||||||
|
.apply()*/
|
||||||
|
|
||||||
|
//text01.text = "MAC ${sharedPreferences.getString("stringtest", null)}"
|
||||||
|
|
||||||
|
//mButton.setEnabled(false)
|
||||||
|
|
||||||
|
/*buttonread.setOnClickListener {
|
||||||
|
//text01.text=edit01.text.toString()
|
||||||
|
BleManager.getInstance().read(
|
||||||
|
bleDevice,
|
||||||
|
serviceWriteUuid,
|
||||||
|
characteristicWriteUuid,
|
||||||
|
object : BleReadCallback() {
|
||||||
|
override fun onReadSuccess(data: ByteArray) {
|
||||||
|
text01.text = "Read OK"
|
||||||
|
textread.text = data.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReadFailure(exception: BleException) {
|
||||||
|
text01.text = "Read Failure $exception"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
buttonwrite.setOnClickListener {
|
||||||
|
val writeba: ByteArray = edit01.text.toString().toByteArray()
|
||||||
|
BleManager.getInstance().write(
|
||||||
|
bleDevice,
|
||||||
|
serviceWriteUuid,
|
||||||
|
characteristicWriteUuid,
|
||||||
|
writeba,
|
||||||
|
object : BleWriteCallback() {
|
||||||
|
override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
|
||||||
|
text01.text = "Write OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWriteFailure(exception: BleException) {
|
||||||
|
text01.text = "Write Failure $exception"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
swblepower.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
if(isChecked) {
|
||||||
|
Intent(this, BLEMockLocationService::class.java).also { intent ->
|
||||||
|
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)
|
||||||
|
intent.action = ServicesConstants.MOCKSERVICEACTION.STARTFOREGROUND_ACTION
|
||||||
|
startService(intent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendStopConfToBLEService()
|
||||||
|
delayFunction({ disconnectBT() }, 1500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swblehrpower.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
if(isChecked) {
|
||||||
|
Intent(this, BLEHRService::class.java).also { intent ->
|
||||||
|
bindService(intent, mServiceConnectionHR, Context.BIND_AUTO_CREATE)
|
||||||
|
intent.action = ServicesConstants.HRSERVICEACTION.STARTFOREGROUND_ACTION
|
||||||
|
startService(intent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//sendStopConfToBLEService()
|
||||||
|
delayFunction({ disconnectBTHR() }, 1500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swbmpnrf.setOnCheckedChangeListener { _,_ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
swbmpbt.setOnCheckedChangeListener { _, checked ->
|
||||||
|
if(checked) {
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBMP).putExtra(ServicesConstants.BROADCAST_KEY.KEYBMPSTATUS, true)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LocalBroadcastManager.getInstance(baseContext).sendBroadcast(
|
||||||
|
Intent(ServicesConstants.BROADCAST_FILTER.FILTERBMP).putExtra(ServicesConstants.BROADCAST_KEY.KEYBMPSTATUS, false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
swbmp2gps.setOnCheckedChangeListener { _,_ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
swexttemp.setOnCheckedChangeListener { _,_ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
swgpsble.setOnCheckedChangeListener { _,_ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
swblegpsverbose.setOnCheckedChangeListener { _, _ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
swgpsserial.setOnCheckedChangeListener { _,_ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
/*swblegpsboost.setOnCheckedChangeListener { _,_ ->
|
||||||
|
sendConfToBLEService()
|
||||||
|
}*/
|
||||||
|
swlog2file.setOnCheckedChangeListener { _, checked ->
|
||||||
|
if(checked) {
|
||||||
|
gpxfilename = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
|
||||||
|
if (BTConnected) {
|
||||||
|
mBoundService.openGPX(gpxfilename)
|
||||||
|
gpxopened = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(BTConnected) {
|
||||||
|
mBoundService.closeGPX()
|
||||||
|
} else if(gpxopened) {
|
||||||
|
var gpxhandle = File(
|
||||||
|
Environment.getExternalStorageDirectory().path + File.separator + "BTGPS",
|
||||||
|
gpxfilename + ".gpx"
|
||||||
|
)
|
||||||
|
var gpxoutputstream = FileOutputStream(gpxhandle, true)
|
||||||
|
try {
|
||||||
|
val gpxfooter = "</trkseg></trk></gpx>\n"
|
||||||
|
gpxoutputstream.write(gpxfooter.toByteArray())
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
gpxoutputstream.close()
|
||||||
|
}
|
||||||
|
gpxopened = false
|
||||||
|
}
|
||||||
|
//sendConfToBLEService()
|
||||||
|
}
|
||||||
|
|
||||||
|
spingpsmode.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onNothingSelected(p0: AdapterView<*>?) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
spinbmp.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onNothingSelected(p0: AdapterView<*>?) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
spingps.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onNothingSelected(p0: AdapterView<*>?) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
spingpssendbt.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onNothingSelected(p0: AdapterView<*>?) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
||||||
|
sendConfToBLEService()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buttoncalibratebmp2gps.setOnClickListener {
|
||||||
|
//text01.text = editcalibratebmp2gps.text
|
||||||
|
sendCalibrateToBLEService()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*startmock.setOnClickListener {
|
||||||
|
//val startIntent = Intent(this,BLEMockLocationService::class.java)
|
||||||
|
//startIntent.action = ServicesConstants.MOCKSERVICEACTION.STARTFOREGROUND_ACTION
|
||||||
|
//startService(startIntent)
|
||||||
|
Intent(this, BLEMockLocationService::class.java).also { intent ->
|
||||||
|
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)
|
||||||
|
intent.action = ServicesConstants.MOCKSERVICEACTION.STARTFOREGROUND_ACTION
|
||||||
|
startService(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stopmock.setOnClickListener {
|
||||||
|
//val stopIntent = Intent(this,BLEMockLocationService::class.java)
|
||||||
|
//stopIntent.action = ServicesConstants.MOCKSERVICEACTION.STOPFOREGROUND_ACTION
|
||||||
|
//startService(stopIntent)
|
||||||
|
//LocalBroadcastManager.getInstance(this)
|
||||||
|
// .unregisterReceiver(brReceiver)
|
||||||
|
Intent(this, BLEMockLocationService::class.java).also { intent ->
|
||||||
|
intent.action = ServicesConstants.MOCKSERVICEACTION.STOPFOREGROUND_ACTION
|
||||||
|
startService(intent)
|
||||||
|
}
|
||||||
|
unbindService(mServiceConnection)
|
||||||
|
mServiceBound = false
|
||||||
|
|
||||||
|
}*/
|
||||||
|
/*bCounter.setOnClickListener {
|
||||||
|
textread.text=mBoundService.getCounter().toString()
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
val manager = LocalBroadcastManager.getInstance(this)
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTER01))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERBT))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERBTHR))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERBTHRM))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERTEMP))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERPRESSURE))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERLOCATION))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERQUALITY))
|
||||||
|
manager.registerReceiver(brReceiver, IntentFilter(ServicesConstants.BROADCAST_FILTER.FILTERSAT))
|
||||||
|
|
||||||
|
//LocalBroadcastManager.getInstance(this)
|
||||||
|
// .unregisterReceiver(broadCastReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
if(!swlog2file.isChecked) {
|
||||||
|
swblegpsverbose.setChecked(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mServiceConnection = object : ServiceConnection {
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
|
mServiceBound = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||||
|
val binder = service as BLEMockLocationService.sBinder
|
||||||
|
mBoundService = binder.getService()
|
||||||
|
mServiceBound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mServiceConnectionHR = object : ServiceConnection {
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
|
mServiceBoundHR = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||||
|
val binderHR = service as BLEHRService.sBinder
|
||||||
|
mBoundServiceHR = binderHR.getService()
|
||||||
|
mServiceBoundHR = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.location.Location
|
||||||
|
import android.location.LocationManager
|
||||||
|
import android.os.SystemClock
|
||||||
|
|
||||||
|
class MockLocationProvider(val providerName: String, val ctx: Context) {
|
||||||
|
|
||||||
|
private val lm = ctx.getSystemService(
|
||||||
|
Context.LOCATION_SERVICE
|
||||||
|
) as LocationManager
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
|
||||||
|
lm.addTestProvider(
|
||||||
|
providerName, false, false, false, false, true,
|
||||||
|
true, true, 0, 5
|
||||||
|
)
|
||||||
|
lm.setTestProviderEnabled(providerName, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pushLocation(lat: Double, lon: Double, alt: Double, speed: Float, heading: Float, accuracy: Float) {
|
||||||
|
val mockLocation = Location(providerName)
|
||||||
|
mockLocation.latitude = lat
|
||||||
|
mockLocation.longitude = lon
|
||||||
|
mockLocation.altitude = alt
|
||||||
|
mockLocation.speed = speed
|
||||||
|
mockLocation.bearing = heading
|
||||||
|
mockLocation.time = System.currentTimeMillis()
|
||||||
|
mockLocation.accuracy = accuracy
|
||||||
|
mockLocation.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
|
||||||
|
|
||||||
|
lm.setTestProviderLocation(providerName, mockLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shutdown() {
|
||||||
|
lm.removeTestProvider(providerName)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
class ServicesConstants {
|
||||||
|
interface MOCKSERVICEACTION {
|
||||||
|
companion object {
|
||||||
|
val MAIN_ACTION = "net.nigreon.blegps.mockservice.action.main"
|
||||||
|
val STARTFOREGROUND_ACTION = "net.nigreon.blegps.mockservice.action.startforeground"
|
||||||
|
val STOPFOREGROUND_ACTION = "net.nigreon.blegps.mockservice.action.stopforeground"
|
||||||
|
val TASKER_ACTION = "net.nigreon.blegps.mockservice.action.tasker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interface HRSERVICEACTION {
|
||||||
|
companion object {
|
||||||
|
//val MAIN_ACTION = "net.nigreon.blegps.mockservice.action.main"
|
||||||
|
val STARTFOREGROUND_ACTION = "net.nigreon.blegps.hrservice.action.startforeground"
|
||||||
|
val STOPFOREGROUND_ACTION = "net.nigreon.blegps.hrservice.action.stopforeground"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interface NOTIFICATION_ID {
|
||||||
|
companion object {
|
||||||
|
val FOREGROUND_MOCK_SERVICE = 101
|
||||||
|
val FOREGROUND_HR_SERVICE = 102
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interface BROADCAST_FILTER {
|
||||||
|
companion object {
|
||||||
|
const val FILTER01 = "just.a.filter"
|
||||||
|
const val FILTERBT = "filter.bt"
|
||||||
|
const val FILTERBMP = "filter.bmp"
|
||||||
|
const val FILTERBTHR = "filter.bthr"
|
||||||
|
const val FILTERBTHRM = "filter.bthrm"
|
||||||
|
const val FILTERTEMP = "filter.temp"
|
||||||
|
const val FILTERPRESSURE = "filter.pressure"
|
||||||
|
const val FILTERLOCATION = "filter.location"
|
||||||
|
const val FILTERQUALITY = "filter.quality"
|
||||||
|
const val FILTERSAT = "filter.sat"
|
||||||
|
const val FILTERTASKER= "filter.tasker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interface BROADCAST_KEY {
|
||||||
|
companion object {
|
||||||
|
const val KEY01 = "key01"
|
||||||
|
const val KEYBTSTATUS = "btstatus"
|
||||||
|
const val KEYBTSTATUSHR = "btstatushr"
|
||||||
|
const val KEYBTHRM = "bthrm"
|
||||||
|
const val KEYBMPSTATUS = "bmpstatus"
|
||||||
|
const val KEYTEMP = "temperature"
|
||||||
|
const val KEYPRESSURE = "pressure"
|
||||||
|
const val KEYBOOST = "boost"
|
||||||
|
const val KEYLOCATIONLAT = "latitude"
|
||||||
|
const val KEYLOCATIONLON = "longitude"
|
||||||
|
const val KEYLOCATIONELE = "elevation"
|
||||||
|
const val KEYLOCATIONSPEED = "speed"
|
||||||
|
const val KEYLOCATIONHEADING = "heading"
|
||||||
|
const val KEYLOCATIONEHPE = "lehpe"
|
||||||
|
const val KEYQUALITYSATVIEW = "satview"
|
||||||
|
const val KEYQUALITYSATUSED = "satused"
|
||||||
|
const val KEYQUALITYEHPE = "ehpe"
|
||||||
|
const val KEYQUALITYEVPE = "evpe"
|
||||||
|
const val KEYQUALITYHDOP = "hdop"
|
||||||
|
const val KEYQUALITYVDOP = "vdop"
|
||||||
|
const val KEYQUALITYELEGPS = "elevation_gps"
|
||||||
|
const val KEYSATGPSALL = "gpsall"
|
||||||
|
const val KEYSATGPSUSED = "gpsused"
|
||||||
|
const val KEYSATSBASALL = "sbasall"
|
||||||
|
const val KEYSATSBASUSED = "sbasused"
|
||||||
|
const val KEYSATGLONASSALL = "glonassall"
|
||||||
|
const val KEYSATGLONASSUSED = "glonassused"
|
||||||
|
const val KEYSATGALILEOALL = "galileoall"
|
||||||
|
const val KEYSATGALILEOUSED = "galileoused"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.support.v4.content.ContextCompat
|
||||||
|
import android.support.v4.content.LocalBroadcastManager
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
class TaskerReceiver: BroadcastReceiver() {
|
||||||
|
private val LOG_TAG = "TaskerReceiver"
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
Log.v(LOG_TAG, "Receive")
|
||||||
|
val serviceIntent = Intent(context, BLEMockLocationService::class.java)
|
||||||
|
serviceIntent.action=ServicesConstants.MOCKSERVICEACTION.TASKER_ACTION
|
||||||
|
|
||||||
|
//serviceIntent.putExtras(Intent(ServicesConstants.BROADCAST_FILTER.FILTERTASKER).putExtra(ServicesConstants.BROADCAST_KEY.KEYBOOST, false))
|
||||||
|
serviceIntent.putExtras(intent)
|
||||||
|
//LocalBroadcastManager.getInstance(context).sendBroadcast(
|
||||||
|
// Intent(ServicesConstants.BROADCAST_FILTER.FILTERTASKER).putExtra(ServicesConstants.BROADCAST_KEY.KEYBOOST, true))
|
||||||
|
ContextCompat.startForegroundService(context, serviceIntent)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="78.5885"
|
||||||
|
android:endY="90.9159"
|
||||||
|
android:startX="48.7653"
|
||||||
|
android:startY="61.0927"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,170 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#008577"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,338 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<Switch
|
||||||
|
android:text="BLE GPS Power"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swblepower">
|
||||||
|
|
||||||
|
</Switch>
|
||||||
|
<Switch
|
||||||
|
android:text="BLE HR Power"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swblehrpower"/>
|
||||||
|
<!--<Button
|
||||||
|
android:text="Start Mock"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/startmock"/>
|
||||||
|
<Button
|
||||||
|
android:text="Stop Mock"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/stopmock"/>-->
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<Switch
|
||||||
|
android:text="BMP nRF"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swbmpnrf"/>
|
||||||
|
<Switch
|
||||||
|
android:text="BMP BT"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swbmpbt"/>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:text="Ext Temp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swexttemp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:text="GPS BLE"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swgpsble"/>
|
||||||
|
<Switch
|
||||||
|
android:text="GPS Serial"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swgpsserial"/>
|
||||||
|
<Switch
|
||||||
|
android:text="BMP2GPS"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swbmp2gps"/>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Hello"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/text01"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Last fix time"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textlastfix"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Notification BMP"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textbmp"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Location"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textlocation"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Speed/Heading"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textspeedheading"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="HR"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/texthr"/>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<Switch
|
||||||
|
android:text="BLE GPS Verbose"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swblegpsverbose"/>
|
||||||
|
<Switch
|
||||||
|
android:text="Log2File"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swlog2file"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Quality"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textquality"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Satellites"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textsatellites"/>
|
||||||
|
<!-- <TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Read"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textread"/>
|
||||||
|
<EditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:hint="Value Hint"
|
||||||
|
android:id="@+id/edit01"/>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<Button
|
||||||
|
android:text="Read"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/buttonread"/>
|
||||||
|
<Button
|
||||||
|
android:text="Write"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/buttonwrite"/>
|
||||||
|
<Button
|
||||||
|
android:text="Get Counter"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/bCounter"/>
|
||||||
|
</LinearLayout>-->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="BMP Poller"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textspinbmp"/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinbmp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:entries="@array/poller" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="GPS Mode"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textspingpsmode"/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spingpsmode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:entries="@array/gpsmode"/>
|
||||||
|
<!--<Switch
|
||||||
|
android:text="BLE GPS Boost"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/swblegpsboost"/>-->
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="GPS Poller"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textspingps"/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spingps"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:entries="@array/poller"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="GPS BT"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textspingpssendbt"/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spingpssendbt"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:entries="@array/poller"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context=".MainActivity"
|
||||||
|
android:focusableInTouchMode="true">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Calibrate BMP2GPS"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/textcalibratebmp2gps"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/editcalibratebmp2gps"
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:inputType="number" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Calibrate"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:id="@+id/buttoncalibratebmp2gps"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#008577</color>
|
||||||
|
<color name="colorPrimaryDark">#00574B</color>
|
||||||
|
<color name="colorAccent">#D81B60</color>
|
||||||
|
</resources>
|
|
@ -0,0 +1,76 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">BLEGPS</string>
|
||||||
|
<string-array name="poller">
|
||||||
|
<!--<item>250 ms</item>
|
||||||
|
<item>500 ms</item>
|
||||||
|
<item>750 ms</item>-->
|
||||||
|
<item>1 s</item>
|
||||||
|
<item>2 s</item>
|
||||||
|
<item>3 s</item>
|
||||||
|
<item>4 s</item>
|
||||||
|
<item>5 s</item>
|
||||||
|
<item>6 s</item>
|
||||||
|
<item>7 s</item>
|
||||||
|
<item>8 s</item>
|
||||||
|
<item>9 s</item>
|
||||||
|
<item>10 s</item>
|
||||||
|
<item>20 s</item>
|
||||||
|
<item>30 s</item>
|
||||||
|
<item>40 s</item>
|
||||||
|
<item>50 s</item>
|
||||||
|
<item>1 min</item>
|
||||||
|
<item>2 min</item>
|
||||||
|
<item>3 min</item>
|
||||||
|
<item>4 min</item>
|
||||||
|
<item>5 min</item>
|
||||||
|
<item>6 min</item>
|
||||||
|
<item>7 min</item>
|
||||||
|
<item>8 min</item>
|
||||||
|
<item>9 min</item>
|
||||||
|
<item>10 min</item>
|
||||||
|
<item>20 min</item>
|
||||||
|
<item>30 min</item>
|
||||||
|
<item>40 min</item>
|
||||||
|
<item>50 min</item>
|
||||||
|
<item>60 min</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="pollerval">
|
||||||
|
<!--<item>0.25</item>
|
||||||
|
<item>0.50</item>
|
||||||
|
<item>0.75</item>-->
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
<item>8</item>
|
||||||
|
<item>9</item>
|
||||||
|
<item>10</item>
|
||||||
|
<item>20</item>
|
||||||
|
<item>30</item>
|
||||||
|
<item>40</item>
|
||||||
|
<item>50</item>
|
||||||
|
<item>60</item>
|
||||||
|
<item>120</item>
|
||||||
|
<item>180</item>
|
||||||
|
<item>240</item>
|
||||||
|
<item>300</item>
|
||||||
|
<item>360</item>
|
||||||
|
<item>420</item>
|
||||||
|
<item>480</item>
|
||||||
|
<item>540</item>
|
||||||
|
<item>600</item>
|
||||||
|
<item>1200</item>
|
||||||
|
<item>1800</item>
|
||||||
|
<item>2400</item>
|
||||||
|
<item>3000</item>
|
||||||
|
<item>3600</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="gpsmode">
|
||||||
|
<item>Auto</item>
|
||||||
|
<item>Normal</item>
|
||||||
|
<item>Eco</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package net.nigreon.blegps
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.3.31'
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 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.
|
||||||
|
org.gradle.jvmargs=-Xmx256m
|
||||||
|
# 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
|
||||||
|
# Kotlin code style for this project: "official" or "obsolete":
|
||||||
|
kotlin.code.style=official
|
|
@ -0,0 +1 @@
|
||||||
|
include ':app'
|