Merge pull request #27 from MilosKozak/master

update to milos master
This commit is contained in:
AdrianLxM 2016-12-01 09:24:02 +01:00 committed by GitHub
commit 2caa58f07e
72 changed files with 5026 additions and 69 deletions

View file

@ -10,6 +10,7 @@
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/wear" />
</set> </set>
</option> </option>
<option name="resolveModulePerSourceSet" value="false" /> <option name="resolveModulePerSourceSet" value="false" />

View file

@ -4,6 +4,7 @@
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/AndroidAPS.iml" filepath="$PROJECT_DIR$/AndroidAPS.iml" /> <module fileurl="file://$PROJECT_DIR$/AndroidAPS.iml" filepath="$PROJECT_DIR$/AndroidAPS.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/wear/wear.iml" filepath="$PROJECT_DIR$/wear/wear.iml" />
</modules> </modules>
</component> </component>
</project> </project>

View file

@ -57,46 +57,62 @@ android {
} }
} }
productFlavors { productFlavors {
flavorDimensions "standard", "wear"
full { full {
dimension "standard"
buildConfigField "boolean", "APS", "true" buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "CLOSEDLOOP", "true" buildConfigField "boolean", "CLOSEDLOOP", "true"
buildConfigField "int", "MAXBOLUS", "17" buildConfigField "int", "MAXBOLUS", "17"
} }
fullteenage { fullteenage {
dimension "standard"
buildConfigField "boolean", "APS", "true" buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "CLOSEDLOOP", "true" buildConfigField "boolean", "CLOSEDLOOP", "true"
buildConfigField "int", "MAXBOLUS", "10" buildConfigField "int", "MAXBOLUS", "10"
} }
fullchild { fullchild {
dimension "standard"
buildConfigField "boolean", "APS", "true" buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "CLOSEDLOOP", "true" buildConfigField "boolean", "CLOSEDLOOP", "true"
buildConfigField "int", "MAXBOLUS", "5" buildConfigField "int", "MAXBOLUS", "5"
} }
danarcontrol { danarcontrol {
dimension "standard"
buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "int", "MAXBOLUS", "17" buildConfigField "int", "MAXBOLUS", "17"
} }
careportal { careportal {
dimension "standard"
buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false" buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "int", "MAXBOLUS", "17" buildConfigField "int", "MAXBOLUS", "17"
} }
openloop { openloop {
dimension "standard"
buildConfigField "boolean", "APS", "true" buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "int", "MAXBOLUS", "17" buildConfigField "int", "MAXBOLUS", "17"
} }
wear {
dimension "wear"
buildConfigField "boolean", "WEAR", "true"
}
nowear {
dimension "wear"
buildConfigField "boolean", "WEAR", "false"
}
} }
} }
dependencies { dependencies {
wearWearApp project(path: ':wear', configuration: 'fullRelease')
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
compile('com.crashlytics.sdk.android:crashlytics:2.5.7@aar') { compile('com.crashlytics.sdk.android:crashlytics:2.5.7@aar') {
transitive = true; transitive = true;
@ -116,4 +132,5 @@ dependencies {
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar' compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar'
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1' compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.google.android.gms:play-services-wearable:7.5.0'
} }

View file

@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.SEND_MMS" /> <uses-permission android:name="android.permission.SEND_MMS" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<!-- To receive data from xdrip. --> <!-- To receive data from xdrip. -->
<uses-permission android:name="com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE" /> <uses-permission android:name="com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE" />
@ -80,6 +81,10 @@
android:enabled="true" android:enabled="true"
android:exported="false" /> android:exported="false" />
<service android:name=".plugins.Wear.wearintegration.WatchUpdaterService" android:exported="true" >
<intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter>
</service>
<meta-data <meta-data
android:name="io.fabric.ApiKey" android:name="io.fabric.ApiKey"
android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" /> android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" />

View file

@ -9,6 +9,7 @@ public class Config {
// PLUGINS // PLUGINS
public static final boolean OPENAPSMAENABLED = APS; public static final boolean OPENAPSMAENABLED = APS;
public static final boolean LOOPENABLED = APS; public static final boolean LOOPENABLED = APS;
public static final boolean WEAR = BuildConfig.WEAR;
public static final boolean CAREPORTALENABLED = true; public static final boolean CAREPORTALENABLED = true;
public static final boolean SMSCOMMUNICATORENABLED = true; public static final boolean SMSCOMMUNICATORENABLED = true;

View file

@ -36,6 +36,7 @@ import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment;
import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment; import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
import info.nightscout.androidaps.plugins.Wear.WearFragment;
import io.fabric.sdk.android.Fabric; import io.fabric.sdk.android.Fabric;
@ -85,6 +86,9 @@ public class MainApp extends Application {
pluginsList.add(SourceNSClientFragment.getPlugin()); pluginsList.add(SourceNSClientFragment.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) if (Config.SMSCOMMUNICATORENABLED)
pluginsList.add(SmsCommunicatorFragment.getPlugin()); pluginsList.add(SmsCommunicatorFragment.getPlugin());
if (Config.WEAR) pluginsList.add(WearFragment.getPlugin(this));
pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin()); pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin());
MainApp.getConfigBuilder().initialize(); MainApp.getConfigBuilder().initialize();

View file

@ -204,4 +204,25 @@ public class TempBasal {
} }
} }
public String toStringShort() {
String extended = isExtended ? "E" : "";
if (isAbsolute) {
return extended + DecimalFormatter.to2Decimal(absolute) + "U/h ";
} else { // percent
return percent + "% ";
}
}
public String toStringMedium() {
String extended = isExtended ? "E" : "";
if (isAbsolute) {
return extended + DecimalFormatter.to2Decimal(absolute) + "U/h ("
+ getRealDuration() + "/" + duration + ") ";
} else { // percent
return percent + "% (" + getRealDuration() + "/" + duration + ") ";
}
}
} }

View file

@ -38,7 +38,7 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.DanaR.comm.MsgOcclusion; import info.nightscout.androidaps.plugins.DanaR.comm.MsgError;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.DeviceStatus; import info.nightscout.androidaps.plugins.Loop.DeviceStatus;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
@ -922,7 +922,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
} }
public void uploadDanaROcclusion() { public void uploadError(String error) {
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd"); bundle.putString("action", "dbAdd");
@ -931,7 +931,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
try { try {
data.put("eventType", "Announcement"); data.put("eventType", "Announcement");
data.put("created_at", DateUtil.toISOString(new Date())); data.put("created_at", DateUtil.toISOString(new Date()));
data.put("notes", MainApp.sResources.getString(R.string.overview_bolusiprogress_occlusion)); data.put("notes", error);
data.put("isAnnouncement", true); data.put("isAnnouncement", true);
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
@ -941,7 +941,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
intent.putExtras(bundle); intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString(), MsgOcclusion.class); DbLogger.dbAdd(intent, data.toString(), MsgError.class);
} }
public void uploadAppStart() { public void uploadAppStart() {

View file

@ -33,7 +33,7 @@ public class MessageHashTable {
put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP
put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP
put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S
put(new MsgOcclusion()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS
put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT
put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT
put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS

View file

@ -0,0 +1,51 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
public class MsgError extends MessageBase {
private static Logger log = LoggerFactory.getLogger(MsgError.class);
public MsgError() {
SetCommand(0x0601);
}
@Override
public void handleMessage(byte[] bytes) {
int errorCode = intFromBuff(bytes, 0, 1);
String errorString = "";
switch (errorCode) {
case 1:
case 2:
case 3: // Pump error
errorString = MainApp.sResources.getString(R.string.pumperror) + " " + errorCode;
break;
case 4: // Shutdown
errorString = MainApp.sResources.getString(R.string.pumpshutdown);
break;
case 5: // Occlusion
errorString = MainApp.sResources.getString(R.string.occlusion);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
MsgBolusStop.stopped = true;
bolusingEvent.status = errorString;
MainApp.bus().post(bolusingEvent);
break;
case 7: // Low Battery
errorString = MainApp.sResources.getString(R.string.lowbattery);
break;
case 8: // Battery 0%
errorString = MainApp.sResources.getString(R.string.batterydischarged);
break;
}
if (Config.logDanaMessageDetail)
log.debug("Error detected: " + errorString);
MainApp.getConfigBuilder().uploadError(errorString);
}
}

View file

@ -1,40 +0,0 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.client.data.DbLogger;
import info.nightscout.utils.DateUtil;
public class MsgOcclusion extends MessageBase {
private static Logger log = LoggerFactory.getLogger(MsgOcclusion.class);
public MsgOcclusion() {
SetCommand(0x0601);
}
@Override
public void handleMessage(byte[] bytes) {
if (Config.logDanaMessageDetail)
log.debug("Oclusion detected");
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
MsgBolusStop.stopped = true;
bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusiprogress_occlusion);
MainApp.bus().post(bolusingEvent);
MainApp.getConfigBuilder().uploadDanaROcclusion();
}
}

View file

@ -13,7 +13,6 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.StringTokenizer;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
@ -26,7 +25,6 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.DanaR.comm.MsgOcclusion;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSMAUpdateGui;

View file

@ -3,12 +3,14 @@ package info.nightscout.androidaps.plugins.Overview;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.DashPathEffect; import android.graphics.DashPathEffect;
import android.graphics.Paint; import android.graphics.Paint;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -72,6 +74,7 @@ import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
@ -79,6 +82,7 @@ public class OverviewFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(OverviewFragment.class); private static Logger log = LoggerFactory.getLogger(OverviewFragment.class);
private static OverviewPlugin overviewPlugin = new OverviewPlugin(); private static OverviewPlugin overviewPlugin = new OverviewPlugin();
private SharedPreferences prefs;
public static OverviewPlugin getPlugin() { public static OverviewPlugin getPlugin() {
return overviewPlugin; return overviewPlugin;
@ -121,6 +125,8 @@ public class OverviewFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
View view = inflater.inflate(R.layout.overview_fragment, container, false); View view = inflater.inflate(R.layout.overview_fragment, container, false);
bgView = (TextView) view.findViewById(R.id.overview_bg); bgView = (TextView) view.findViewById(R.id.overview_bg);
timeAgoView = (TextView) view.findViewById(R.id.overview_timeago); timeAgoView = (TextView) view.findViewById(R.id.overview_timeago);
@ -578,8 +584,16 @@ public class OverviewFragment extends Fragment {
long toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding long toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
long fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; long fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
Double lowLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units); Double lowLine = SafeParse.stringToDouble(prefs.getString("low_mark", "0"));
Double highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0"));
if (lowLine < 1){
lowLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units);
}
if(highLine < 1){
highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
}
BarGraphSeries<DataPoint> basalsSeries = null; BarGraphSeries<DataPoint> basalsSeries = null;
LineGraphSeries<DataPoint> seriesLow = null; LineGraphSeries<DataPoint> seriesLow = null;
@ -662,6 +676,7 @@ public class OverviewFragment extends Fragment {
} }
maxBgValue = NSProfile.fromMgdlToUnits(maxBgValue, units); maxBgValue = NSProfile.fromMgdlToUnits(maxBgValue, units);
maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4;
if(highLine > maxBgValue) maxBgValue = highLine;
Integer numOfHorizLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); Integer numOfHorizLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1);
BgReading[] inRange = new BgReading[inRangeArray.size()]; BgReading[] inRange = new BgReading[inRangeArray.size()];

View file

@ -0,0 +1,52 @@
package info.nightscout.androidaps.plugins.Wear;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.FragmentBase;
/**
* Created by adrian on 17/11/16.
*/
public class WearFragment extends Fragment implements FragmentBase {
private static WearPlugin wearPlugin;
public static WearPlugin getPlugin(Context ctx) {
if (wearPlugin == null){
wearPlugin = new WearPlugin(ctx);
}
return wearPlugin;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.wear_fragment, container, false);
view.findViewById(R.id.wear_resend).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getPlugin(getContext()).resendDataToWatch();
}
});
view.findViewById(R.id.wear_opensettings).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getPlugin(getContext()).openSettings();
}
});
return view;
}
}

View file

@ -0,0 +1,144 @@
package info.nightscout.androidaps.plugins.Wear;
import android.content.Context;
import android.content.Intent;
import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Wear.wearintegration.WatchUpdaterService;
/**
* Created by adrian on 17/11/16.
*/
public class WearPlugin implements PluginBase {
static boolean fragmentEnabled = true;
static boolean fragmentVisible = true;
private static WatchUpdaterService watchUS;
private final Context ctx;
WearPlugin(Context ctx){
this.ctx = ctx;
MainApp.bus().register(this);
}
@Override
public int getType() {
return PluginBase.GENERAL;
}
@Override
public String getFragmentClass() {
return WearFragment.class.getName();
}
@Override
public String getName() {
return ctx.getString(R.string.wear);
}
@Override
public boolean isEnabled(int type) {
return fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
WearPlugin.fragmentEnabled = fragmentEnabled;
if(watchUS!=null){
watchUS.setSettings();
}
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
WearPlugin.fragmentVisible = fragmentVisible;
}
private void sendDataToWatch(boolean status, boolean basals, boolean bgValue){
if (isEnabled(getType())) { //only start service when this plugin is enabled
if(bgValue){
ctx.startService(new Intent(ctx, WatchUpdaterService.class));
}
if(basals){
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BASALS));
}
if(status){
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_STATUS));
}
}
}
void resendDataToWatch(){
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_RESEND));
}
void openSettings(){
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS));
}
@Subscribe
public void onStatusEvent(final EventPreferenceChange ev) {
//possibly new high or low mark
resendDataToWatch();
}
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
sendDataToWatch(true, true, false);
}
@Subscribe
public void onStatusEvent(final EventTempBasalChange ev) {
sendDataToWatch(true, true, false);
}
@Subscribe
public void onStatusEvent(final EventNewBG ev) {
sendDataToWatch(true, true, true);
}
@Subscribe
public void onStatusEvent(final EventNewBasalProfile ev) {
sendDataToWatch(false, true, false);
}
public static boolean isEnabled() {
return fragmentEnabled;
}
public static void registerWatchUpdaterService(WatchUpdaterService wus){
watchUS = wus;
}
public static void unRegisterWatchUpdaterService(){
watchUS = null;
}
}

View file

@ -0,0 +1,52 @@
package info.nightscout.androidaps.plugins.Wear.wearintegration;
import android.os.AsyncTask;
import android.util.Log;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import java.util.concurrent.TimeUnit;
/**
* Created by emmablack on 12/26/14.
*/
class SendToDataLayerThread extends AsyncTask<DataMap,Void,Void> {
private GoogleApiClient googleApiClient;
private static final String TAG = "SendDataThread";
String path;
SendToDataLayerThread(String path, GoogleApiClient pGoogleApiClient) {
this.path = path;
googleApiClient = pGoogleApiClient;
}
@Override
protected Void doInBackground(DataMap... params) {
try {
final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(15, TimeUnit.SECONDS);
for (Node node : nodes.getNodes()) {
for (DataMap dataMap : params) {
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleApiClient, request).await(15, TimeUnit.SECONDS);
if (result.getStatus().isSuccess()) {
Log.d(TAG, "DataMap: " + dataMap + " sent to: " + node.getDisplayName());
} else {
Log.d(TAG, "ERROR: failed to send DataMap");
}
}
}
} catch (Exception e) {
Log.e(TAG, "Got exception sending data to wear: " + e.toString());
}
return null;
}
}

View file

