Merge branch 'pull/2542' into dagger3

This commit is contained in:
Milos Kozak 2020-04-02 18:48:37 +02:00
commit 615b025600
20 changed files with 423 additions and 116 deletions

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@ -43,6 +44,7 @@ import info.nightscout.androidaps.plugins.configBuilder.PluginStore;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.receivers.BTReceiver;
import info.nightscout.androidaps.receivers.ChargingStateReceiver;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
@ -199,6 +201,11 @@ public class MainApp extends DaggerApplication {
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(new ChargingStateReceiver(), filter);
filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(new BTReceiver(), filter);
}
@Deprecated

View file

@ -95,6 +95,7 @@ interface AppComponent : AndroidInjector<MainApp> {
fun injectTrigger(triggerAutosensValue: TriggerAutosensValue)
fun injectTrigger(triggerBg: TriggerBg)
fun injectTrigger(triggerBolusAgo: TriggerBolusAgo)
fun injectTrigger(triggerBTDevice: TriggerBTDevice)
fun injectTrigger(triggerCOB: TriggerCOB)
fun injectTrigger(triggerConnector: TriggerConnector)
fun injectTrigger(triggerDelta: TriggerDelta)
@ -127,8 +128,10 @@ interface AppComponent : AndroidInjector<MainApp> {
fun injectElement(inputButton: InputButton)
fun injectElement(comparator: Comparator)
fun injectElement(comparatorExists: ComparatorExists)
fun injectElement(comparatorConnect: ComparatorConnect)
fun injectElement(inputDateTime: InputDateTime)
fun injectElement(inputDelta: InputDelta)
fun injectElement(inputDropdownMenu: InputDropdownMenu)
fun injectElement(inputDouble: InputDouble)
fun injectElement(inputDuration: InputDuration)
fun injectElement(inputInsulin: InputInsulin)

View file

@ -171,6 +171,7 @@ open class AppModule {
@ContributesAndroidInjector
fun triggerPumpLastConnectionInjector(): TriggerPumpLastConnection
@ContributesAndroidInjector fun triggerBTDeviceInjector(): TriggerBTDevice
@ContributesAndroidInjector fun triggerRecurringTimeInjector(): TriggerRecurringTime
@ContributesAndroidInjector fun triggerTempTargetInjector(): TriggerTempTarget
@ContributesAndroidInjector fun triggerTime(): TriggerTime
@ -197,10 +198,12 @@ open class AppModule {
@ContributesAndroidInjector fun inputBgInjector(): InputBg
@ContributesAndroidInjector fun inputButtonInjector(): InputButton
@ContributesAndroidInjector fun comparatorInjector(): Comparator
@ContributesAndroidInjector fun comparatorConnectInjector(): ComparatorConnect
@ContributesAndroidInjector fun comparatorExistsInjector(): ComparatorExists
@ContributesAndroidInjector fun inputDateTimeInjector(): InputDateTime
@ContributesAndroidInjector fun inputDeltaInjector(): InputDelta
@ContributesAndroidInjector fun inputDoubleInjector(): InputDouble
@ContributesAndroidInjector fun inputDropdownMenuInjector(): InputDropdownMenu
@ContributesAndroidInjector fun inputDurationInjector(): InputDuration
@ContributesAndroidInjector fun inputInsulinInjector(): InputInsulin
@ContributesAndroidInjector fun inputLocationModeInjector(): InputLocationMode

View file

@ -21,6 +21,7 @@ import info.nightscout.androidaps.plugins.constraints.signatureVerifier.Signatur
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin
import info.nightscout.androidaps.plugins.general.dataBroadcaster.DataBroadcastPlugin
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
@ -213,6 +214,12 @@ abstract class PluginsModule {
@IntKey(250)
abstract fun bindLocalProfilePlugin(plugin: LocalProfilePlugin): PluginBase
@Binds
@AllConfigs
@IntoMap
@IntKey(255)
abstract fun bindAutomationPlugin(plugin: AutomationPlugin): PluginBase
@Binds
@AllConfigs
@IntoMap

View file

@ -3,16 +3,13 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver
import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.receivers.DataReceiver
import info.nightscout.androidaps.receivers.KeepAliveReceiver
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
import info.nightscout.androidaps.receivers.*
@Module
@Suppress("unused")
abstract class ReceiversModule {
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.events
class EventBTChange constructor(val state: Change, val deviceName: String) : Event() {
enum class Change {
CONNECT,
DISCONNECT
}
}

View file

@ -6,6 +6,7 @@ import android.os.Build
import android.os.Handler
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventBTChange
import info.nightscout.androidaps.events.EventChargingState
import info.nightscout.androidaps.events.EventLocationChange
import info.nightscout.androidaps.events.EventNetworkChange
@ -38,6 +39,7 @@ import org.json.JSONObject
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.collections.ArrayList
@Singleton
class AutomationPlugin @Inject constructor(
@ -65,6 +67,7 @@ class AutomationPlugin @Inject constructor(
val automationEvents = ArrayList<AutomationEvent>()
var executionLog: MutableList<String> = ArrayList()
var btConnects : MutableList<EventBTChange> = ArrayList()
private val loopHandler = Handler()
private lateinit var refreshLoop: Runnable
@ -123,6 +126,14 @@ class AutomationPlugin @Inject constructor(
.toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(Schedulers.io())
.subscribe({ processActions() }, { fabricPrivacy.logException(it) })
disposable += rxBus
.toObservable(EventBTChange::class.java)
.observeOn(Schedulers.io())
.subscribe({
aapsLogger.debug(LTag.AUTOMATION, "Grabbed new BT event: $it")
btConnects.add(it)
processActions()
}, { fabricPrivacy.logException(it) })
}
override fun onStop() {
@ -197,6 +208,12 @@ class AutomationPlugin @Inject constructor(
event.lastRun = DateUtil.now()
}
}
// we cannot detect connected BT devices
// so let's collect all connection/disconnections between 2 runs of processActions()
// TriggerBTDevice can pick up and process these events
// after processing clear events to prevent repeated actions
btConnects.clear()
storeToSP() // save last run time
}
@ -231,8 +248,8 @@ class AutomationPlugin @Inject constructor(
TriggerLocation(injector),
TriggerAutosensValue(injector),
TriggerBolusAgo(injector),
TriggerPumpLastConnection(injector)
TriggerPumpLastConnection(injector),
TriggerBTDevice(injector)
)
}
}

View file

@ -0,0 +1,60 @@
package info.nightscout.androidaps.plugins.general.automation.elements
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.LinearLayout
import android.widget.Spinner
import androidx.annotation.StringRes
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.*
import javax.inject.Inject
class ComparatorConnect(injector: HasAndroidInjector) : Element(injector) {
@Inject lateinit var resourceHelper: ResourceHelper
enum class Compare {
ON_CONNECT, ON_DISCONNECT;
@get:StringRes val stringRes: Int
get() = when (this) {
ON_CONNECT -> R.string.onconnect
ON_DISCONNECT -> R.string.ondisconnect
}
companion object {
fun labels(resourceHelper: ResourceHelper): List<String> {
val list: MutableList<String> = ArrayList()
for (c in values()) list.add(resourceHelper.gs(c.stringRes))
return list
}
}
}
constructor(injector: HasAndroidInjector, value: Compare) : this(injector) {
this.value = value
}
var value = Compare.ON_CONNECT
override fun addToLayout(root: LinearLayout) {
val spinner = Spinner(root.context)
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = spinnerArrayAdapter
val spinnerParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
spinner.layoutParams = spinnerParams
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
value = Compare.values()[position]
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
spinner.setSelection(value.ordinal)
root.addView(spinner)
}
}

View file

@ -0,0 +1,68 @@
package info.nightscout.androidaps.plugins.general.automation.elements
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.LinearLayout
import android.widget.Spinner
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.*
import javax.inject.Inject
class InputDropdownMenu(injector: HasAndroidInjector) : Element(injector) {
@Inject lateinit var resourceHelper: ResourceHelper
private var itemList: ArrayList<CharSequence> = ArrayList()
var value: String = ""
constructor(injector: HasAndroidInjector, name: String) : this(injector) {
value = name
}
constructor(injector: HasAndroidInjector, another: InputDropdownMenu) : this(injector) {
value = another.value
}
override fun addToLayout(root: LinearLayout) {
val spinner = Spinner(root.context)
spinner.adapter = ArrayAdapter(root.context,
R.layout.spinner_centered, itemList).also {
it.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
}
spinner.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).also { it.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4)) }
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
setValue(itemList[position].toString())
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
spinner.setSelection(0)
root.addView(LinearLayout(root.context).also {
it.orientation = LinearLayout.VERTICAL
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
it.addView(spinner)
})
}
fun setValue(name: String): InputDropdownMenu {
value = name
return this
}
fun setList(values: ArrayList<CharSequence>) {
itemList = ArrayList(values)
}
// For testing only
fun add(item: String) {
itemList.add(item)
}
}

View file

@ -0,0 +1,94 @@
package info.nightscout.androidaps.plugins.general.automation.triggers
import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.widget.LinearLayout
import com.google.common.base.Optional
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventBTChange
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorConnect
import info.nightscout.androidaps.plugins.general.automation.elements.InputDropdownMenu
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel
import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
class TriggerBTDevice(injector: HasAndroidInjector) : Trigger(injector) {
@Inject lateinit var context: Context
@Inject lateinit var automationPlugin: AutomationPlugin
var btDevice = InputDropdownMenu(injector, "")
var comparator: ComparatorConnect = ComparatorConnect(injector)
private constructor(injector: HasAndroidInjector, triggerBTDevice: TriggerBTDevice) : this(injector) {
comparator = ComparatorConnect(injector, triggerBTDevice.comparator.value)
btDevice.value = triggerBTDevice.btDevice.value
}
@Synchronized
override fun shouldRun(): Boolean {
if (eventExists()) {
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
return true
}
return false
}
@Synchronized override fun toJSON(): String {
val data = JSONObject()
.put("comparator", comparator.value.toString())
.put("name", btDevice.value)
return JSONObject()
.put("type", this::class.java.name)
.put("data", data)
.toString()
}
override fun fromJSON(data: String): Trigger {
val d = JSONObject(data)
btDevice.value = JsonHelper.safeGetString(d, "name")!!
comparator.value = ComparatorConnect.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")!!)
return this
}
override fun friendlyName(): Int = R.string.btdevice
override fun friendlyDescription(): String =
resourceHelper.gs(R.string.btdevicecompared, btDevice.value, resourceHelper.gs(comparator.value.stringRes))
override fun icon(): Optional<Int?> = Optional.of(R.drawable.ic_bluetooth_white_48dp)
override fun duplicate(): Trigger = TriggerBTDevice(injector, this)
override fun generateDialog(root: LinearLayout) {
val pairedDevices = devicesPaired()
btDevice.setList(pairedDevices)
LayoutBuilder()
.add(StaticLabel(injector, R.string.btdevice, this))
.add(btDevice)
.add(comparator)
.build(root)
}
// Get the list of paired BT devices to use in dropdown menu
private fun devicesPaired(): ArrayList<CharSequence> {
val s = ArrayList<CharSequence>()
BluetoothAdapter.getDefaultAdapter()?.bondedDevices?.forEach { s.add(it.name) }
return s
}
private fun eventExists(): Boolean {
automationPlugin.btConnects.forEach {
if (btDevice.value == it.deviceName) {
if (comparator.value == ComparatorConnect.Compare.ON_CONNECT && it.state == EventBTChange.Change.CONNECT) return true
if (comparator.value == ComparatorConnect.Compare.ON_DISCONNECT && it.state == EventBTChange.Change.DISCONNECT) return true
}
}
return false
}
}

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.pump.danaR.services;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
@ -20,6 +19,9 @@ import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventBTChange;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
@ -41,9 +43,12 @@ import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgPCCommStop;
import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.ToastUtils;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
/**
* Created by mike on 28.01.2018.
@ -57,6 +62,9 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
@Inject Context context;
@Inject ResourceHelper resourceHelper;
@Inject DanaRPump danaRPump;
@Inject FabricPrivacy fabricPrivacy;
private CompositeDisposable disposable = new CompositeDisposable();
protected String mDevName;
@ -101,22 +109,41 @@ public abstract class AbstractDanaRExecutionService extends DaggerService {
public abstract PumpEnactResult setUserOptions();
protected BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
aapsLogger.debug(LTag.PUMP, "Device was disconnected " + device.getName());//Device was disconnected
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
if (mSerialIOThread != null) {
mSerialIOThread.disconnect("BT disconnection broadcast");
@Override public void onCreate() {
super.onCreate();
disposable.add(rxBus
.toObservable(EventBTChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
if (event.getState() == EventBTChange.Change.DISCONNECT) {
aapsLogger.debug(LTag.PUMP, "Device was disconnected " + event.getDeviceName());//Device was disconnected
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(event.getDeviceName())) {
if (mSerialIOThread != null) {
mSerialIOThread.disconnect("BT disconnection broadcast");
}
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
}
}
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
}
}
}
};
}, fabricPrivacy::logException)
);
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
aapsLogger.debug(LTag.PUMP, "EventAppExit received");
if (mSerialIOThread != null)
mSerialIOThread.disconnect("Application exit");
stopSelf();
}, fabricPrivacy::logException)
);
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {

View file

@ -92,42 +92,13 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
@Inject ProfileFunction profileFunction;
@Inject SP sp;
private CompositeDisposable disposable = new CompositeDisposable();
public DanaRExecutionService() {
}
@Override
public void onCreate() {
super.onCreate();
mBinder = new LocalBinder();
context.registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
disposable.add(rxBus
.toObservable(EventPreferenceChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
if (mSerialIOThread != null)
mSerialIOThread.disconnect("EventPreferenceChange");
}, exception -> FabricPrivacy.getInstance().logException(exception))
);
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
aapsLogger.debug(LTag.PUMP, "EventAppExit received");
if (mSerialIOThread != null)
mSerialIOThread.disconnect("Application exit");
context.unregisterReceiver(receiver);
stopSelf();
}, exception -> FabricPrivacy.getInstance().logException(exception))
);
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
public class LocalBinder extends Binder {

View file

@ -83,8 +83,6 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
@Inject ActivePluginProvider activePlugin;
@Inject ProfileFunction profileFunction;
private CompositeDisposable disposable = new CompositeDisposable();
public DanaRKoreanExecutionService() {
}
@ -92,33 +90,6 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
public void onCreate() {
super.onCreate();
mBinder = new LocalBinder();
context.registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
disposable.add(rxBus
.toObservable(EventPreferenceChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
if (mSerialIOThread != null)
mSerialIOThread.disconnect("EventPreferenceChange");
}, exception -> FabricPrivacy.getInstance().logException(exception))
);
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
aapsLogger.debug(LTag.PUMP, "EventAppExit received");
if (mSerialIOThread != null)
mSerialIOThread.disconnect("Application exit");
context.unregisterReceiver(receiver);
stopSelf();
}, exception -> FabricPrivacy.getInstance().logException(exception))
);
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
public class LocalBinder extends Binder {

View file

@ -108,8 +108,6 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
@Inject ProfileFunction profileFunction;
@Inject SP sp;
private CompositeDisposable disposable = new CompositeDisposable();
private long lastHistoryFetched = 0;
public DanaRv2ExecutionService() {
@ -125,33 +123,6 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
public void onCreate() {
super.onCreate();
mBinder = new LocalBinder();
context.registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
disposable.add(rxBus
.toObservable(EventPreferenceChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
if (mSerialIOThread != null)
mSerialIOThread.disconnect("EventPreferenceChange");
}, exception -> FabricPrivacy.getInstance().logException(exception))
);
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
aapsLogger.debug(LTag.PUMP, "EventAppExit received");
if (mSerialIOThread != null)
mSerialIOThread.disconnect("Application exit");
context.getApplicationContext().unregisterReceiver(receiver);
stopSelf();
}, exception -> FabricPrivacy.getInstance().logException(exception))
);
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
public void connect() {

View file

@ -0,0 +1,25 @@
package info.nightscout.androidaps.receivers
import android.bluetooth.BluetoothDevice
import android.content.Context
import android.content.Intent
import dagger.android.DaggerBroadcastReceiver
import info.nightscout.androidaps.events.EventBTChange
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import javax.inject.Inject
class BTReceiver : DaggerBroadcastReceiver() {
@Inject lateinit var rxBus: RxBusWrapper
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
val device : BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
when (intent.action) {
BluetoothDevice.ACTION_ACL_CONNECTED ->
rxBus.send(EventBTChange(EventBTChange.Change.CONNECT, device.name))
BluetoothDevice.ACTION_ACL_DISCONNECTED ->
rxBus.send(EventBTChange(EventBTChange.Change.DISCONNECT, device.name))
}
}
}

View file

@ -1382,6 +1382,8 @@
<string name="exists">exists</string>
<string name="notexists">not exists</string>
<string name="temptargetcompared">Temp target %1$s</string>
<string name="btdevicecompared">Bluetooth connection to device %1$s %2$s</string>
<string name="btdevice">Connection to Bluetooth device </string>
<string name="wifissidcompared">WiFi SSID %1$s %2$s</string>
<string name="autosenscompared">Autosens %1$s %2$s %%</string>
<string name="autosenslabel">Autosens %</string>
@ -1736,4 +1738,6 @@
<string name="smscommunicator_otp_install_info">On each follower phone install Authenticator app that support RFC 6238 TOTP tokens. Popular free apps are:\n • Authy\n • Google Authenticator\n • LastPass Authenticator\n • FreeOTP Authenticator</string>
<string name="smscommunicator_otp_provisioning_warning">DO NOT SHARE this code online!\nUse it only to setup Authenticator App on follower phones.</string>
<string name="smscommunicator_otp_reset_warning">By reseting authenticator you make all already provisioned authenticators invalid. You will need to set up them again!</string>
<string name="onconnect">On connect</string>
<string name="ondisconnect">On disconnect</string>
</resources>

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.plugins.general.automation.elements
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTestBase
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
class ComparatorConnectTest : TriggerTestBase() {
@Test fun labelsTest() {
Assert.assertEquals(2, ComparatorConnect.Compare.labels(resourceHelper).size)
}
@Test fun setValueTest() {
val c = ComparatorConnect(injector)
c.value = ComparatorConnect.Compare.ON_DISCONNECT
Assert.assertEquals(ComparatorConnect.Compare.ON_DISCONNECT, c.value)
}
}

View file

@ -1,12 +1,14 @@
package info.nightscout.androidaps.plugins.general.automation.elements
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTestBase
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.`when`
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)

View file

@ -0,0 +1,50 @@
package info.nightscout.androidaps.plugins.general.automation.triggers
import com.google.common.base.Optional
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorConnect
import org.json.JSONObject
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
class TriggerBTDeviceTest : TriggerTestBase() {
var now = 1514766900000L
var someName = "Headset"
var btJson = "{\"data\":{\"comparator\":\"ON_CONNECT\",\"name\":\"Headset\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBTDevice\"}"
@Test fun shouldRun() {
val t: TriggerBTDevice = TriggerBTDevice(injector)
}
@Test fun toJSON() {
val t: TriggerBTDevice = TriggerBTDevice(injector)
t.btDevice.value = someName
Assert.assertEquals(btJson, t.toJSON())
}
@Test
fun fromJSON() {
val t2 = TriggerDummy(injector).instantiate(JSONObject(btJson)) as TriggerBTDevice
Assert.assertEquals(ComparatorConnect.Compare.ON_CONNECT, t2.comparator.value)
Assert.assertEquals("Headset", t2.btDevice.value)
}
@Test
fun icon() {
Assert.assertEquals(Optional.of(R.drawable.ic_bluetooth_white_48dp), TriggerBTDevice(injector).icon())
}
@Test fun duplicate() {
val t: TriggerBTDevice = TriggerBTDevice(injector).also {
it.comparator.value = ComparatorConnect.Compare.ON_DISCONNECT
it.btDevice.value = someName
}
val t1 = t.duplicate() as TriggerBTDevice
Assert.assertEquals("Headset", t1.btDevice.value)
Assert.assertEquals(ComparatorConnect.Compare.ON_DISCONNECT, t.comparator.value)
}
}

View file

@ -3,27 +3,23 @@ package info.nightscout.androidaps.plugins.general.automation.triggers
import android.content.Context
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.TestBaseWithProfile
import info.nightscout.androidaps.events.EventNetworkChange
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.receivers.ReceiverStatusStore
import info.nightscout.androidaps.services.LastLocationDataContainer
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.junit.Before
import org.mockito.Mock
import org.powermock.core.classloader.annotations.PrepareForTest
@PrepareForTest(LastLocationDataContainer::class)
@PrepareForTest(LastLocationDataContainer::class, AutomationPlugin::class)
open class TriggerTestBase : TestBaseWithProfile() {
@Mock lateinit var profileFunction: ProfileFunction
@ -32,6 +28,7 @@ open class TriggerTestBase : TestBaseWithProfile() {
@Mock lateinit var activePlugin: ActivePluginProvider
@Mock lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
@Mock lateinit var context: Context
@Mock lateinit var automationPlugin: AutomationPlugin
lateinit var receiverStatusStore: ReceiverStatusStore
@ -56,6 +53,10 @@ open class TriggerTestBase : TestBaseWithProfile() {
if (it is TriggerBg) {
it.profileFunction = profileFunction
}
if (it is TriggerBTDevice) {
it.context = context
it.automationPlugin = automationPlugin
}
if (it is TriggerWifiSsid) {
it.receiverStatusStore = receiverStatusStore
}