Merge pull request #1650 from MilosKozak/PoweRGbg-DstHelperPlugin

Dst helper plugin
This commit is contained in:
Milos Kozak 2019-03-02 15:34:08 +01:00 committed by GitHub
commit 0b1284d636
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 202 additions and 4 deletions

View file

@ -34,6 +34,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin;
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment;
@ -195,6 +196,8 @@ public class MainApp extends Application {
pluginsList.add(ConfigBuilderPlugin.getPlugin());
pluginsList.add(DstHelperPlugin.getPlugin());
ConfigBuilderPlugin.getPlugin().initialize();
}

View file

@ -0,0 +1,125 @@
package info.nightscout.androidaps.plugins.constraints.dstHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.utils.T;
/**
* Created by Rumen on 31.10.2018.
*/
public class DstHelperPlugin extends PluginBase implements ConstraintsInterface {
private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS);
private int minutesToChange = 0;
static DstHelperPlugin plugin = null;
public static DstHelperPlugin getPlugin() {
if (plugin == null)
plugin = new DstHelperPlugin();
return plugin;
}
public DstHelperPlugin() {
super(new PluginDescription()
.mainType(PluginType.CONSTRAINTS)
.neverVisible(true)
.alwaysEnabled(true)
.showInList(false)
.pluginName(R.string.dst_plugin_name)
);
}
public int dstTest(Calendar c) throws Exception {
// c = Calendar.getInstance(TimeZone.getDefault());
// c = Calendar.getInstance(TimeZone.getTimeZone("Australia/Lord_Howe"));
// c.setTimeInMillis(DateUtil.fromISODateString("2018-10-07T01:00:00Z").getTime());
long zoneOffset = c.get(Calendar.ZONE_OFFSET);
long d1 = c.getTimeInMillis() - zoneOffset;
c.setTimeInMillis(d1);
int offset1 = c.get(Calendar.DST_OFFSET);
c.add(Calendar.DATE, 1);
long d2 = c.getTimeInMillis();
int diffInHours = (int) ((d1 - d2) / -T.hours(1).msecs());
long offsetDetectedTime = 0;
// comparing millis because change can be < 1 hour
// log.debug("Starting from: "+startTimeString + " to "+endTimeString);
// log.debug("start "+offset1+" end "+c.get(Calendar.DST_OFFSET));
if (offset1 != c.get(Calendar.DST_OFFSET)) {
//we have a time change in next 24 hours, but when exactly
// log.debug("Daylight saving time detected between " + startTimeString + " and " + endTimeString);
// log.debug("Diff in hours is: "+diffInHours);
c.setTimeInMillis(d1 - zoneOffset);
offset1 = c.get(Calendar.DST_OFFSET);
for (int i = 0; i <= diffInHours * 4; i++) {
if (offset1 != c.get(Calendar.DST_OFFSET)) {
log.debug("Detected offset in " + ((i / 4) - zoneOffset / T.hours(1).msecs()) + " hours value is " + (offset1 - c.get(Calendar.DST_OFFSET)) / T.mins(1).msecs() + " minutes");
offsetDetectedTime = c.getTimeInMillis() - d1;
break;
}
c.add(Calendar.MINUTE, 15);
}
}
int minutesLeft = (int) ((offsetDetectedTime / T.mins(1).msecs()));
/*log.debug("zoneoffset(minutes):"+zoneOffset/T.mins(1).msecs());
log.debug("Start offset: "+offset1/T.mins(1).msecs());
log.debug("End offset :" + c.get(Calendar.DST_OFFSET)/T.mins(1).msecs());
log.debug("Now is:"+startTimeString);
log.debug("Detected in(min): "+(offsetDetectedTime/T.mins(1).msecs()));
log.debug("Returning value of: " + minutesLeft); */
minutesToChange = minutesLeft;
return minutesLeft;
}
//Return false if time to DST change is less than 91 and positive
@Override
public Constraint<Boolean> isLoopInvocationAllowed(Constraint<Boolean> value) {
try {
this.dstTest(Calendar.getInstance());
} catch (Exception e) {
e.printStackTrace();
}
if (this.minutesToChange <= 90 && minutesToChange > 0 && value.value()) {
try {
LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (loopPlugin.suspendedTo() == 0L) {
// loopPlugin.suspendTo(System.currentTimeMillis() + minutesToChange * T.mins(1).msecs());
warnUser(Notification.DST_LOOP_DISABLED, MainApp.gs(R.string.dst_loop_disabled_warning));
} else
log.debug("Loop already suspended");
} catch (Exception e) {
e.printStackTrace();
}
value.set(false, "DST in 90 minutes or less", this);
} else if (minutesToChange <= 24 * T.hours(1).mins() && minutesToChange > 0) {
warnUser(Notification.DST_IN_24H, MainApp.gs(R.string.dst_in_24h_warning));
}
return value;
}
// display warning
void warnUser(int id, String warningText) {
Notification notification = new Notification(id, warningText, Notification.LOW);
MainApp.bus().post(new EventNewNotification(notification));
}
}