@ -0,0 +1,474 @@
package info.nightscout.androidaps.plugins.Wear.wearintegration;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.BatteryManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SafeParse;
public class WatchUpdaterService extends WearableListenerService implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings");
public static final String ACTION_SEND_STATUS = WatchUpdaterService.class.getName().concat(".SendStatus");
public static final String ACTION_SEND_BASALS = WatchUpdaterService.class.getName().concat(".SendBasals");
private GoogleApiClient googleApiClient;
public static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
public static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
private static final String OPEN_SETTINGS_PATH = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
boolean wear_integration = false;
SharedPreferences mPrefs;
@Override
public void onCreate() {
mPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
listenForChangeInSettings();
setSettings();
if (wear_integration) {
googleApiConnect();
}
}
public void listenForChangeInSettings() {
WearPlugin.registerWatchUpdaterService(this);
}
public void setSettings() {
wear_integration = WearPlugin.isEnabled();
if (wear_integration) {
googleApiConnect();
}
}
public void googleApiConnect() {
if(googleApiClient != null && (googleApiClient.isConnected() || googleApiClient.isConnecting())) { googleApiClient.disconnect(); }
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wearable.API)
.build();
Wearable.MessageApi.addListener(googleApiClient, this);
if (googleApiClient.isConnected()) {
Log.d("WatchUpdater", "API client is connected");
} else {
googleApiClient.connect();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
double timestamp = 0;
if (intent != null) {
timestamp = intent.getDoubleExtra("timestamp", 0);
}
String action = null;
if (intent != null) {
action = intent.getAction();
}
if (wear_integration) {
if (googleApiClient.isConnected()) {
if (ACTION_RESEND.equals(action)) {
resendData();
} else if (ACTION_OPEN_SETTINGS.equals(action)) {
sendNotification();
} else if (ACTION_SEND_STATUS.equals(action)) {
sendStatus();
} else if (ACTION_SEND_BASALS.equals(action)) {
sendBasals();
} else {
sendData();
}
} else {
googleApiClient.connect();
}
}
return START_STICKY;
}
@Override
public void onConnected(Bundle connectionHint) {
sendData();
}
@Override
public void onMessageReceived(MessageEvent event) {
if (wear_integration) {
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH))
resendData();
}
}
public void sendData() {
BgReading lastBG = MainApp.getDbHelper().lastBg();
if (lastBG != null) {
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); }
if (wear_integration) {
new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient).execute(dataMapSingleBG(lastBG, glucoseStatus));
}
}
}
private DataMap dataMapSingleBG(BgReading lastBG, DatabaseHelper.GlucoseStatus glucoseStatus) {
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
Double lowLine = SafeParse.stringToDouble(mPrefs.getString("low_mark", "0"));
Double highLine = SafeParse.stringToDouble(mPrefs.getString("high_mark", "0"));
//convert to mg/dl
if (! profile.getUnits().equals(Constants.MGDL)){
lowLine *= Constants.MMOLL_TO_MGDL;
highLine *= Constants.MMOLL_TO_MGDL;
}
if (lowLine < 1){
lowLine = OverviewPlugin.bgTargetLow;
}
if(highLine < 1){
highLine = OverviewPlugin.bgTargetHigh;
}
long sgvLevel = 0l;
if (lastBG.value > highLine) {
sgvLevel = 1;
} else if (lastBG.value < lowLine) {
sgvLevel = -1;
}
DataMap dataMap = new DataMap();
int battery = getBatteryLevel(getApplicationContext());
dataMap.putString("sgvString", lastBG.valueToUnitsToString(profile.getUnits()));
dataMap.putDouble("timestamp", lastBG.getTimeIndex());
if(glucoseStatus == null) {
dataMap.putString("slopeArrow", "" );
dataMap.putString("delta", "");
dataMap.putString("avgDelta", "");
} else {
dataMap.putString("slopeArrow", slopeArrow(glucoseStatus.delta));
dataMap.putString("delta", deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, profile.getUnits()));
dataMap.putString("avgDelta", deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, profile.getUnits()));
}
dataMap.putString("battery", "" + battery);
dataMap.putLong("sgvLevel", sgvLevel);
dataMap.putInt("batteryLevel", (battery>=30)?1:0);
dataMap.putDouble("sgvDouble", lastBG.value);
dataMap.putDouble("high", highLine);
dataMap.putDouble("low", lowLine);
return dataMap;
}
private String deltastring(double deltaMGDL, double deltaMMOL, String units) {
String deltastring = "";
if (deltaMGDL >=0){
deltastring += "+";
} else{
deltastring += "-";
}
if (units.equals(Constants.MGDL)){
deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMGDL));
}
else {
deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMMOL));
}
return deltastring;
}
private String slopeArrow(double delta) {
if (delta <= (-3.5*5)) {
return "\u21ca";
} else if (delta <= (-2*5)) {
return "\u2193";
} else if (delta <= (-1*5)) {
return "\u2198";
} else if (delta <= (1*5)) {
return "\u2192";
} else if (delta <= (2*5)) {
return "\u2197";
} else if (delta <= (3.5*5)) {
return "\u2191";
} else {
return "\u21c8";
}
}
private void resendData() {
if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); }
long startTime = System.currentTimeMillis() - (long)(60000 * 60 * 5.5);
BgReading last_bg = MainApp.getDbHelper().lastBg();
if (last_bg == null) return;
List<BgReading> graph_bgs = MainApp.getDbHelper().getDataFromTime(startTime);
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
if (!graph_bgs.isEmpty()) {
DataMap entries = dataMapSingleBG(last_bg, glucoseStatus);
final ArrayList<DataMap> dataMaps = new ArrayList<>(graph_bgs.size());
for (BgReading bg : graph_bgs) {
dataMaps.add(dataMapSingleBG(bg, glucoseStatus));
}
entries.putDataMapArrayList("entries", dataMaps);
new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient).execute(entries);
}
sendBasals();
sendStatus();
}
private void sendBasals() {
if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); }
long now = System.currentTimeMillis();
long startTimeWindow = now - (long)(60000 * 60 * 5.5);
ArrayList<DataMap> basals = new ArrayList<>();
ArrayList<DataMap> temps = new ArrayList<>();
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
if( profile == null) return;
long beginBasalSegmentTime = startTimeWindow;
long runningTime = startTimeWindow;
double beginBasalValue = profile.getBasal(NSProfile.secondsFromMidnight(new Date(beginBasalSegmentTime)));
double endBasalValue = beginBasalValue;
TempBasal tb1 = MainApp.getConfigBuilder().getTempBasal(new Date(runningTime));
TempBasal tb2 = MainApp.getConfigBuilder().getTempBasal(new Date(runningTime));
double tb_before = beginBasalValue;
double tb_amount = beginBasalValue;
long tb_start = runningTime;
if(tb1 != null){
tb_before = beginBasalValue;
tb_amount = tb1.tempBasalConvertedToAbsolute(new Date(runningTime));
tb_start = runningTime;
}
for(;runningTime<now;runningTime+= 5*60*1000){
//basal rate
endBasalValue = profile.getBasal(NSProfile.secondsFromMidnight(new Date(runningTime)));
if(endBasalValue != beginBasalValue){
//push the segment we recently left
basals.add(basalMap(beginBasalSegmentTime, runningTime, beginBasalValue));
//begin new Basal segment
beginBasalSegmentTime = runningTime;
beginBasalValue = endBasalValue;
}
//temps
tb2 = MainApp.getConfigBuilder().getTempBasal(new Date(runningTime));
if (tb1 == null && tb2 == null) {
//no temp stays no temp
} else if (tb1 != null && tb2 == null) {
//temp is over -> push it
temps.add(tempDatamap(tb_start, tb_before, runningTime, endBasalValue, tb_amount));
tb1 = null;
} else if (tb1 == null && tb2 != null) {
//temp begins
tb1 = tb2;
tb_start = runningTime;
tb_before = endBasalValue;
tb_amount = tb1.tempBasalConvertedToAbsolute(new Date(runningTime));
} else if (tb1 != null && tb2 != null) {
double currentAmount = tb2.tempBasalConvertedToAbsolute(new Date(runningTime));
if(currentAmount != tb_amount){
temps.add(tempDatamap(tb_start, tb_before, runningTime, currentAmount, tb_amount));
tb_start = runningTime;
tb_before = tb_amount;
tb_amount = currentAmount;
tb1 = tb2;
}
}
}
if(beginBasalSegmentTime != runningTime){
//push the remaining segment
basals.add(basalMap(beginBasalSegmentTime, runningTime, beginBasalValue));
}
if(tb1 != null){
tb2 = MainApp.getConfigBuilder().getTempBasal(new Date(now)); //use "now" to express current situation
if(tb2 == null) {
//express the cancelled temp by painting it down one minute early
temps.add(tempDatamap(tb_start, tb_before, now - 1 * 60 * 1000, endBasalValue, tb_amount));
} else {
//express currently running temp by painting it a bit into the future
double currentAmount = tb2.tempBasalConvertedToAbsolute(new Date(now));
if(currentAmount != tb_amount){
temps.add(tempDatamap(tb_start, tb_before, now, tb_amount, tb_amount));
temps.add(tempDatamap(now, tb_amount, runningTime + 5 * 60 * 1000, currentAmount, currentAmount));
} else {
temps.add(tempDatamap(tb_start, tb_before, runningTime + 5 * 60 * 1000, tb_amount, tb_amount));
}
}
} else {
tb2 = MainApp.getConfigBuilder().getTempBasal(new Date(now)); //use "now" to express current situation
if(tb2 != null) {
//onset at the end
double currentAmount = tb2.tempBasalConvertedToAbsolute(new Date(runningTime));
temps.add(tempDatamap(now - 1 * 60 * 1000, endBasalValue, runningTime + 5 * 60 * 1000, currentAmount, currentAmount));
}
}
DataMap dm = new DataMap();
dm.putDataMapArrayList("basals", basals);
dm.putDataMapArrayList("temps", temps);
new SendToDataLayerThread(BASAL_DATA_PATH, googleApiClient).execute(dm);
}
private DataMap tempDatamap(long startTime, double startBasal, long to, double toBasal, double amount) {
DataMap dm = new DataMap();
dm.putLong("starttime", startTime);
dm.putDouble("startBasal", startBasal);
dm.putLong("endtime", to);
dm.putDouble("endbasal", toBasal);
dm.putDouble("amount", amount);
return dm;
}
private DataMap basalMap(long startTime, long endTime, double amount) {
DataMap dm = new DataMap();
dm.putLong("starttime", startTime);
dm.putLong("endtime", endTime);
dm.putDouble("amount", amount);
return dm;
}
private void sendNotification() {
if (googleApiClient.isConnected()) {
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(OPEN_SETTINGS_PATH);
//unique content
dataMapRequest.getDataMap().putDouble("timestamp", System.currentTimeMillis());
dataMapRequest.getDataMap().putString("openSettings", "openSettings");
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
Log.e("OpenSettings", "No connection to wearable available!");
}
}
private void sendStatus() {
if (googleApiClient.isConnected()) {
String status = "";
boolean shortString = true;
//Temp basal
PumpInterface pump = MainApp.getConfigBuilder();
if (pump.isTempBasalInProgress()) {
TempBasal activeTemp = pump.getTempBasal();
if (shortString) {
status += activeTemp.toStringShort();
} else {
status += activeTemp.toStringMedium();
}
}
//IOB
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
if (bolusIob == null) bolusIob = new IobTotal();
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
if (basalIob == null) basalIob = new IobTotal();
status += (shortString?"":(getString(R.string.treatments_iob_label_string) + " ")) + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "("
+ DecimalFormatter.to2Decimal(bolusIob.iob) + "|"
+ DecimalFormatter.to2Decimal(basalIob.basaliob) + ")";
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_STATUS_PATH);
//unique content
dataMapRequest.getDataMap().putDouble("timestamp", System.currentTimeMillis());
dataMapRequest.getDataMap().putString("externalStatusString", status);
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
Log.e("SendStatus", "No connection to wearable available!");
}
}
@Override
public void onDestroy() {
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
WearPlugin.unRegisterWatchUpdaterService();
}
@Override
public void onConnectionSuspended(int cause) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public static int getBatteryLevel(Context context) {
Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
if(level == -1 || scale == -1) {
return 50;
}
return (int)(((float)level / (float)scale) * 100.0f);
}
}

View file

@ -0,0 +1,40 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.nightscout.androidaps.plugins.Wear.WearFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/wear_resend"
style="?android:attr/buttonStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="0.5"
android:text="@string/resend_all_data"
android:textColor="@color/colorTreatmentButton" />
<Button
android:id="@+id/wear_opensettings"
style="?android:attr/buttonStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_weight="0.5"
android:text="@string/open_settings_on_wear"
android:textColor="@color/colorTreatmentButton" />
</LinearLayout>
</FrameLayout>

View file

@ -187,7 +187,7 @@
<string name="export_to">Експортирай настройки до</string> <string name="export_to">Експортирай настройки до</string>
<string name="nav_export">Експорт настройки</string> <string name="nav_export">Експорт настройки</string>
<string name="nav_import">Импорт настройки</string> <string name="nav_import">Импорт настройки</string>
<string name="de_lang">Deutsch</string> <string name="de_lang">German</string>
<string name="openapsma_high_summary">Макс. стойност, която е в границите</string> <string name="openapsma_high_summary">Макс. стойност, която е в границите</string>
<string name="openapsma_low_summary">Мин. стойност, която е в границите</string> <string name="openapsma_low_summary">Мин. стойност, която е в границите</string>
<string name="openapsma_maxbasal_summary">Макс. лимит на временен базал [Е/ч] </string> <string name="openapsma_maxbasal_summary">Макс. лимит на временен базал [Е/ч] </string>
@ -240,7 +240,7 @@
<string name="careportal_temporarytargetcancel">Отакажи временна цел</string> <string name="careportal_temporarytargetcancel">Отакажи временна цел</string>
<string name="comment">Коментар</string> <string name="comment">Коментар</string>
<string name="absolute">Абсолютна</string> <string name="absolute">Абсолютна</string>
<string name="overview_bolusiprogress_occlusion">Запушване</string> <string name="occlusion">Запушване</string>
<string name="overview_bolusprogress_delivered">Доставено</string> <string name="overview_bolusprogress_delivered">Доставено</string>
<string name="overview_bolusprogress_goingtodeliver" formatted="false">Подаване на %.2fU Е инсулин</string> <string name="overview_bolusprogress_goingtodeliver" formatted="false">Подаване на %.2fU Е инсулин</string>
<string name="overview_bolusprogress_stop">Стоп</string> <string name="overview_bolusprogress_stop">Стоп</string>
@ -295,7 +295,7 @@
<string name="objectives_5_objective">Настройване на базалния инсулин и коефициенти ако е необходимо и активиране на auto-sens</string> <string name="objectives_5_objective">Настройване на базалния инсулин и коефициенти ако е необходимо и активиране на auto-sens</string>
<string name="uploading">Uploading</string> <string name="uploading">Uploading</string>
<string name="bolusdelivering" formatted="false">Подава %.2fU</string> <string name="bolusdelivering" formatted="false">Подава %.2fU</string>
<string name="es_lang">Español</string> <string name="es_lang">Spanish</string>
<string name="noprofileselected">Не е избран профил</string> <string name="noprofileselected">Не е избран профил</string>
<string name="ko_lang">Korean</string> <string name="ko_lang">Korean</string>
<string name="openapsma_valueoutofrange" formatted="false">%s е недопустима стойност</string> <string name="openapsma_valueoutofrange" formatted="false">%s е недопустима стойност</string>

View file

@ -272,7 +272,7 @@
<string name="wrongpumppassword">Špatné heslo k pumpě</string> <string name="wrongpumppassword">Špatné heslo k pumpě</string>
<string name="mm640g">MM 640g</string> <string name="mm640g">MM 640g</string>
<string name="danar_password">Heslo k pumpě</string> <string name="danar_password">Heslo k pumpě</string>
<string name="overview_bolusiprogress_occlusion">Okluze</string> <string name="occlusion">Okluze</string>
<string name="overview_bolusprogress_delivered">Podáno</string> <string name="overview_bolusprogress_delivered">Podáno</string>
<string name="overview_bolusprogress_stop">Stop</string> <string name="overview_bolusprogress_stop">Stop</string>
<string name="overview_bolusprogress_stoped">Zastaveno</string> <string name="overview_bolusprogress_stoped">Zastaveno</string>
@ -299,7 +299,7 @@
<string name="smscommunicator_loophasbeenenabled">Smyčka byla povolena</string> <string name="smscommunicator_loophasbeenenabled">Smyčka byla povolena</string>
<string name="smscommunicator_loopisdisabled">Smyčka je zakázána</string> <string name="smscommunicator_loopisdisabled">Smyčka je zakázána</string>
<string name="smscommunicator_loopisenabled">Smyčka je povolena</string> <string name="smscommunicator_loopisenabled">Smyčka je povolena</string>
<string name="es_lang">Español</string> <string name="es_lang">Spanish</string>
<string name="noprofileselected">Není vybrán žádný profil</string> <string name="noprofileselected">Není vybrán žádný profil</string>
<string name="openapsma_valueoutofrange" formatted="false">Hodnota %s je mimo přednastavený rozsah</string> <string name="openapsma_valueoutofrange" formatted="false">Hodnota %s je mimo přednastavený rozsah</string>
<string name="remotebasalnotallowed">Vzdálené posílání příkazů není povoleno</string> <string name="remotebasalnotallowed">Vzdálené posílání příkazů není povoleno</string>
@ -322,4 +322,46 @@
<string name="ko_lang">Korean</string> <string name="ko_lang">Korean</string>
<string name="correctionbous">Korekce</string> <string name="correctionbous">Korekce</string>
<string name="actions">Akce</string> <string name="actions">Akce</string>
<string name="androidaps_start">AndroidAPS restartován</string>
<string name="androidaps_tempbasalendnote">Dočasný bazál konec</string>
<string name="androidaps_tempbasalstartnote">Dočasný bazál začátek</string>
<string name="absorption_rate">Rychlost absorbce sacharidů:</string>
<string name="alert_dialog_storage_permission_text">Prosím restartujte Váš telefon nebo restartujte AndroidAPS z nastavení systému jinak nebudou zaznamenány ladící informace (důležité pro sledování a kontrolu, zda algoritmus pracuje správně)</string>
<string name="base_profile_label">Bazální profil:</string>
<string name="batterydischarged">Baterie v pumpě vybitá</string>
<string name="button1">Tlačítko 1</string>
<string name="button2">Tlačítko 2</string>
<string name="button3">Tlačítko 3</string>
<string name="circadian_percentage_profile">Cirkadiánní procentuální profil</string>
<string name="dia">DIA:</string>
<string name="disabledloop">Smyčka zakázána</string>
<string name="edit_base_basal">Editovat základní bazál:</string>
<string name="edit_base_ic">Editovat základní IC:</string>
<string name="edit_base_isf">Editovat základní ISF:</string>
<string name="fillbolus_title">Hodnoty plnění/doplňování</string>
<string name="fillwarning">Prosím ujistěte se, že hodnota odpovídá specifikaci Vašeho setu!</string>
<string name="high_mark">Horní značka</string>
<string name="low_mark">Dolní značka</string>
<string name="lowbattery">Nízký stav baterie</string>
<string name="mgdl">mg/dl</string>
<string name="mmol">mmol/l</string>
<string name="ns_upload_only">Pouze náhráváni do NS (zakázaná synchronizace)</string>
<string name="ns_upload_only_enabled">Prosím deaktivujte \"Pouze nahrávání do NS\", abyste mohli použít tuto funkci.</string>
<string name="ns_upload_only_summary">Pouze náhrávání dat do NS. Neplatí pro glykémie, dokud není vybraní místní zdroj dat jako xDrip. Neplatí pro profily, pokud se používá NS profil.</string>
<string name="open_settings_on_wear">Otevřít nastavení na hodinkách Wear</string>
<string name="othersettings_title">Jiné</string>
<string name="percentagefactor_hint">Hodnota v procentech, kterou bude základní profil vynásoben.</string>
<string name="prefs_range_summary">Značka vysoké a nízké hodnoty v přehledu a na hodinkách Wear</string>
<string name="prefs_range_title">Rozsah pro zobrazení</string>
<string name="primefill">Plnění/doplňování</string>
<string name="pumpNotInitialized">Pumpa není inicializována</string>
<string name="pumperror">Chyba pumpy</string>
<string name="pumpshutdown">Pumpa vypnuta</string>
<string name="resend_all_data">Znovu poslat všechny data</string>
<string name="reset_db_confirm">Opravdu resetovat všechny databáze</string>
<string name="send_to_pump">POSLAT DO PUMPY</string>
<string name="target_range">Cílový rozsah:</string>
<string name="timeshift_hint">Čas v hodinách, o který bude bazál posunutý.</string>
<string name="units">Jednotky:</string>
<string name="wear">Wear</string>
</resources> </resources>

View file

@ -287,9 +287,10 @@
<string name="ns_upload_only_enabled">Bitte deaktivieren Sie \"Zu NightScout nur hochladen\" um dieses Feature zu nutzen.</string> <string name="ns_upload_only_enabled">Bitte deaktivieren Sie \"Zu NightScout nur hochladen\" um dieses Feature zu nutzen.</string>
<string name="ns_upload_only_summary">Zu NightScout nur hochladen. Nicht wirksam bei SGV wenn nicht eine lokale Quelle wie xDrip gewählt wird. Nicht wirksam bei Profilen, wenn NS-Profile verwendet werden.</string> <string name="ns_upload_only_summary">Zu NightScout nur hochladen. Nicht wirksam bei SGV wenn nicht eine lokale Quelle wie xDrip gewählt wird. Nicht wirksam bei Profilen, wenn NS-Profile verwendet werden.</string>
<string name="othersettings_title">Andere</string> <string name="othersettings_title">Andere</string>
<string name="overview_bolusiprogress_occlusion">Verstopfung</string> <string name="occlusion">Verstopfung</string>
<string name="overview_bolusprogress_delivered">Abgegeben</string> <string name="overview_bolusprogress_delivered">Abgegeben</string>
<string name="overview_bolusprogress_goingtodeliver">%.2fU werden abgegeben werden</string> <string name="overview_bolusprogress_goingtodeliver">%.2fU werden abgegeben werden</string>
<string name="primefill">Füllen</string> <string name="primefill">Füllen</string>
<string name="uploading">Hochladen</string> <string name="uploading">Hochladen</string>
<string name="es_lang">Spanish</string>
</resources> </resources>

View file

@ -139,8 +139,8 @@
<string name="objectives_pumpstatusavailableinns">Estado de la bomba disponible en NS</string> <string name="objectives_pumpstatusavailableinns">Estado de la bomba disponible en NS</string>
<string name="objectives_manualenacts">Aceptados</string> <string name="objectives_manualenacts">Aceptados</string>
<string name="loopdisabled">LAZO DESACTIVADO POR RESTRICCIONES</string> <string name="loopdisabled">LAZO DESACTIVADO POR RESTRICCIONES</string>
<string name="cs_lang">checo</string> <string name="cs_lang">Czech</string>
<string name="en_lang">Inglés</string> <string name="en_lang">English</string>
<string name="treatments_wizard_basaliob_label">Basal IOB</string> <string name="treatments_wizard_basaliob_label">Basal IOB</string>
<string name="bolusconstraintapplied">Restricción aplicada en bolo</string> <string name="bolusconstraintapplied">Restricción aplicada en bolo</string>
<string name="carbsconstraintapplied">Restricción aplicada en carbohidratos</string> <string name="carbsconstraintapplied">Restricción aplicada en carbohidratos</string>
@ -197,12 +197,12 @@
<string name="filenotfound">Archivo no encontrado</string> <string name="filenotfound">Archivo no encontrado</string>
<string name="nav_export">Exportar ajustes</string> <string name="nav_export">Exportar ajustes</string>
<string name="nav_import">Importar ajustes</string> <string name="nav_import">Importar ajustes</string>
<string name="de_lang">alemán</string> <string name="de_lang">German</string>
<string name="openapsma_low_summary">Valor mínimo de BG para estar en rango.</string> <string name="openapsma_low_summary">Valor mínimo de BG para estar en rango.</string>
<string name="openapsma_high_summary">Valor máximo BG para estar en rango.</string> <string name="openapsma_high_summary">Valor máximo BG para estar en rango.</string>
<string name="openapsma_maxbasal_summary">Max valor U / hr en Basal temporal</string> <string name="openapsma_maxbasal_summary">Max valor U / hr en Basal temporal</string>
<string name="openapsma_maxiob_summary">Máximos basales IOB para OpenAPS [U]</string> <string name="openapsma_maxiob_summary">Máximos basales IOB para OpenAPS [U]</string>
<string name="bg_lang">búlgaro</string> <string name="bg_lang">Bulgarian</string>
<string name="dismiss">DESCARTAR</string> <string name="dismiss">DESCARTAR</string>
<string name="language">Idioma</string> <string name="language">Idioma</string>
@ -283,7 +283,7 @@
<string name="pumpbusy">Bomba ocupada</string> <string name="pumpbusy">Bomba ocupada</string>
<string name="overview_bolusprogress_delivered">Entregado</string> <string name="overview_bolusprogress_delivered">Entregado</string>
<string name="overview_bolusprogress_stoped">Detenido</string> <string name="overview_bolusprogress_stoped">Detenido</string>
<string name="overview_bolusiprogress_occlusion">Oclusión</string> <string name="occlusion">Oclusión</string>
<string name="overview_bolusprogress_stop">Detener</string> <string name="overview_bolusprogress_stop">Detener</string>
<string name="overview_bolusprogress_stoppressed">Parar pulsado</string> <string name="overview_bolusprogress_stoppressed">Parar pulsado</string>
<string name="waitingforpump">Esperando bomba</string> <string name="waitingforpump">Esperando bomba</string>

View file

@ -140,8 +140,8 @@
<string name="objectives_pumpstatusavailableinns">NS에서 펌프상태가 확인 가능합니다.</string> <string name="objectives_pumpstatusavailableinns">NS에서 펌프상태가 확인 가능합니다.</string>
<string name="objectives_manualenacts">수동 주입</string> <string name="objectives_manualenacts">수동 주입</string>
<string name="loopdisabled">제한으로 인해 LOOP가 사용불가합니다.</string> <string name="loopdisabled">제한으로 인해 LOOP가 사용불가합니다.</string>
<string name="cs_lang">체코어</string> <string name="cs_lang">Czech</string>
<string name="en_lang">영어</string> <string name="en_lang">English</string>
<string name="treatments_wizard_basaliob_label">기초주입 IOB</string> <string name="treatments_wizard_basaliob_label">기초주입 IOB</string>
<string name="bolusconstraintapplied">식사주입 제한이 적용되었습니다</string> <string name="bolusconstraintapplied">식사주입 제한이 적용되었습니다</string>
<string name="carbsconstraintapplied">탄수화물 제한이 적용되었습니다</string> <string name="carbsconstraintapplied">탄수화물 제한이 적용되었습니다</string>
@ -198,13 +198,13 @@
<string name="filenotfound">파일을 찾을 수 없습니다</string> <string name="filenotfound">파일을 찾을 수 없습니다</string>
<string name="nav_export">Export 설정</string> <string name="nav_export">Export 설정</string>
<string name="nav_import">Import 설정</string> <string name="nav_import">Import 설정</string>
<string name="de_lang">독일어</string> <string name="de_lang">German</string>
<string name="es_lang">스페인어</string> <string name="es_lang">Spanish</string>
<string name="openapsma_low_summary">목표범위 최소 혈당값</string> <string name="openapsma_low_summary">목표범위 최소 혈당값</string>
<string name="openapsma_high_summary">목표범위 최대 혈당값</string> <string name="openapsma_high_summary">목표범위 최대 혈당값</string>
<string name="openapsma_maxbasal_summary">임시기초주입 최대량 [U/hr]</string> <string name="openapsma_maxbasal_summary">임시기초주입 최대량 [U/hr]</string>
<string name="openapsma_maxiob_summary">OpenAPS가 주입할수 있는 최대 기초주입 IOB [U]</string> <string name="openapsma_maxiob_summary">OpenAPS가 주입할수 있는 최대 기초주입 IOB [U]</string>
<string name="bg_lang">불가리아어</string> <string name="bg_lang">Bulgarian</string>
<string name="dismiss">DISMISS</string> <string name="dismiss">DISMISS</string>
<string name="language">언어</string> <string name="language">언어</string>
@ -286,7 +286,7 @@
<string name="pumpbusy">펌프가 바쁩니다</string> <string name="pumpbusy">펌프가 바쁩니다</string>
<string name="overview_bolusprogress_delivered">주입됨</string> <string name="overview_bolusprogress_delivered">주입됨</string>
<string name="overview_bolusprogress_stoped">정지됨</string> <string name="overview_bolusprogress_stoped">정지됨</string>
<string name="overview_bolusiprogress_occlusion">Occlusion</string> <string name="occlusion">Occlusion</string>
<string name="overview_bolusprogress_stop">정지</string> <string name="overview_bolusprogress_stop">정지</string>
<string name="overview_bolusprogress_stoppressed">정지 누름</string> <string name="overview_bolusprogress_stoppressed">정지 누름</string>
<string name="waitingforpump">펌프를 기다리고 있습니다.</string> <string name="waitingforpump">펌프를 기다리고 있습니다.</string>

View file

@ -202,7 +202,7 @@
<string name="nav_export">Export settings</string> <string name="nav_export">Export settings</string>
<string name="nav_import">Import settings</string> <string name="nav_import">Import settings</string>
<string name="de_lang">German</string> <string name="de_lang">German</string>
<string name="es_lang">Español</string> <string name="es_lang">Spanish</string>
<string name="openapsma_low_summary">The minimum BG value to be in range.</string> <string name="openapsma_low_summary">The minimum BG value to be in range.</string>
<string name="openapsma_high_summary">The maximum BG value to be in range.</string> <string name="openapsma_high_summary">The maximum BG value to be in range.</string>
<string name="openapsma_maxbasal_summary">Max U/hr a Temp Basal can be set to</string> <string name="openapsma_maxbasal_summary">Max U/hr a Temp Basal can be set to</string>
@ -289,7 +289,7 @@
<string name="pumpbusy">Pump is busy</string> <string name="pumpbusy">Pump is busy</string>
<string name="overview_bolusprogress_delivered">Delivered</string> <string name="overview_bolusprogress_delivered">Delivered</string>
<string name="overview_bolusprogress_stoped">Stopped</string> <string name="overview_bolusprogress_stoped">Stopped</string>
<string name="overview_bolusiprogress_occlusion">Occlusion</string> <string name="occlusion">Occlusion</string>
<string name="overview_bolusprogress_stop">Stop</string> <string name="overview_bolusprogress_stop">Stop</string>
<string name="overview_bolusprogress_stoppressed">STOP PRESSED</string> <string name="overview_bolusprogress_stoppressed">STOP PRESSED</string>
<string name="waitingforpump">Waiting for pump</string> <string name="waitingforpump">Waiting for pump</string>
@ -364,4 +364,15 @@
<string name="circadian_percentage_profile">CircadianPercentageProfile</string> <string name="circadian_percentage_profile">CircadianPercentageProfile</string>
<string name="androidaps_tempbasalendnote">Basal Temp End</string> <string name="androidaps_tempbasalendnote">Basal Temp End</string>
<string name="androidaps_tempbasalstartnote">Basal Temp Start</string> <string name="androidaps_tempbasalstartnote">Basal Temp Start</string>
<string name="prefs_range_title">Range for Visualization</string>
<string name="prefs_range_summary">High and low mark for the charts in Overview and Smartwatch</string>
<string name="low_mark">LOW mark</string>
<string name="high_mark">HIGH mark</string>
<string name="wear">Wear</string>
<string name="resend_all_data">Resend All Data</string>
<string name="open_settings_on_wear">Open Settings on Wear</string>
<string name="pumperror">Pump Error</string>
<string name="lowbattery">Low Battery</string>
<string name="pumpshutdown">Pump Shutdown</string>
<string name="batterydischarged">Pump Battery Discharged</string>
</resources> </resources>