View file

@ -71,6 +71,8 @@ public class Notification {
public static final int PERMISSION_PHONESTATE = 46;
public static final int INSIGHT_DATE_TIME_UPDATED = 47;
public static final int INSIGHT_TIMEOUT_DURING_HANDSHAKE = 48;
public static final int DST_LOOP_DISABLED = 49;
public static final int DST_IN_24H = 50;
public int id;

View file

@ -1309,6 +1309,9 @@
<string name="tomato_short">Tomato</string>
<string name="key_smbmaxminutes" translatable="false">smbmaxminutes</string>
<string name="dst_plugin_name" translatable="false">Dayligh Saving time</string>
<string name="dst_in_24h_warning">Dayligh Saving time change in 24h or less</string>
<string name="dst_loop_disabled_warning">Dayligh Saving time change in less than 3 hours - Closed loop diabled</string>
<plurals name="objective_days">
<item quantity="one">%1$d day</item>

View file

@ -71,7 +71,7 @@ public class MainAppTest {
if (Config.NSCLIENT)
expected = 1; // VirtualPump only
else
expected = 7;
expected = 8;
Assert.assertEquals(expected, mainApp.getSpecificPluginsList(PluginType.PUMP).size());
}
@ -82,7 +82,7 @@ public class MainAppTest {
if (Config.NSCLIENT)
expected = 1; // VirtualPump only
else
expected = 7;
expected = 8;
Assert.assertEquals(expected, mainApp.getSpecificPluginsVisibleInList(PluginType.PUMP).size());
}
@ -93,7 +93,7 @@ public class MainAppTest {
if (Config.NSCLIENT)
expected = 1; // VirtualPump only
else
expected = 7;
expected = 8;
Assert.assertEquals(expected, mainApp.getSpecificPluginsListByInterface(PumpInterface.class).size());
}
@ -104,7 +104,7 @@ public class MainAppTest {
if (Config.NSCLIENT)
expected = 1; // VirtualPump only
else
expected = 7;
expected = 8;
Assert.assertEquals(expected, mainApp.getSpecificPluginsVisibleInListByInterface(PumpInterface.class, PluginType.PUMP).size());
}

View file

@ -0,0 +1,65 @@
package info.nightscout.androidaps.plugins.constraints.dstHelper;
import android.content.Context;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.Calendar;
import java.util.TimeZone;
import info.AAPSMocker;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, SP.class, Context.class})
public class DstHelperPluginTest {
DstHelperPlugin plugin = new DstHelperPlugin();
@Test
public void runTest() throws Exception {
AAPSMocker.mockMainApp();
AAPSMocker.mockApplicationContext();
// test different time zones
//Starting with Europe/Sofia
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Europe/Sofia"));
c.setTimeInMillis(DateUtil.fromISODateString("2018-10-28T02:00:00Z").getTime());
int minutesLeftToChange = plugin.dstTest(c);
Assert.assertEquals(60, minutesLeftToChange);
c.setTimeInMillis(DateUtil.fromISODateString("2018-03-25T02:00:00Z").getTime());
minutesLeftToChange = plugin.dstTest(c);
Assert.assertEquals(60, minutesLeftToChange);
// try something with half hour somewhere in Australia
c = Calendar.getInstance(TimeZone.getTimeZone("Australia/Lord_Howe"));
c.setTimeInMillis(DateUtil.fromISODateString("2018-04-01T00:00:00Z").getTime());
minutesLeftToChange = plugin.dstTest(c);
// try something with half hour somewhere in Australia
c = Calendar.getInstance(TimeZone.getTimeZone("Australia/Lord_Howe"));
c.setTimeInMillis(DateUtil.fromISODateString("2018-04-01T00:00:00Z").getTime());
minutesLeftToChange = plugin.dstTest(c);
Assert.assertEquals(90, minutesLeftToChange);
c = Calendar.getInstance(TimeZone.getTimeZone("Australia/Lord_Howe"));
// and back
c.setTimeInMillis(DateUtil.fromISODateString("2018-10-07T00:00:00Z").getTime());
minutesLeftToChange = plugin.dstTest(c);
Assert.assertEquals(120, minutesLeftToChange);
c.setTimeInMillis(DateUtil.fromISODateString("2018-10-08T00:00:00Z").getTime());
minutesLeftToChange = plugin.dstTest(c);
Assert.assertEquals(0, minutesLeftToChange);
// DST event was 30 mins
c.setTimeInMillis(DateUtil.fromISODateString("2018-04-01T02:00:00Z").getTime());
minutesLeftToChange = plugin.dstTest(c);
// Assert.assertEquals(630, plugin.zoneOffsetInMinutes(c));
Assert.assertEquals(0, minutesLeftToChange);
}
}