View file

@ -24,5 +24,21 @@
android:inputType="numberDecimal"> android:inputType="numberDecimal">
</EditTextPreference> </EditTextPreference>
</PreferenceScreen> </PreferenceScreen>
<PreferenceScreen
android:title="@string/prefs_range_title"
android:summary= "@string/prefs_range_summary">
<EditTextPreference
android:title="@string/low_mark"
android:key="low_mark"
android:defaultValue="0"
android:inputType="number">
</EditTextPreference>
<EditTextPreference
android:title="@string/high_mark"
android:key="high_mark"
android:defaultValue="0"
android:inputType="number">
</EditTextPreference>
</PreferenceScreen>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View file

@ -1 +1 @@
include ':app' include ':app', ':wear'

1
wear/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

56
wear/build.gradle Normal file
View file

@ -0,0 +1,56 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "info.nightscout.androidaps"
minSdkVersion 20
targetSdkVersion 23
versionCode 1
versionName "1.0.2"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
publishNonDefault true
productFlavors {
full {
applicationId = "info.nightscout.androidaps"
resValue "string", "label_xdrip", "AAPS"
resValue "string", "label_xdrip_large", "AAPS(Large)"
resValue "string", "label_xdrip_big_chart", "AAPS(BigChart)"
resValue "string", "label_xdrip_circle", "AAPS(Circle)"
resValue "string", "label_xdrip_activity", "AAPS Prefs."
resValue "string", "app_settings", "AAPS Settings"
}
}
}
allprojects {
repositories {
jcenter()
flatDir {
dirs 'libs'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
//compile 'com.ustwo.android:clockwise-wearable:1.0.2'
compile 'com.google.android.support:wearable:1.4.0'
compile 'com.google.android.gms:play-services-wearable:7.3.0'
compile files('libs/hellocharts-library-1.5.5.jar')
compile(name:'ustwo-clockwise-debug', ext:'aar')
compile 'com.android.support:support-v4:23.0.1'
compile 'me.denley.wearpreferenceactivity:wearpreferenceactivity:0.5.0'
}

Binary file not shown.

Binary file not shown.

17
wear/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/stephenblack/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View file

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.nightscout.androidaps" >
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<service
android:name="info.nightscout.androidaps.BIGChart"
android:allowEmbedded="true"
android:label="@string/label_xdrip_big_chart"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_bigchart" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service
android:name="info.nightscout.androidaps.Home"
android:allowEmbedded="true"
android:label="@string/label_xdrip"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_graph" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service
android:name="info.nightscout.androidaps.LargeHome"
android:allowEmbedded="true"
android:label="@string/label_xdrip_large"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_dark" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service
android:name="info.nightscout.androidaps.CircleWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_circle"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/watch_face"/>
<meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/watchface_circle" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<service android:name="info.nightscout.androidaps.ListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<activity
android:name="info.nightscout.androidaps.NWPreferences"
android:label="@string/label_xdrip_activity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,632 @@
package info.nightscout.androidaps;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.wearable.view.WatchViewStub;
import android.support.wearable.watchface.WatchFaceStyle;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.android.gms.wearable.DataMap;
import com.ustwo.clockwise.wearable.WatchFace;
import com.ustwo.clockwise.common.WatchFaceTime;
import com.ustwo.clockwise.common.WatchMode;
import com.ustwo.clockwise.common.WatchShape;
import java.util.ArrayList;
import java.util.Date;
import lecho.lib.hellocharts.view.LineChartView;
/**
* Created by adrianLxM.
*/
public class BIGChart extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
public final static IntentFilter INTENT_FILTER;
public TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
public RelativeLayout mRelativeLayout;
public long sgvLevel = 0;
public int batteryLevel = 1;
public int ageLevel = 1;
public int highColor = Color.YELLOW;
public int lowColor = Color.RED;
public int midColor = Color.WHITE;
public int gridColour = Color.WHITE;
public int basalBackgroundColor = Color.BLUE;
public int basalCenterColor = Color.BLUE;
public int pointSize = 2;
public boolean lowResMode = false;
public boolean layoutSet = false;
public BgGraphBuilder bgGraphBuilder;
public LineChartView chart;
public double datetime;
public ArrayList<BgWatchData> bgDataList = new ArrayList<>();
public ArrayList<TempWatchData> tempWatchDataList = new ArrayList<>();
public ArrayList<BasalWatchData> basalWatchDataList = new ArrayList<>();
public PowerManager.WakeLock wakeLock;
public View layoutView;
private final Point displaySize = new Point();
private int specW, specH;
private int animationAngle = 0;
private boolean isAnimated = false;
private LocalBroadcastManager localBroadcastManager;
private MessageReceiver messageReceiver;
protected SharedPreferences sharedPrefs;
private String rawString = "000 | 000 | 000";
private String batteryString = "--";
private String sgvString = "--";
private String externalStatusString = "no status";
private TextView statusView;
private long chartTapTime = 0l;
@Override
public void onCreate() {
super.onCreate();
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
display.getSize(displaySize);
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Clock");
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x,
View.MeasureSpec.EXACTLY);
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
View.MeasureSpec.EXACTLY);
sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_bigchart, null);
performViewSetup();
}
@Override
protected void onLayout(WatchShape shape, Rect screenBounds, WindowInsets screenInsets) {
super.onLayout(shape, screenBounds, screenInsets);
layoutView.onApplyWindowInsets(screenInsets);
}
public void performViewSetup() {
final WatchViewStub stub = (WatchViewStub) layoutView.findViewById(R.id.watch_view_stub);
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
messageReceiver = new MessageReceiver();
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
mTime = (TextView) stub.findViewById(R.id.watch_time);
mSgv = (TextView) stub.findViewById(R.id.sgv);
mTimestamp = (TextView) stub.findViewById(R.id.timestamp);
mDelta = (TextView) stub.findViewById(R.id.delta);
mAvgDelta = (TextView) stub.findViewById(R.id.avgdelta);
mRelativeLayout = (RelativeLayout) stub.findViewById(R.id.main_layout);
chart = (LineChartView) stub.findViewById(R.id.chart);
statusView = (TextView) stub.findViewById(R.id.aps_status);
layoutSet = true;
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
});
ListenerService.requestData(this);
wakeLock.acquire(50);
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
if (tapType == TAP_TYPE_TAP&&
x >=chart.getLeft() &&
x <= chart.getRight()&&
y >= chart.getTop() &&
y <= chart.getBottom()){
if (eventTime - chartTapTime < 800){
changeChartTimeframe();
}
chartTapTime = eventTime;
}
}
private void changeChartTimeframe() {
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
timeframe = (timeframe%5) + 1;
sharedPrefs.edit().putString("chart_timeframe", "" + timeframe).commit();
}
protected void onWatchModeChanged(WatchMode watchMode) {
if(lowResMode ^ isLowRes(watchMode)){ //if there was a change in lowResMode
lowResMode = isLowRes(watchMode);
setColor();
} else if (! sharedPrefs.getBoolean("dark", true)){
//in bright mode: different colours if active:
setColor();
}
}
private boolean isLowRes(WatchMode watchMode) {
return (watchMode == WatchMode.LOW_BIT) || (watchMode == WatchMode.LOW_BIT_BURN_IN) || (watchMode == WatchMode.LOW_BIT_BURN_IN);
}
@Override
protected WatchFaceStyle getWatchFaceStyle(){
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
public int ageLevel() {
if(timeSince() <= (1000 * 60 * 12)) {
return 1;
} else {
return 0;
}
}
public double timeSince() {
return System.currentTimeMillis() - datetime;
}
public String readingAge(boolean shortString) {
if (datetime == 0) { return shortString?"--'":"-- Minute ago"; }
int minutesAgo = (int) Math.floor(timeSince()/(1000*60));
if (minutesAgo == 1) {
return minutesAgo + (shortString?"'":" Minute ago");
}
return minutesAgo + (shortString?"'":" Minutes ago");
}
@Override
public void onDestroy() {
if(localBroadcastManager != null && messageReceiver != null){
localBroadcastManager.unregisterReceiver(messageReceiver);}
if (sharedPrefs != null){
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
}
super.onDestroy();
}
static {
INTENT_FILTER = new IntentFilter();
INTENT_FILTER.addAction(Intent.ACTION_TIME_TICK);
INTENT_FILTER.addAction(Intent.ACTION_TIMEZONE_CHANGED);
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
}
@Override
protected void onDraw(Canvas canvas) {
if(layoutSet) {
this.mRelativeLayout.draw(canvas);
Log.d("onDraw", "draw");
}
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
wakeLock.acquire(50);
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BIGChart.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
showAgeAndStatus();
if(ageLevel()<=0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
missedReadingAlert();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getBundleExtra("data");
if (layoutSet && bundle !=null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(50);
sgvLevel = dataMap.getLong("sgvLevel");
batteryLevel = dataMap.getInt("batteryLevel");
datetime = dataMap.getDouble("timestamp");
rawString = dataMap.getString("rawString");
sgvString = dataMap.getString("sgvString");
batteryString = dataMap.getString("battery");
mSgv.setText(dataMap.getString("sgvString"));
if(ageLevel()<=0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BIGChart.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
showAgeAndStatus();
String delta = dataMap.getString("delta");
if (delta.endsWith(" mg/dl")) {
mDelta.setText(delta.substring(0, delta.length() - 6));
} else if (delta.endsWith(" mmol/l")||delta.endsWith(" mmol")) {
mDelta.setText(delta.substring(0, delta.length() - 5));
} else {
mDelta.setText(delta);
}
String avgDelta = dataMap.getString("avgDelta");
if (delta.endsWith(" mg/dl")) {
mAvgDelta.setText(avgDelta.substring(0, avgDelta.length() - 6));
} else if (avgDelta.endsWith(" mmol/l")||avgDelta.endsWith(" mmol")) {
mAvgDelta.setText(avgDelta.substring(0, avgDelta.length() - 5));
} else {
mAvgDelta.setText(avgDelta);
}
if (chart != null) {
addToWatchSet(dataMap);
setupCharts();
}
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
//start animation?
// dataMap.getDataMapArrayList("entries") == null -> not on "resend data".
if (!lowResMode && (sharedPrefs.getBoolean("animation", false) && dataMap.getDataMapArrayList("entries") == null && (sgvString.equals("100") || sgvString.equals("5.5") || sgvString.equals("5,5")))) {
startAnimation();
}
}
//status
bundle = intent.getBundleExtra("status");
if (layoutSet && bundle != null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(50);
externalStatusString = dataMap.getString("externalStatusString");
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
}
//basals and temps
bundle = intent.getBundleExtra("basals");
if (layoutSet && bundle != null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(500);
loadBasalsAndTemps(dataMap);
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
}
}
}
private void loadBasalsAndTemps(DataMap dataMap) {
ArrayList<DataMap> temps = dataMap.getDataMapArrayList("temps");
if (temps != null) {
tempWatchDataList = new ArrayList<>();
for (DataMap temp : temps) {
TempWatchData twd = new TempWatchData();
twd.startTime = temp.getLong("starttime");
twd.startBasal = temp.getDouble("startBasal");
twd.endTime = temp.getLong("endtime");
twd.endBasal = temp.getDouble("endbasal");
twd.amount = temp.getDouble("amount");
tempWatchDataList.add(twd);
}
}
ArrayList<DataMap> basals = dataMap.getDataMapArrayList("basals");
if (basals != null) {
basalWatchDataList = new ArrayList<>();
for (DataMap basal : basals) {
BasalWatchData bwd = new BasalWatchData();
bwd.startTime = basal.getLong("starttime");
bwd.endTime = basal.getLong("endtime");
bwd.amount = basal.getDouble("amount");
basalWatchDataList.add(bwd);
}
}
}
private void showAgeAndStatus() {
if( mTimestamp != null){
mTimestamp.setText(readingAge(true));
}
boolean showStatus = sharedPrefs.getBoolean("showExternalStatus", true);
boolean showAvgDelta = sharedPrefs.getBoolean("showAvgDelta", true);
if(showAvgDelta){
mAvgDelta.setVisibility(View.VISIBLE);
} else {
mAvgDelta.setVisibility(View.GONE);
}
if(showStatus){
statusView.setText(externalStatusString);
statusView.setVisibility(View.VISIBLE);
} else {
statusView.setVisibility(View.GONE);
}
}
public void setColor() {
if(lowResMode){
setColorLowRes();
} else if (sharedPrefs.getBoolean("dark", true)) {
setColorDark();
} else {
setColorBright();
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
setColor();
if(layoutSet){
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
invalidate();
}
protected void updateRainbow() {
animationAngle = (animationAngle + 1) % 360;
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
mSgv.getPaint().setShader(shader);
invalidate();
}
private synchronized boolean isAnimated() {
return isAnimated;
}
private synchronized void setIsAnimated(boolean isAnimated) {
this.isAnimated = isAnimated;
}
void startAnimation() {
Log.d("CircleWatchface", "start startAnimation");
Thread animator = new Thread() {
public void run() {
setIsAnimated(true);
for (int i = 0; i <= 8 * 1000 / 40; i++) {
updateRainbow();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mSgv.getPaint().setShader(null);
setIsAnimated(false);
invalidate();
setColor();
System.gc();
}
};
animator.start();
}
protected void setColorLowRes() {
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_Timestamp));
if (chart != null) {
highColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
midColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
gridColour = ContextCompat.getColor(getApplicationContext(), R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark_lowres);
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light_lowres);
pointSize = 2;
setupCharts();
}
}
protected void setColorDark() {
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_Timestamp));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
}
if (chart != null) {
highColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor);
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor);
midColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
gridColour = ContextCompat.getColor(getApplicationContext(), R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light);
pointSize = 2;
setupCharts();
}
}
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_bigchart_time));
statusView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_bigchart_status));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
mAvgDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_mTimestamp1));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_mTimestamp));
}
if (chart != null) {
highColor = ContextCompat.getColor(getApplicationContext(), R.color.light_highColor);
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor);
midColor = ContextCompat.getColor(getApplicationContext(), R.color.light_midColor);
gridColour = ContextCompat.getColor(getApplicationContext(), R.color.light_gridColor);
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light);
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
pointSize = 2;
setupCharts();
}
} else {
setColorDark();
}
}
public void missedReadingAlert() {
int minutes_since = (int) Math.floor(timeSince()/(1000*60));
if(minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
ListenerService.requestData(this); // attempt endTime recover missing data
}
}
public void addToWatchSet(DataMap dataMap) {
ArrayList<DataMap> entries = dataMap.getDataMapArrayList("entries");
if (entries != null) {
bgDataList = new ArrayList<BgWatchData>();
for (DataMap entry : entries) {
double sgv = entry.getDouble("sgvDouble");
double high = entry.getDouble("high");
double low = entry.getDouble("low");
double timestamp = entry.getDouble("timestamp");
bgDataList.add(new BgWatchData(sgv, high, low, timestamp));
}
} else {
double sgv = dataMap.getDouble("sgvDouble");
double high = dataMap.getDouble("high");
double low = dataMap.getDouble("low");
double timestamp = dataMap.getDouble("timestamp");
final int size = bgDataList.size();
if (size > 0) {
if (bgDataList.get(size - 1).timestamp == timestamp)
return; // Ignore duplicates.
}
bgDataList.add(new BgWatchData(sgv, high, low, timestamp));
}
for (int i = 0; i < bgDataList.size(); i++) {
if (bgDataList.get(i).timestamp < (new Date().getTime() - (1000 * 60 * 60 * 5))) {
bgDataList.remove(i); //Get rid of anything more than 5 hours old
break;
}
}
}
public void setupCharts() {
if(bgDataList.size() > 0) { //Dont crash things just because we dont have values, people dont like crashy things
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
if (lowResMode) {
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, tempWatchDataList, basalWatchDataList, pointSize, midColor, gridColour, basalBackgroundColor, basalCenterColor, timeframe);
} else {
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, tempWatchDataList, basalWatchDataList, pointSize, highColor, lowColor, midColor, gridColour, basalBackgroundColor, basalCenterColor, timeframe);
}
chart.setLineChartData(bgGraphBuilder.lineData());
chart.setViewportCalculationEnabled(true);
chart.setMaximumViewport(chart.getMaximumViewport());
} else {
ListenerService.requestData(this);
}
}
}

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps;
/**
* Created by adrian on 18/11/16.
*/
public class BasalWatchData {
public long startTime;
public long endTime;
public double amount;
}

View file

@ -0,0 +1,441 @@
package info.nightscout.androidaps;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.wearable.view.WatchViewStub;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.android.gms.wearable.DataMap;
import com.ustwo.clockwise.common.WatchMode;
import com.ustwo.clockwise.wearable.WatchFace;
import com.ustwo.clockwise.common.WatchFaceTime;
import com.ustwo.clockwise.common.WatchShape;
import java.util.ArrayList;
import java.util.Date;
import lecho.lib.hellocharts.view.LineChartView;
/**
* Created by emmablack on 12/29/14.
*/
public abstract class BaseWatchFace extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
public final static IntentFilter INTENT_FILTER;
public static final long[] vibratePattern = {0,400,300,400,300,400};
public TextView mTime, mSgv, mDirection, mTimestamp, mUploaderBattery, mDelta, mStatus;
public RelativeLayout mRelativeLayout;
public LinearLayout mLinearLayout;
public long sgvLevel = 0;
public int batteryLevel = 1;
public int ageLevel = 1;
public int highColor = Color.YELLOW;
public int lowColor = Color.RED;
public int midColor = Color.WHITE;
public int gridColor = Color.WHITE;
public int basalBackgroundColor = Color.BLUE;
public int basalCenterColor = Color.BLUE;
public boolean lowResMode = false;
public int pointSize = 2;
public boolean layoutSet = false;
public int missed_readings_alert_id = 818;
public BgGraphBuilder bgGraphBuilder;
public LineChartView chart;
public double datetime;
public ArrayList<BgWatchData> bgDataList = new ArrayList<>();
public ArrayList<TempWatchData> tempWatchDataList = new ArrayList<>();
public ArrayList<BasalWatchData> basalWatchDataList = new ArrayList<>();
public PowerManager.WakeLock wakeLock;
// related endTime manual layout
public View layoutView;
private final Point displaySize = new Point();
private int specW, specH;
private LocalBroadcastManager localBroadcastManager;
private MessageReceiver messageReceiver;
protected SharedPreferences sharedPrefs;
private String batteryString = "--";
private String sgvString = "--";
private String externalStatusString = "no status";
private String avgDelta = "";
private String delta = "";
@Override
public void onCreate() {
super.onCreate();
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
display.getSize(displaySize);
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Clock");
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x,
View.MeasureSpec.EXACTLY);
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
View.MeasureSpec.EXACTLY);
sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onLayout(WatchShape shape, Rect screenBounds, WindowInsets screenInsets) {
super.onLayout(shape, screenBounds, screenInsets);
layoutView.onApplyWindowInsets(screenInsets);
}
public void performViewSetup() {
final WatchViewStub stub = (WatchViewStub) layoutView.findViewById(R.id.watch_view_stub);
IntentFilter messageFilter = new IntentFilter(Intent.ACTION_SEND);
messageReceiver = new MessageReceiver();
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(messageReceiver, messageFilter);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
mTime = (TextView) stub.findViewById(R.id.watch_time);
mSgv = (TextView) stub.findViewById(R.id.sgv);
mDirection = (TextView) stub.findViewById(R.id.direction);
mTimestamp = (TextView) stub.findViewById(R.id.timestamp);
mStatus = (TextView) stub.findViewById(R.id.externaltstatus);
mUploaderBattery = (TextView) stub.findViewById(R.id.uploader_battery);
mDelta = (TextView) stub.findViewById(R.id.delta);
mRelativeLayout = (RelativeLayout) stub.findViewById(R.id.main_layout);
mLinearLayout = (LinearLayout) stub.findViewById(R.id.secondary_layout);
chart = (LineChartView) stub.findViewById(R.id.chart);
layoutSet = true;
showAgoRawBattStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
});
ListenerService.requestData(this);
wakeLock.acquire(50);
}
public int ageLevel() {
if(timeSince() <= (1000 * 60 * 12)) {
return 1;
} else {
return 0;
}
}
public double timeSince() {
return System.currentTimeMillis() - datetime;
}
public String readingAge(boolean shortString) {
if (datetime == 0) { return shortString?"--'":"-- Minute ago"; }
int minutesAgo = (int) Math.floor(timeSince()/(1000*60));
if (minutesAgo == 1) {
return minutesAgo + (shortString?"'":" Minute ago");
}
return minutesAgo + (shortString?"'":" Minutes ago");
}
@Override
public void onDestroy() {
if(localBroadcastManager != null && messageReceiver != null){
localBroadcastManager.unregisterReceiver(messageReceiver);}
if (sharedPrefs != null){
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
}
super.onDestroy();
}
static {
INTENT_FILTER = new IntentFilter();
INTENT_FILTER.addAction(Intent.ACTION_TIME_TICK);
INTENT_FILTER.addAction(Intent.ACTION_TIMEZONE_CHANGED);
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
}
@Override
protected void onDraw(Canvas canvas) {
if(layoutSet) {
this.mRelativeLayout.draw(canvas);
Log.d("onDraw", "draw");
}
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
wakeLock.acquire(50);
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BaseWatchFace.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
showAgoRawBattStatus();
if(ageLevel()<=0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
missedReadingAlert();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//data
Bundle bundle = intent.getBundleExtra("data");
if (layoutSet && bundle != null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(50);
sgvLevel = dataMap.getLong("sgvLevel");
batteryLevel = dataMap.getInt("batteryLevel");
datetime = dataMap.getDouble("timestamp");
sgvString = dataMap.getString("sgvString");
batteryString = dataMap.getString("battery");
mSgv.setText(dataMap.getString("sgvString"));
if(ageLevel()<=0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BaseWatchFace.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
mDirection.setText(dataMap.getString("slopeArrow"));
avgDelta = dataMap.getString("avgDelta");
delta = dataMap.getString("delta");
showAgoRawBattStatus();
if (chart != null) {
addToWatchSet(dataMap);
setupCharts();
}
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
}
//status
bundle = intent.getBundleExtra("status");
if (layoutSet && bundle != null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(50);
externalStatusString = dataMap.getString("externalStatusString");
showAgoRawBattStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
}
//basals and temps
bundle = intent.getBundleExtra("basals");
if (layoutSet && bundle != null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(500);
loadBasalsAndTemps(dataMap);
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
}
}
}
private void showAgoRawBattStatus() {
boolean showAvgDelta = sharedPrefs.getBoolean("showAvgDelta", true);
mDelta.setText(delta);
if(showAvgDelta){
mDelta.append(" " + avgDelta);
}
if( mTimestamp == null || mUploaderBattery == null|| mStatus == null){
return;
}
boolean showStatus = sharedPrefs.getBoolean("showExternalStatus", true);
if(showStatus){
//use short forms
mTimestamp.setText(readingAge(true));
mUploaderBattery.setText("U: " + batteryString + "%");
} else {
mTimestamp.setText(readingAge(false));
mUploaderBattery.setText("Uploader: " + batteryString + "%");
}
if (showStatus) {
mStatus.setVisibility(View.VISIBLE);
mStatus.setText("S: " + externalStatusString);
} else {
mStatus.setVisibility(View.GONE);
}
}
public void setColor() {
if(lowResMode){
setColorLowRes();
} else if (sharedPrefs.getBoolean("dark", true)) {
setColorDark();
} else {
setColorBright();
}
}
protected void onWatchModeChanged(WatchMode watchMode) {
if(lowResMode ^ isLowRes(watchMode)){ //if there was a change in lowResMode
lowResMode = isLowRes(watchMode);
setColor();
} else if (! sharedPrefs.getBoolean("dark", true)){
//in bright mode: different colours if active:
setColor();
}
}
private boolean isLowRes(WatchMode watchMode) {
return (watchMode == WatchMode.LOW_BIT) || (watchMode == WatchMode.LOW_BIT_BURN_IN) || (watchMode == WatchMode.LOW_BIT_BURN_IN);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
setColor();
if(layoutSet){
showAgoRawBattStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
invalidate();
}
protected abstract void setColorDark();
protected abstract void setColorBright();
protected abstract void setColorLowRes();
public void missedReadingAlert() {
int minutes_since = (int) Math.floor(timeSince()/(1000*60));
if(minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
ListenerService.requestData(this); // attempt endTime recover missing data
}
}
public void addToWatchSet(DataMap dataMap) {
ArrayList<DataMap> entries = dataMap.getDataMapArrayList("entries");
if (entries != null) {
bgDataList = new ArrayList<BgWatchData>();
for (DataMap entry : entries) {
double sgv = entry.getDouble("sgvDouble");
double high = entry.getDouble("high");
double low = entry.getDouble("low");
double timestamp = entry.getDouble("timestamp");
bgDataList.add(new BgWatchData(sgv, high, low, timestamp));
}
} else {
double sgv = dataMap.getDouble("sgvDouble");
double high = dataMap.getDouble("high");
double low = dataMap.getDouble("low");
double timestamp = dataMap.getDouble("timestamp");
final int size = bgDataList.size();
if (size > 0) {
if (bgDataList.get(size - 1).timestamp == timestamp)
return; // Ignore duplicates.
}
bgDataList.add(new BgWatchData(sgv, high, low, timestamp));
}
for (int i = 0; i < bgDataList.size(); i++) {
if (bgDataList.get(i).timestamp < (new Date().getTime() - (1000 * 60 * 60 * 5))) {
bgDataList.remove(i); //Get rid of anything more than 5 hours old
break;
}
}
}
public void setupCharts() {
if(bgDataList.size() > 0) { //Dont crash things just because we dont have values, people dont like crashy things
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
if (lowResMode) {
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, tempWatchDataList, basalWatchDataList, pointSize, midColor, gridColor, basalBackgroundColor, basalCenterColor, timeframe);
} else {
bgGraphBuilder = new BgGraphBuilder(getApplicationContext(), bgDataList, tempWatchDataList, basalWatchDataList, pointSize, highColor, lowColor, midColor, gridColor, basalBackgroundColor, basalCenterColor, timeframe);
}
chart.setLineChartData(bgGraphBuilder.lineData());
chart.setViewportCalculationEnabled(true);
chart.setMaximumViewport(chart.getMaximumViewport());
} else {
ListenerService.requestData(this);
}
}
private void loadBasalsAndTemps(DataMap dataMap) {
ArrayList<DataMap> temps = dataMap.getDataMapArrayList("temps");
if (temps != null) {
tempWatchDataList = new ArrayList<>();
for (DataMap temp : temps) {
TempWatchData twd = new TempWatchData();
twd.startTime = temp.getLong("starttime");
twd.startBasal = temp.getDouble("startBasal");
twd.endTime = temp.getLong("endtime");
twd.endBasal = temp.getDouble("endbasal");
twd.amount = temp.getDouble("amount");
tempWatchDataList.add(twd);
}
}
ArrayList<DataMap> basals = dataMap.getDataMapArrayList("basals");
if (basals != null) {
basalWatchDataList = new ArrayList<>();
for (DataMap basal : basals) {
BasalWatchData bwd = new BasalWatchData();
bwd.startTime = basal.getLong("starttime");
bwd.endTime = basal.getLong("endtime");
bwd.amount = basal.getDouble("amount");
basalWatchDataList.add(bwd);
}
}
}
}

View file

@ -0,0 +1,354 @@
package info.nightscout.androidaps;
import android.content.Context;
import android.graphics.DashPathEffect;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.text.format.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
/**
* Created by emmablack on 11/15/14.
*/
public class BgGraphBuilder {
private ArrayList<BasalWatchData> basalWatchDataList;
public List<TempWatchData> tempWatchDataList;
private int timespan;
public double end_time;
public double start_time;
public double fuzzyTimeDenom = (1000 * 60 * 1);
public Context context;
public double highMark;
public double lowMark;
public List<BgWatchData> bgDataList = new ArrayList<BgWatchData>();
public int pointSize;
public int highColor;
public int lowColor;
public int midColor;
public int gridColour;
public int basalCenterColor;
public int basalBackgroundColor;
public boolean singleLine = false;
private double endHour;
private List<PointValue> inRangeValues = new ArrayList<PointValue>();
private List<PointValue> highValues = new ArrayList<PointValue>();
private List<PointValue> lowValues = new ArrayList<PointValue>();
public Viewport viewport;
//used for low resolution screen.
public BgGraphBuilder(Context context, List<BgWatchData> aBgList, List<TempWatchData> tempWatchDataList, ArrayList<BasalWatchData> basalWatchDataList, int aPointSize, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int timespan) {
end_time = new Date().getTime() + (1000 * 60 * 6 * timespan); //Now plus 30 minutes padding (for 5 hours. Less if less.)
start_time = new Date().getTime() - (1000 * 60 * 60 * timespan); //timespan hours ago
this.bgDataList = aBgList;
this.context = context;
this.highMark = aBgList.get(aBgList.size() - 1).high;
this.lowMark = aBgList.get(aBgList.size() - 1).low;
this.pointSize = aPointSize;
this.singleLine = false;
this.midColor = aMidColor;
this.lowColor = aMidColor;
this.highColor = aMidColor;
this.timespan = timespan;
this.tempWatchDataList = tempWatchDataList;
this.basalWatchDataList = basalWatchDataList;
this.gridColour = gridColour;
this.basalCenterColor = basalCenterColor;
this.basalBackgroundColor = basalBackgroundColor;
}
public BgGraphBuilder(Context context, List<BgWatchData> aBgList, List<TempWatchData> tempWatchDataList, ArrayList<BasalWatchData> basalWatchDataList, int aPointSize, int aHighColor, int aLowColor, int aMidColor, int gridColour, int basalBackgroundColor, int basalCenterColor, int timespan) {
end_time = new Date().getTime() + (1000 * 60 * 6 * timespan); //Now plus 30 minutes padding (for 5 hours. Less if less.)
start_time = new Date().getTime() - (1000 * 60 * 60 * timespan); //timespan hours ago
this.bgDataList = aBgList;
this.context = context;
this.highMark = aBgList.get(aBgList.size() - 1).high;
this.lowMark = aBgList.get(aBgList.size() - 1).low;
this.pointSize = aPointSize;
this.highColor = aHighColor;
this.lowColor = aLowColor;
this.midColor = aMidColor;
this.timespan = timespan;
this.tempWatchDataList = tempWatchDataList;
this.basalWatchDataList = basalWatchDataList;
this.gridColour = gridColour;
this.basalCenterColor = basalCenterColor;
this.basalBackgroundColor = basalBackgroundColor;
}
public LineChartData lineData() {
LineChartData lineData = new LineChartData(defaultLines());
lineData.setAxisYLeft(yAxis());
lineData.setAxisXBottom(xAxis());
return lineData;
}
public List<Line> defaultLines() {
addBgReadingValues();
List<Line> lines = new ArrayList<Line>();
lines.add(highLine());
lines.add(lowLine());
lines.add(inRangeValuesLine());
lines.add(lowValuesLine());
lines.add(highValuesLine());
double minChart = lowMark;
double maxChart = highMark;
for ( BgWatchData bgd:bgDataList) {
if(bgd.sgv > maxChart){
maxChart = bgd.sgv;
}
if(bgd.sgv < minChart){
minChart = bgd.sgv;
}
}
double maxBasal = 0.1;
for (BasalWatchData bwd: basalWatchDataList) {
if(bwd.amount > maxBasal){
maxBasal = bwd.amount;
}
}
double maxTemp = maxBasal;
for (TempWatchData twd: tempWatchDataList) {
if(twd.amount > maxTemp){
maxTemp = twd.amount;
}
}
double factor = (maxChart-minChart)/maxTemp;
// in case basal is the highest, don't paint it totally at the top.
factor = Math.min(factor, ((maxChart-minChart)/maxBasal)*(2/3d));
boolean highlight = PreferenceManager
.getDefaultSharedPreferences(context)
.getBoolean("highlight_basals", false);
for (TempWatchData twd: tempWatchDataList) {
if(twd.endTime > start_time) {
lines.add(tempValuesLine(twd, (float) minChart, factor, false, highlight?3:2));
if(highlight){
lines.add(tempValuesLine(twd, (float) minChart, factor, true, 1));
}
}
}
lines.add(basalLine((float) minChart, factor, highlight));
return lines;
}
private Line basalLine(float offset, double factor, boolean highlight) {
List<PointValue> pointValues = new ArrayList<PointValue>();
for (BasalWatchData bwd: basalWatchDataList) {
if(bwd.endTime > start_time) {
long begin = (long) Math.max(start_time, bwd.startTime);
pointValues.add(new PointValue(fuzz(begin), offset + (float) (factor * bwd.amount)));
pointValues.add(new PointValue(fuzz(bwd.endTime), offset + (float) (factor * bwd.amount)));
}
}
Line basalLine = new Line(pointValues);
basalLine.setHasPoints(false);
basalLine.setColor(basalCenterColor);
basalLine.setPathEffect(new DashPathEffect(new float[]{4f, 3f}, 4f));
basalLine.setStrokeWidth(highlight?2:1);
return basalLine;
}
public Line highValuesLine() {
Line highValuesLine = new Line(highValues);
highValuesLine.setColor(highColor);
highValuesLine.setHasLines(false);
highValuesLine.setPointRadius(pointSize);
highValuesLine.setHasPoints(true);
return highValuesLine;
}
public Line lowValuesLine() {
Line lowValuesLine = new Line(lowValues);
lowValuesLine.setColor(lowColor);
lowValuesLine.setHasLines(false);
lowValuesLine.setPointRadius(pointSize);
lowValuesLine.setHasPoints(true);
return lowValuesLine;
}
public Line inRangeValuesLine() {
Line inRangeValuesLine = new Line(inRangeValues);
inRangeValuesLine.setColor(midColor);
if(singleLine) {
inRangeValuesLine.setHasLines(true);
inRangeValuesLine.setHasPoints(false);
inRangeValuesLine.setStrokeWidth(pointSize);
} else {
inRangeValuesLine.setPointRadius(pointSize);
inRangeValuesLine.setHasPoints(true);
inRangeValuesLine.setHasLines(false);
}
return inRangeValuesLine;
}
public Line tempValuesLine(TempWatchData twd, float offset, double factor, boolean isHighlightLine, int strokeWidth) {
List<PointValue> lineValues = new ArrayList<PointValue>();
long begin = (long) Math.max(start_time, twd.startTime);
lineValues.add(new PointValue(fuzz(begin), offset + (float) (factor * twd.startBasal)));
lineValues.add(new PointValue(fuzz(begin), offset + (float) (factor * twd.amount)));
lineValues.add(new PointValue(fuzz(twd.endTime), offset + (float) (factor * twd.amount)));
lineValues.add(new PointValue(fuzz(twd.endTime), offset + (float) (factor * twd.endBasal)));
Line valueLine = new Line(lineValues);
valueLine.setHasPoints(false);
if (isHighlightLine){
valueLine.setColor(basalCenterColor);
valueLine.setStrokeWidth(1);
}else {
valueLine.setColor(basalBackgroundColor);
valueLine.setStrokeWidth(strokeWidth);
}
return valueLine;
}
private void addBgReadingValues() {
if(singleLine) {
for (BgWatchData bgReading : bgDataList) {
if(bgReading.timestamp > start_time) {
if (bgReading.sgv >= 400) {
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 400));
} else if (bgReading.sgv >= highMark) {
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
} else if (bgReading.sgv >= lowMark) {
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
} else if (bgReading.sgv >= 40) {
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
} else if (bgReading.sgv >= 11) {
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 40));
}
}
}
} else {
for (BgWatchData bgReading : bgDataList) {
if (bgReading.timestamp > start_time) {
if (bgReading.sgv >= 400) {
highValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 400));
} else if (bgReading.sgv >= highMark) {
highValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
} else if (bgReading.sgv >= lowMark) {
inRangeValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
} else if (bgReading.sgv >= 40) {
lowValues.add(new PointValue(fuzz(bgReading.timestamp), (float) bgReading.sgv));
} else if (bgReading.sgv >= 11) {
lowValues.add(new PointValue(fuzz(bgReading.timestamp), (float) 40));
}
}
}
}
}
public Line highLine() {
List<PointValue> highLineValues = new ArrayList<PointValue>();
highLineValues.add(new PointValue(fuzz(start_time), (float) highMark));
highLineValues.add(new PointValue(fuzz(end_time), (float) highMark));
Line highLine = new Line(highLineValues);
highLine.setHasPoints(false);
highLine.setStrokeWidth(1);
highLine.setColor(highColor);
return highLine;
}
public Line lowLine() {
List<PointValue> lowLineValues = new ArrayList<PointValue>();
lowLineValues.add(new PointValue(fuzz(start_time), (float) lowMark));
lowLineValues.add(new PointValue(fuzz(end_time), (float) lowMark));
Line lowLine = new Line(lowLineValues);
lowLine.setHasPoints(false);
lowLine.setColor(lowColor);
lowLine.setStrokeWidth(1);
return lowLine;
}
/////////AXIS RELATED//////////////
public Axis yAxis() {
Axis yAxis = new Axis();
yAxis.setAutoGenerated(true);
List<AxisValue> axisValues = new ArrayList<AxisValue>();
yAxis.setValues(axisValues);
yAxis.setHasLines(false);
yAxis.setLineColor(gridColour);
return yAxis;
}
public Axis xAxis() {
final boolean is24 = DateFormat.is24HourFormat(context);
Axis xAxis = new Axis();
xAxis.setAutoGenerated(false);
List<AxisValue> xAxisValues = new ArrayList<AxisValue>();
GregorianCalendar now = new GregorianCalendar();
GregorianCalendar today = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH));
SimpleDateFormat timeFormat = new SimpleDateFormat(is24? "HH" : "h a");
timeFormat.setTimeZone(TimeZone.getDefault());
double start_hour = today.getTime().getTime();
double timeNow = new Date().getTime();
for (int l = 0; l <= 24; l++) {
if ((start_hour + (60000 * 60 * (l))) < timeNow) {
if ((start_hour + (60000 * 60 * (l + 1))) >= timeNow) {
endHour = start_hour + (60000 * 60 * (l));
l = 25;
}
}
}
//Display current time on the graph
SimpleDateFormat longTimeFormat = new SimpleDateFormat(is24? "HH:mm" : "h:mm a");
xAxisValues.add(new AxisValue(fuzz(timeNow), (longTimeFormat.format(timeNow)).toCharArray()));
//Add whole hours endTime the axis (as long as they are more than 15 mins away from the current time)
for (int l = 0; l <= 24; l++) {
double timestamp = endHour - (60000 * 60 * l);
if((timestamp - timeNow < 0) && (timestamp > start_time)) {
if(Math.abs(timestamp - timeNow) > (1000 * 60 * 8 * timespan)){
xAxisValues.add(new AxisValue(fuzz(timestamp), (timeFormat.format(timestamp)).toCharArray()));
}else {
xAxisValues.add(new AxisValue(fuzz(timestamp), "".toCharArray()));
}
}
}
xAxis.setValues(xAxisValues);
xAxis.setTextSize(10);
xAxis.setHasLines(true);
xAxis.setLineColor(gridColour);
xAxis.setTextColor(gridColour);
return xAxis;
}
public float fuzz(double value) {
return (float) Math.round(value / fuzzyTimeDenom);
}
}

View file

@ -0,0 +1,39 @@
package info.nightscout.androidaps;
/**
* Created by emmablack on 1/7/15.
*/
public class BgWatchData implements Comparable<BgWatchData>{
public double sgv;
public double high;
public double low;
public double timestamp;
public BgWatchData(double aSgv, double aHigh, double aLow, double aTimestamp) {
this.sgv = aSgv;
this.high = aHigh;
this.low = aLow;
this.timestamp = aTimestamp;
}
@Override
public boolean equals(Object that){
if(! (that instanceof BgWatchData)){
return false;
}
return this.timestamp == ((BgWatchData) that).timestamp;
}
@Override
public int hashCode(){
return (int) (timestamp%Integer.MAX_VALUE);
}
@Override
public int compareTo(BgWatchData that) {
// reverse order endTime get latest first
if(this.timestamp < that.timestamp) return 1;
if(this.timestamp > that.timestamp) return -1;
return 0;
}
}

View file

@ -0,0 +1,703 @@
package info.nightscout.androidaps;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.wearable.DataMap;
import com.ustwo.clockwise.wearable.WatchFace;
import com.ustwo.clockwise.common.WatchFaceTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.TreeSet;
public class CircleWatchface extends WatchFace implements SharedPreferences.OnSharedPreferenceChangeListener {
public final float PADDING = 20f;
public final float CIRCLE_WIDTH = 10f;
public final int BIG_HAND_WIDTH = 16;
public final int SMALL_HAND_WIDTH = 8;
public final int NEAR = 2; //how near do the hands have endTime be endTime activate overlapping mode
public final boolean ALWAYS_HIGHLIGT_SMALL = false;
//variables for time
private float angleBig = 0f;
private float angleSMALL = 0f;
private int hour, minute;
private int color;
private Paint circlePaint = new Paint();
private Paint removePaint = new Paint();
private RectF rect, rectDelete;
private boolean overlapping;
private int animationAngle = 0;
private boolean isAnimated = false;
public Point displaySize = new Point();
private MessageReceiver messageReceiver = new MessageReceiver();
private int sgvLevel = 0;
private String sgvString = "999";
private String statusString = "no status";
private int batteryLevel = 0;
private double datetime = 0;
private String direction = "";
private String delta = "";
private String avgDelta = "";
public TreeSet<BgWatchData> bgDataList = new TreeSet<BgWatchData>();
private View layoutView;
private int specW;
private int specH;
private View myLayout;
protected SharedPreferences sharedPrefs;
@Override
public void onCreate() {
super.onCreate();
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CreateWakelock");
wakeLock.acquire(30000);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
display.getSize(displaySize);
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x,
View.MeasureSpec.EXACTLY);
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
View.MeasureSpec.EXACTLY);
sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
//register Message Receiver
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, new IntentFilter(Intent.ACTION_SEND));
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myLayout = inflater.inflate(R.layout.modern_layout, null);
prepareLayout();
prepareDrawTime();
//ListenerService.requestData(this); //usually connection is not set up yet
wakeLock.release();
}
@Override
public void onDestroy() {
if (messageReceiver != null) {
LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver);
}
if (sharedPrefs != null) {
sharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
}
super.onDestroy();
}
@Override
protected synchronized void onDraw(Canvas canvas) {
Log.d("CircleWatchface", "start onDraw");
canvas.drawColor(getBackgroundColor());
drawTime(canvas);
drawOtherStuff(canvas);
myLayout.draw(canvas);
}
private synchronized void prepareLayout() {
Log.d("CircleWatchface", "start startPrepareLayout");
// prepare fields
TextView textView = null;
textView = (TextView) myLayout.findViewById(R.id.sgvString);
if (sharedPrefs.getBoolean("showBG", true)) {
textView.setVisibility(View.VISIBLE);
textView.setText(getSgvString());
textView.setTextColor(getTextColor());
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.INVISIBLE);
}
textView = (TextView) myLayout.findViewById(R.id.statusString);
if (sharedPrefs.getBoolean("showExternalStatus", true)) {
textView.setVisibility(View.VISIBLE);
textView.setText(getStatusString());
textView.setTextColor(getTextColor());
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.GONE);
}
textView = (TextView) myLayout.findViewById(R.id.agoString);
if (sharedPrefs.getBoolean("showAgo", true)) {
textView.setVisibility(View.VISIBLE);
if (sharedPrefs.getBoolean("showBigNumbers", false)) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 26);
} else {
((TextView) myLayout.findViewById(R.id.agoString)).setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
}
textView.setText(getMinutes());
textView.setTextColor(getTextColor());
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.INVISIBLE);
}
textView = (TextView) myLayout.findViewById(R.id.deltaString);
if (sharedPrefs.getBoolean("showDelta", true)) {
textView.setVisibility(View.VISIBLE);
textView.setText(getDelta());
textView.setTextColor(getTextColor());
if (sharedPrefs.getBoolean("showBigNumbers", false)) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
} else {
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
}
if(sharedPrefs.getBoolean("showAvgDelta", true)){
textView.append(" " + getAvgDelta());
}
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.INVISIBLE);
}
myLayout.measure(specW, specH);
myLayout.layout(0, 0, myLayout.getMeasuredWidth(),
myLayout.getMeasuredHeight());
}
public String getMinutes() {
String minutes = "--\'";
if (getDatetime() != 0) {
minutes = ((int) Math.floor((System.currentTimeMillis() - getDatetime()) / 60000)) + "\'";
}
return minutes;
}
private void drawTime(Canvas canvas) {
//draw circle
circlePaint.setColor(color);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
canvas.drawArc(rect, 0, 360, false, circlePaint);
//"remove" hands from circle
removePaint.setStrokeWidth(CIRCLE_WIDTH * 3);
canvas.drawArc(rectDelete, angleBig, (float) BIG_HAND_WIDTH, false, removePaint);
canvas.drawArc(rectDelete, angleSMALL, (float) SMALL_HAND_WIDTH, false, removePaint);
if (overlapping) {
//add small hand with extra
circlePaint.setStrokeWidth(CIRCLE_WIDTH * 2);
circlePaint.setColor(color);
canvas.drawArc(rect, angleSMALL, (float) SMALL_HAND_WIDTH, false, circlePaint);
//remove inner part of hands
removePaint.setStrokeWidth(CIRCLE_WIDTH);
canvas.drawArc(rect, angleBig, (float) BIG_HAND_WIDTH, false, removePaint);
canvas.drawArc(rect, angleSMALL, (float) SMALL_HAND_WIDTH, false, removePaint);
}
}
private synchronized void prepareDrawTime() {
Log.d("CircleWatchface", "start prepareDrawTime");
hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch (getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
if (isAnimated()) {
//Animation matrix:
int[] rainbow = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE
, Color.CYAN};
Shader shader = new LinearGradient(0, 0, 0, 20, rainbow,
null, Shader.TileMode.MIRROR);
Matrix matrix = new Matrix();
matrix.setRotate(animationAngle);
shader.setLocalMatrix(matrix);
circlePaint.setShader(shader);
} else {
circlePaint.setShader(null);
}
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
;
rect = new RectF(PADDING, PADDING, (float) (displaySize.x - PADDING), (float) (displaySize.y - PADDING));
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, (float) (displaySize.x - PADDING + CIRCLE_WIDTH / 2), (float) (displaySize.y - PADDING + CIRCLE_WIDTH / 2));
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
Log.d("CircleWatchface", "end prepareDrawTime");
}
synchronized void animationStep() {
animationAngle = (animationAngle + 1) % 360;
prepareDrawTime();
invalidate();
}
private boolean areOverlapping(float aBegin, float aEnd, float bBegin, float bEnd) {
return
aBegin <= bBegin && aEnd >= bBegin ||
aBegin <= bBegin && (bEnd > 360) && bEnd % 360 > aBegin ||
bBegin <= aBegin && bEnd >= aBegin ||
bBegin <= aBegin && aEnd > 360 && aEnd % 360 > bBegin;
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (oldTime.hasMinuteChanged(newTime)) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TimeChangedWakelock");
wakeLock.acquire(30000);
/*Preparing the layout just on every minute tick:
* - hopefully better battery life
* - drawback: might update the minutes since last reading up endTime one minute late*/
prepareLayout();
prepareDrawTime();
invalidate(); //redraw the time
wakeLock.release();
}
}
// defining color for dark and bright
public int getLowColor() {
if (sharedPrefs.getBoolean("dark", true)) {
return Color.argb(255, 255, 120, 120);
} else {
return Color.argb(255, 255, 80, 80);
}
}
public int getInRangeColor() {
if (sharedPrefs.getBoolean("dark", false)) {
return Color.argb(255, 120, 255, 120);
} else {
return Color.argb(255, 0, 240, 0);
}
}
public int getHighColor() {
if (sharedPrefs.getBoolean("dark", false)) {
return Color.argb(255, 255, 255, 120);
} else {
return Color.argb(255, 255, 200, 0);
}
}
public int getBackgroundColor() {
if (sharedPrefs.getBoolean("dark", false)) {
return Color.BLACK;
} else {
return Color.WHITE;
}
}
public int getTextColor() {
if (sharedPrefs.getBoolean("dark", false)) {
return Color.WHITE;
} else {
return Color.BLACK;
}
}
public void drawOtherStuff(Canvas canvas) {
Log.d("CircleWatchface", "start onDrawOtherStuff. bgDataList.size(): " + bgDataList.size());
if (isAnimated()) return; // too many repaints when animated
if (sharedPrefs.getBoolean("showRingHistory", false)) {
//Perfect low and High indicators
if (bgDataList.size() > 0) {
addIndicator(canvas, 100, Color.LTGRAY);
addIndicator(canvas, (float) bgDataList.iterator().next().low, getLowColor());
addIndicator(canvas, (float) bgDataList.iterator().next().high, getHighColor());
if (sharedPrefs.getBoolean("softRingHistory", true)) {
for (BgWatchData data : bgDataList) {
addReadingSoft(canvas, data);
}
} else {
for (BgWatchData data : bgDataList) {
addReading(canvas, data);
}
}
}
}
}
public int holdInMemory() {
return 6;
}
//getters & setters
private synchronized int getSgvLevel() {
return sgvLevel;
}
private synchronized void setSgvLevel(int sgvLevel) {
this.sgvLevel = sgvLevel;
}
private synchronized int getBatteryLevel() {
return batteryLevel;
}
private synchronized void setBatteryLevel(int batteryLevel) {
this.batteryLevel = batteryLevel;
}
private synchronized double getDatetime() {
return datetime;
}
private synchronized void setDatetime(double datetime) {
this.datetime = datetime;
}
private synchronized String getDirection() {
return direction;
}
private void setDirection(String direction) {
this.direction = direction;
}
String getSgvString() {
return sgvString;
}
void setSgvString(String sgvString) {
this.sgvString = sgvString;
}
String getStatusString() {
return statusString;
}
void setStatusString(String statusString) {
this.statusString = statusString;
}
public String getDelta() {
return delta;
}
private void setDelta(String delta) {
this.delta = delta;
}
private String getAvgDelta() {
return avgDelta;
}
private void setAvgDelta(String avgDelta) {
this.avgDelta = avgDelta;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
prepareDrawTime();
prepareLayout();
invalidate();
}
private synchronized boolean isAnimated() {
return isAnimated;
}
private synchronized void setIsAnimated(boolean isAnimated) {
this.isAnimated = isAnimated;
}
void startAnimation() {
Log.d("CircleWatchface", "start startAnimation");
Thread animator = new Thread() {
public void run() {
setIsAnimated(true);
for (int i = 0; i <= 8 * 1000 / 40; i++) {
animationStep();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setIsAnimated(false);
prepareDrawTime();
invalidate();
System.gc();
}
};
animator.start();
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire(30000);
Bundle bundle = intent.getBundleExtra("data");
if (bundle!= null) {
DataMap dataMap = DataMap.fromBundle(bundle);
setSgvLevel((int) dataMap.getLong("sgvLevel"));
Log.d("CircleWatchface", "sgv level : " + getSgvLevel());
setSgvString(dataMap.getString("sgvString"));
Log.d("CircleWatchface", "sgv string : " + getSgvString());
setDelta(dataMap.getString("delta"));
setAvgDelta(dataMap.getString("avgDelta"));
setDatetime(dataMap.getDouble("timestamp"));
addToWatchSet(dataMap);
//start animation?
// dataMap.getDataMapArrayList("entries") == null -> not on "resend data".
if (sharedPrefs.getBoolean("animation", false) && dataMap.getDataMapArrayList("entries") == null && (getSgvString().equals("100") || getSgvString().equals("5.5") || getSgvString().equals("5,5"))) {
startAnimation();
}
prepareLayout();
prepareDrawTime();
invalidate();
}
//status
bundle = intent.getBundleExtra("status");
if (bundle != null) {
DataMap dataMap = DataMap.fromBundle(bundle);
wakeLock.acquire(50);
setStatusString(dataMap.getString("externalStatusString"));
prepareLayout();
prepareDrawTime();
invalidate();
}
wakeLock.release();
}
}
public synchronized void addToWatchSet(DataMap dataMap) {
if(!sharedPrefs.getBoolean("showRingHistory", false)){
bgDataList.clear();
return;
}
Log.d("CircleWatchface", "start addToWatchSet");
ArrayList<DataMap> entries = dataMap.getDataMapArrayList("entries");
if (entries == null) {
double sgv = dataMap.getDouble("sgvDouble");
double high = dataMap.getDouble("high");
double low = dataMap.getDouble("low");
double timestamp = dataMap.getDouble("timestamp");
bgDataList.add(new BgWatchData(sgv, high, low, timestamp));
} else if (!sharedPrefs.getBoolean("animation", false)) {
// don't load history at once if animations are set (less resource consumption)
Log.d("addToWatchSet", "entries.size(): " + entries.size());
for (DataMap entry : entries) {
double sgv = entry.getDouble("sgvDouble");
double high = entry.getDouble("high");
double low = entry.getDouble("low");
double timestamp = entry.getDouble("timestamp");
bgDataList.add(new BgWatchData(sgv, high, low, timestamp));
}
} else
Log.d("addToWatchSet", "start removing bgDataList.size(): " + bgDataList.size());
HashSet removeSet = new HashSet();
double threshold = (new Date().getTime() - (1000 * 60 * 5 * holdInMemory()));
for (BgWatchData data : bgDataList) {
if (data.timestamp < threshold) {
removeSet.add(data);
}
}
bgDataList.removeAll(removeSet);
Log.d("addToWatchSet", "after bgDataList.size(): " + bgDataList.size());
removeSet = null;
System.gc();
}
public int darken(int color, double fraction) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
red = darkenColor(red, fraction);
green = darkenColor(green, fraction);
blue = darkenColor(blue, fraction);
int alpha = Color.alpha(color);
return Color.argb(alpha, red, green, blue);
}
private int darkenColor(int color, double fraction) {
//if (sharedPrefs.getBoolean("dark", false)) {
return (int) Math.max(color - (color * fraction), 0);
//}
// return (int)Math.min(color + (color * fraction), 255);
}
public void addArch(Canvas canvas, float offset, int color, float size) {
Paint paint = new Paint();
paint.setColor(color);
RectF rectTemp = new RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, (displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2), (displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2));
canvas.drawArc(rectTemp, 270, size, true, paint);
}
public void addArch(Canvas canvas, float start, float offset, int color, float size) {
Paint paint = new Paint();
paint.setColor(color);
RectF rectTemp = new RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, (displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2), (displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2));
canvas.drawArc(rectTemp, start + 270, size, true, paint);
}
public void addIndicator(Canvas canvas, float bg, int color) {
float convertedBg;
convertedBg = bgToAngle(bg);
convertedBg += 270;
Paint paint = new Paint();
paint.setColor(color);
float offset = 9;
RectF rectTemp = new RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, (displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2), (displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2));
canvas.drawArc(rectTemp, convertedBg, 2, true, paint);
}
private float bgToAngle(float bg) {
if (bg > 100) {
return (((bg - 100f) / 300f) * 225f) + 135;
} else {
return ((bg / 100) * 135);
}
}
public void addReadingSoft(Canvas canvas, BgWatchData entry) {
Log.d("CircleWatchface", "addReadingSoft");
double size;
int color = Color.LTGRAY;
if (sharedPrefs.getBoolean("dark", false)) {
color = Color.DKGRAY;
}
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
float offset = (float) Math.max(1, Math.ceil((new Date().getTime() - entry.timestamp) / (1000 * 60 * 5)));
size = bgToAngle((float) entry.sgv);
addArch(canvas, offset * offsetMultiplier + 10, color, (float) size);
addArch(canvas, (float) size, offset * offsetMultiplier + 10, getBackgroundColor(), (float) (360 - size));
addArch(canvas, (offset + .8f) * offsetMultiplier + 10, getBackgroundColor(), 360);
}
public void addReading(Canvas canvas, BgWatchData entry) {
Log.d("CircleWatchface", "addReading");
double size;
int color = Color.LTGRAY;
int indicatorColor = Color.DKGRAY;
if (sharedPrefs.getBoolean("dark", false)) {
color = Color.DKGRAY;
indicatorColor = Color.LTGRAY;
}
int barColor = Color.GRAY;
if (entry.sgv >= entry.high) {
indicatorColor = getHighColor();
barColor = darken(getHighColor(), .5);
} else if (entry.sgv <= entry.low) {
indicatorColor = getLowColor();
barColor = darken(getLowColor(), .5);
}
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
float offset = (float) Math.max(1, Math.ceil((new Date().getTime() - entry.timestamp) / (1000 * 60 * 5)));
size = bgToAngle((float) entry.sgv);
addArch(canvas, offset * offsetMultiplier + 11, barColor, (float) size - 2); // Dark Color Bar
addArch(canvas, (float) size - 2, offset * offsetMultiplier + 11, indicatorColor, 2f); // Indicator at end of bar
addArch(canvas, (float) size, offset * offsetMultiplier + 11, color, (float) (360f - size)); // Dark fill
addArch(canvas, (offset + .8f) * offsetMultiplier + 11, getBackgroundColor(), 360);
}
}

View file

@ -0,0 +1,160 @@
package info.nightscout.androidaps;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
public class Home extends BaseWatchFace {
private long chartTapTime = 0;
@Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_home, null);
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
if (tapType == TAP_TYPE_TAP&&
x >=chart.getLeft() &&
x <= chart.getRight()&&
y >= chart.getTop() &&
y <= chart.getBottom()){
if (eventTime - chartTapTime < 800){
changeChartTimeframe();
}
chartTapTime = eventTime;
}
}
private void changeChartTimeframe() {
int timeframe = Integer.parseInt(sharedPrefs.getString("chart_timeframe", "3"));
timeframe = (timeframe%5) + 1;
sharedPrefs.edit().putString("chart_timeframe", "" + timeframe).commit();
}
@Override
protected WatchFaceStyle getWatchFaceStyle(){
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
protected void setColorDark() {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_statusView));
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTimestamp1_home));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
}
if (batteryLevel == 1) {
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBattery));
} else {
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBatteryEmpty));
}
mStatus.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mStatus_home));
if (chart != null) {
highColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor);
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor);
midColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
gridColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light);
pointSize = 2;
setupCharts();
}
}
protected void setColorLowRes() {
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_Timestamp));
if (chart != null) {
highColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
midColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor);
gridColor = ContextCompat.getColor(getApplicationContext(), R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark_lowres);
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light_lowres);
pointSize = 2;
setupCharts();
}
}
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_stripe_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(Color.WHITE);
} else {
mTimestamp.setTextColor(Color.RED);
}
if (batteryLevel == 1) {
mUploaderBattery.setTextColor(Color.WHITE);
} else {
mUploaderBattery.setTextColor(Color.RED);
}
mStatus.setTextColor(Color.WHITE);
mTime.setTextColor(Color.BLACK);
if (chart != null) {
highColor = ContextCompat.getColor(getApplicationContext(), R.color.light_highColor);
lowColor = ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor);
midColor = ContextCompat.getColor(getApplicationContext(), R.color.light_midColor);
gridColor = ContextCompat.getColor(getApplicationContext(), R.color.light_gridColor);
basalBackgroundColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_light);
basalCenterColor = ContextCompat.getColor(getApplicationContext(), R.color.basal_dark);
pointSize = 2;
setupCharts();
}
} else {
setColorDark();
}
}
}

View file

@ -0,0 +1,121 @@
package info.nightscout.androidaps;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
public class LargeHome extends BaseWatchFace {
@Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_home_large, null);
performViewSetup();
}
@Override
protected void setColorDark(){
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mLinearLayout));
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTimestamp1_home));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_TimestampOld));
}
if (batteryLevel == 1) {
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBattery));
} else {
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBatteryEmpty));
}
mStatus.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mStatus_home));
}
@Override
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_stripe_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.light_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(Color.WHITE);
} else {
mTimestamp.setTextColor(Color.RED);
}
if (batteryLevel == 1) {
mUploaderBattery.setTextColor(Color.WHITE);
} else {
mUploaderBattery.setTextColor(Color.RED);
}
mStatus.setTextColor(Color.WHITE);
mTime.setTextColor(Color.BLACK);
} else {
mRelativeLayout.setBackgroundColor(Color.BLACK);
mLinearLayout.setBackgroundColor(Color.LTGRAY);
if (sgvLevel == 1) {
mSgv.setTextColor(Color.YELLOW);
mDirection.setTextColor(Color.YELLOW);
mDelta.setTextColor(Color.YELLOW);
} else if (sgvLevel == 0) {
mSgv.setTextColor(Color.WHITE);
mDirection.setTextColor(Color.WHITE);
mDelta.setTextColor(Color.WHITE);
} else if (sgvLevel == -1) {
mSgv.setTextColor(Color.RED);
mDirection.setTextColor(Color.RED);
mDelta.setTextColor(Color.RED);
}
mUploaderBattery.setTextColor(Color.BLACK);
mTimestamp.setTextColor(Color.BLACK);
mStatus.setTextColor(Color.BLACK);
mTime.setTextColor(Color.WHITE);
}
}
@Override
protected void setColorLowRes() {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mLinearLayout));
mTime.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mTimestamp1_home));
mUploaderBattery.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_uploaderBattery));
mStatus.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.dark_mStatus_home));
}
}

View file

@ -0,0 +1,155 @@
package info.nightscout.androidaps;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
/**
* Created by emmablack on 12/26/14.
*/
public class ListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
private static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
private static final String OPEN_SETTINGS = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
private static final String ACTION_RESEND = "com.dexdrip.stephenblack.nightwatch.RESEND_DATA";
private static final String ACTION_RESEND_BULK = "com.dexdrip.stephenblack.nightwatch.RESEND_BULK_DATA";
GoogleApiClient googleApiClient;
private long lastRequest = 0;
public class DataRequester extends AsyncTask<Void, Void, Void> {
Context mContext;
DataRequester(Context context) {
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
if (googleApiClient.isConnected()) {
if (System.currentTimeMillis() - lastRequest > 20 * 1000) { // enforce 20-second debounce period
lastRequest = System.currentTimeMillis();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_RESEND_PATH, null);
}
}
} else
googleApiClient.connect();
return null;
}
}
public void requestData() {
new DataRequester(this).execute();
}
public void googleApiConnect() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wearable.API)
.build();
Wearable.MessageApi.addListener(googleApiClient, this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && ACTION_RESEND.equals(intent.getAction())) {
googleApiConnect();
requestData();
}
return START_STICKY;
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
DataMap dataMap;
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
String path = event.getDataItem().getUri().getPath();
if (path.equals(OPEN_SETTINGS)) {
Intent intent = new Intent(this, NWPreferences.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if (path.equals(NEW_STATUS_PATH)) {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("status", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else if (path.equals(BASAL_DATA_PATH)){
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("basals", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("data", dataMap.toBundle());
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
}
}
}
public static void requestData(Context context) {
Intent intent = new Intent(context, ListenerService.class);
intent.setAction(ACTION_RESEND);
context.startService(intent);
}
@Override
public void onConnected(Bundle bundle) {
requestData();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onDestroy() {
super.onDestroy();
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
if (googleApiClient != null) {
Wearable.MessageApi.removeListener(googleApiClient, this);
}
}
}

View file

@ -0,0 +1,18 @@
package info.nightscout.androidaps;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import info.nightscout.androidaps.R;
import preference.WearPreferenceActivity;
public class NWPreferences extends WearPreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}

View file

@ -0,0 +1,13 @@
package info.nightscout.androidaps;
/**
* Created by adrian on 17/11/16.
*/
public class TempWatchData {
public long startTime;
public double startBasal;
public long endTime;
public double endBasal;
public double amount;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WatchViewStub
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:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_bigchart"
app:roundLayout="@layout/round_activity_bigchart"
tools:context=".Home"
tools:deviceIds="wear"/>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WatchViewStub
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:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_home"
app:roundLayout="@layout/round_activity_home"
tools:context=".Home"
tools:deviceIds="wear"/>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WatchViewStub
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:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="@layout/rect_activity_home_large"
app:roundLayout="@layout/round_activity_home_large"
tools:context=".Home"
tools:deviceIds="wear"/>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical|center_horizontal"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true">
<TextView android:id="@+id/agoString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="99'"
android:layout_gravity="center"
android:layout_marginBottom="-5dp" />
<TextView android:id="@+id/sgvString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="55sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="999"
android:layout_gravity="center" />
<TextView android:id="@+id/statusString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="no status"
android:layout_gravity="center"
android:layout_marginTop="-5dp" />
<TextView android:id="@+id/deltaString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="+99"
android:layout_gravity="center"
android:layout_marginTop="-5dp" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:gravity="center_horizontal">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:paddingTop="5dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-5dp"
android:gravity="center_horizontal">
<TextView
android:id="@+id/delta"
android:textSize="30sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal|bottom"
android:layout_marginRight="5dp" />
<TextView
android:id="@+id/sgv"
android:textSize="41sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/avgdelta"
android:textSize="30sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal|bottom"
android:layout_marginLeft="5dp" />
</LinearLayout>
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/aps_status"
android:textSize="18sp"
android:text="E xU/h IOB: x (x+x)"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:gravity="center_horizontal">
<TextView
android:id="@+id/watch_time"
android:textSize="35sp"
android:text="12:00"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_marginRight="6dp"
android:layout_gravity="center_horizontal" />
<TextView
android:id="@+id/timestamp"
android:textSize="26sp"
android:text="-- '"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textAlignment="center"
android:gravity="center_horizontal"
android:weightSum="1">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:paddingTop="5dp"
android:weightSum="1"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-5dp"
android:gravity="center_horizontal">
<TextView
android:id="@+id/sgv"
android:textSize="41sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="bottom|right"
android:layout_marginBottom="-2dp"
android:paddingTop="-2dp"
android:layout_marginRight="5dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1"
android:textAlignment="center"
android:baselineAligned="false"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal">
<TextView
android:id="@+id/direction"
android:textSize="30sp"
android:textStyle="bold"
android:text="--"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textAlignment="center"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_marginBottom="-5dp"
android:layout_marginTop="-2dp"
android:paddingTop="1dp" />
<TextView
android:id="@+id/delta"
android:textSize="10sp"
android:text="--- mg/dl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal|bottom"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/light_grey"
android:id="@+id/secondary_layout"
android:padding="1dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/timestamp"
android:textSize="10sp"
android:text="-- Minutes ago"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/uploader_battery"
android:textSize="10sp"
android:text="Uploader: ---%"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/raw"
android:textSize="10sp"
android:text=""
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/externaltstatus"
android:textSize="10sp"
android:text="S: no status"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/watch_time"
android:textSize="35sp"
android:text="12:00"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal|top" />
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="77dp"
android:layout_gravity="bottom"
android:gravity="center_horizontal|top" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textAlignment="center">
<LinearLayout
android:orientation="horizontal"
android:layout_width="147dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:paddingTop="15dp"
android:weightSum="1"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/sgv"
android:textSize="50sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="55dp"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="bottom|right" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1"
android:textAlignment="center"
android:baselineAligned="false"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/direction"
android:textSize="27sp"
android:textStyle="bold"
android:text="--"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textAlignment="center"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:paddingTop="1dp" />
<TextView
android:id="@+id/delta"
android:textSize="10sp"
android:text="--- mg/dl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/light_grey"
android:id="@+id/secondary_layout"
android:padding="2dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/timestamp"
android:textSize="12sp"
android:text="-- Minutes ago"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/uploader_battery"
android:textSize="12sp"
android:text="Uploader: ---%"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/raw"
android:textSize="12sp"
android:text=""
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/externaltstatus"
android:textSize="12sp"
android:text="S: no status"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/watch_time"
android:textSize="55sp"
android:text="12:00"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal|top" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:gravity="center_horizontal">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:paddingTop="5dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-5dp"
android:gravity="center_horizontal">
<TextView
android:id="@+id/delta"
android:textSize="30sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal|bottom"
android:layout_marginRight="5dp" />
<TextView
android:id="@+id/sgv"
android:textSize="41sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/avgdelta"
android:textSize="30sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal|bottom"
android:layout_marginLeft="5dp" />
</LinearLayout>
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/aps_status"
android:textSize="18sp"
android:text="E xU/h IOB: x (x+x)"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:gravity="center_horizontal">
<TextView
android:id="@+id/watch_time"
android:textSize="35sp"
android:text="12:00"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_marginRight="6dp"
android:layout_gravity="center_horizontal" />
<TextView
android:id="@+id/timestamp"
android:textSize="26sp"
android:text="-- '"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_round"
android:background="@color/black"
android:id="@+id/main_layout">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textAlignment="center"
android:weightSum="1">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:paddingTop="15dp"
android:weightSum="1"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:layout_marginTop="-5dp">
<TextView
android:id="@+id/sgv"
android:textSize="41sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="center_horizontal|bottom"
android:gravity="bottom|right"
android:paddingRight="5dp"
android:layout_marginBottom="-2dp"
android:paddingTop="-2dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:weightSum="1"
android:textAlignment="center"
android:baselineAligned="false"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/direction"
android:textSize="30sp"
android:text="--"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textAlignment="center"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:layout_marginBottom="-5dp"
android:layout_marginTop="-2dp"
android:textStyle="bold" />
<TextView
android:id="@+id/delta"
android:textSize="10sp"
android:text="--- mg/dl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal|bottom"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/light_grey"
android:id="@+id/secondary_layout"
android:padding="1dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/timestamp"
android:textSize="8sp"
android:text="-- Minutes ago"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/uploader_battery"
android:textSize="8sp"
android:text="Uploader: ---%"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/raw"
android:textSize="8sp"
android:text=""
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/externaltstatus"
android:textSize="8sp"
android:text="S: no status"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/watch_time"
android:textSize="30sp"
android:text="12:00"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:layout_marginTop="-2dp"
android:layout_marginBottom="-3dp" />
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="77dp"
android:layout_gravity="bottom"
android:gravity="center_horizontal|top" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".Home" tools:deviceIds="wear_round"
android:background="@color/black"
android:id="@+id/main_layout">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textAlignment="center">
<LinearLayout
android:orientation="horizontal"
android:layout_width="147dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:paddingTop="29dp"
android:weightSum="1"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/sgv"
android:textSize="50sp"
android:text="---"
android:layout_width="wrap_content"
android:layout_height="55dp"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="bottom|right" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1"
android:textAlignment="center"
android:baselineAligned="false"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/direction"
android:textSize="27sp"
android:textStyle="bold"
android:text="--"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textAlignment="center"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|bottom"
android:paddingTop="1dp" />
<TextView
android:id="@+id/delta"
android:textSize="10sp"
android:text="--- mg/dl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:layout_gravity="bottom"
android:gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/light_grey"
android:id="@+id/secondary_layout"
android:padding="2dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/timestamp"
android:textSize="12sp"
android:text="-- Minutes ago"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/uploader_battery"
android:textSize="12sp"
android:text="Uploader: ---%"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/raw"
android:textSize="12sp"
android:text=""
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/externaltstatus"
android:textSize="12sp"
android:text="S: no status"
android:layout_width="wrap_content"
android:textAlignment="center"
android:textColor="#000000"
android:paddingLeft="10sp"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/watch_time"
android:textSize="55sp"
android:text="12:00"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_gravity="center_horizontal|top" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- light colors -->
<color name="light_bigchart_time">@color/black</color>
<color name="light_bigchart_status">@color/black</color>
<color name="light_background">@color/white</color>
<color name="light_stripe_background">@color/black</color>
<color name="light_mTimestamp1">@color/black</color>
<color name="light_mTimestamp">@color/red_600</color>
<color name="light_highColor">@color/yellow_700</color>
<color name="light_lowColor">@color/red_600</color>
<color name="light_midColor">@color/black</color>
<color name="light_gridColor">@color/black</color>
<!-- dark colors -->
<color name="dark_mTime">@color/white</color>
<color name="dark_statusView">@color/white</color>
<color name="dark_background">@color/black</color>
<color name="dark_mLinearLayout">@color/grey_50</color>
<color name="dark_Timestamp">@color/white</color>
<color name="dark_mTimestamp1_home">@color/black</color>
<color name="dark_TimestampOld">@color/red_600</color>
<color name="dark_uploaderBattery">@color/black</color>
<color name="dark_uploaderBatteryEmpty">@color/red_600</color>
<color name="dark_mStatus_home">@color/black</color>
<color name="dark_highColor">@color/yellow_A200</color>
<color name="dark_lowColor">@color/RED</color>
<color name="dark_midColor">@color/grey_50</color>
<color name="dark_gridColor">@color/grey_50</color>
<!-- basal colors -->
<color name="basal_light">@color/blue_300</color>
<color name="basal_dark">@color/BLUE</color>
<color name="basal_light_lowres">@color/grey_300</color>
<color name="basal_dark_lowres">@color/grey_500</color>
<!-- Material Design - Color Palette -->
<!-- Red -->
<color name="red_600">#E53935</color>
<color name="RED">#FF0000</color>
<!-- Red -->
<!-- Blue -->
<color name="blue_300">#64B5F6</color>
<!-- Blue -->
<!-- Yellow -->
<color name="yellow_700">#FBC02D</color>
<color name="yellow_A200">#FFFF00</color>
<!-- Yellow -->
<!-- Grey -->
<color name="grey_50">#FAFAFA</color>
<color name="grey_300">#E0E0E0</color>
<color name="grey_500">#9E9E9E</color>
<!-- Grey -->
<!-- Blue Grey -->
<color name="BLUE">#0000FF</color>
<!-- Blue Grey -->
<!-- Black -->
<color name="black">#000000</color>
<!-- Black -->
<!-- White -->
<color name="white">#FFFFFF</color>
<!-- White -->
</resources>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">AAPS Prefs.</string>
<string-array name="chart_timeframe">
<item>1 hour</item>
<item>2 hours</item>
<item>3 hours</item>
<item>4 hours</item>
<item>5 hours</item>
</string-array>
<string-array name="chart_timeframe_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
</string-array>
</resources>

View file

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<CheckBoxPreference
android:defaultValue="true"
android:key="showExternalStatus"
android:title="Show Loop Status"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
<CheckBoxPreference
android:defaultValue="false"
android:key="highlight_basals"
android:summary="Better visible basal rate and temp basals"
android:title="Highlight Basals"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="showAvgDelta"
android:summary="Show the avgDelta."
android:title="Show AvgDelta"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="dark"
android:summary="Dark theme"
android:title="Dark"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<ListPreference
android:defaultValue="3"
android:entries="@array/chart_timeframe"
android:entryValues="@array/chart_timeframe_values"
android:key="chart_timeframe"
android:summary="Chart Timeframe"
android:title="Chart Timeframe" />
<CheckBoxPreference
android:defaultValue="true"
android:key="showAgo"
android:summary="Minutes since last reading. (Circle WF)"
android:title="Show Ago"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="showDelta"
android:summary="Show delta. (Circle WF)"
android:title="Show Delta"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="showBG"
android:summary="Show BG. (Circle WF)"
android:title="Show BG"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="showBigNumbers"
android:summary="Big numbers. (Circle WF)"
android:title="Big Numbers"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="showRingHistory"
android:summary="Graphical history. (Circle WF)"
android:title="Ring History"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
<CheckBoxPreference
android:defaultValue="true"
android:key="softRingHistory"
android:summary="Less eyecandy. (Circle WF)"
android:title="Light Ring History"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="animation"
android:summary="Animations. (Circle WF)"
android:title="Animations"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on"/>
</PreferenceScreen>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />

152
wear/wear.iml Normal file
View file

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":wear" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":wear" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="fullDebug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleFullDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileFullDebugSources" />
<afterSyncTasks>
<task>generateFullDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/full/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/full/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/full/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/full/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/full/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/full/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/full/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/full/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/full/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/fullDebug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/full/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/full/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/full/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/full/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/full/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/full/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/full/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFullDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/full/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/full/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/full/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/full/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/full/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/full/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/full/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/full/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestFull/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testFull/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-base/7.3.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-wearable/7.3.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.support/wearable/1.4.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/me.denley.wearpreferenceactivity/wearpreferenceactivity/0.5.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/ustwo-clockwise-debug/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="ustwo-clockwise-debug-" level="project" />
<orderEntry type="library" exported="" name="hellocharts-library-1.5.5" level="project" />
<orderEntry type="library" exported="" name="play-services-wearable-7.3.0" level="project" />
<orderEntry type="library" exported="" name="wearpreferenceactivity-0.5.0" level="project" />
<orderEntry type="library" exported="" name="wearable-1.4.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="play-services-base-7.3.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
</component>
</module>