├── .gitignore
├── src
├── main
│ ├── resources
│ │ ├── Dawn.JPG
│ │ ├── Thumbs.db
│ │ ├── Nightscout.jpg
│ │ ├── images
│ │ │ ├── Thumbs.db
│ │ │ ├── MainPage.jpg
│ │ │ ├── FindModify.JPG
│ │ │ ├── TrendAnalysis.jpg
│ │ │ ├── AnalysisCGMDates.JPG
│ │ │ ├── Autotune_MainPage.JPG
│ │ │ ├── CGMTrendAnalysis.jpg
│ │ │ ├── Autotune_ListBackups.JPG
│ │ │ ├── AutotuneManagementRun.JPG
│ │ │ ├── TreatmentTrendAnalysis.jpg
│ │ │ ├── Autotune_ProfileEditorPage.JPG
│ │ │ ├── AutotuneManagementListBackups.JPG
│ │ │ └── AutotuneManagementProfileEditor.JPG
│ │ └── NightscoutLoader.pdf
│ └── java
│ │ ├── entity
│ │ ├── TextLineReceiverInterface.java
│ │ ├── DBResultInterface.java
│ │ ├── DBResultPumpSettingCarbRatio.java
│ │ ├── DBResultOmniPod.java
│ │ ├── DBResultPumpSettingISF.java
│ │ ├── ResultFromDBComparator.java
│ │ ├── DBResultPumpSettingTarget.java
│ │ ├── DBResultPumpSetting.java
│ │ ├── DBResultPumpSettingBasal.java
│ │ ├── DBResultRoche.java
│ │ ├── DBResultEntryLibreView.java
│ │ ├── DBResultEntryDiasend.java
│ │ ├── DBResultCore.java
│ │ ├── DBResultCellNovoRaw.java
│ │ ├── DBResultMedtronicOld.java
│ │ └── DBResultMedtronicNew.java
│ │ ├── win
│ │ ├── WinSetDatesInterface.java
│ │ ├── WinAbout.java
│ │ ├── WinTextWin.java
│ │ └── WinWhy.java
│ │ ├── control
│ │ ├── MainControlInterface.java
│ │ ├── ThreadAutotuneRun.java
│ │ ├── ThreadAutotuneListBackups.java
│ │ ├── ThreadMongoDBAlerterEntries.java
│ │ ├── ThreadMongoDBAlerterTreatments.java
│ │ ├── ThreadAutotuneRemoteSaveAs.java
│ │ ├── ThreadAutotuneDownloadBackups.java
│ │ ├── MainNightScoutLoader.java
│ │ ├── ThreadHelpLauncher.java
│ │ ├── ThreadAutotune.java
│ │ ├── ThreadDataLoad.java
│ │ ├── ThreadAnalyzer.java
│ │ └── ThreadMongoDBAlerter.java
│ │ ├── loader
│ │ ├── DataLoadFile.java
│ │ ├── AuditLogComparator.java
│ │ ├── DataLoadNightScoutEntries.java
│ │ ├── DataLoadRocheCSV.java
│ │ ├── DataLoadLibreView.java
│ │ ├── DataLoadCellNovo.java
│ │ └── DataLoadMedtronic.java
│ │ ├── miscellaneous
│ │ ├── OmniPodBinaryFileRecord.java
│ │ ├── OmniPodBinaryLogFileSection.java
│ │ ├── BinaryFileFieldValue.java
│ │ ├── OmniPodBinaryFileSectionComparator.java
│ │ ├── DateLabelFormatter.java
│ │ ├── OmniPodValidator.java
│ │ ├── BinaryFileFieldAccess.java
│ │ ├── OmniPodBinaryFileSection.java
│ │ ├── FileChecker.java
│ │ └── BinaryStruct.java
│ │ ├── analysis
│ │ ├── AnalyzerID.java
│ │ ├── AnalyzerEntriesCGMDay.java
│ │ ├── AnalyzerTrendResultEntryComparator.java
│ │ ├── AnalyzerTrendResultEntryAggregate.java
│ │ ├── AnalyzerTabs.java
│ │ └── AnalyzerTrendResultEntry.java
│ │ ├── utils
│ │ └── DatePatternFormat.java
│ │ └── mongo
│ │ └── NightscoutMongoDB.java
└── test
│ ├── resources
│ ├── Sample_Diasend.xls
│ ├── Sample_Diasend2.xls
│ ├── Sample_Diasend_forCoding.xls
│ └── Sample_Libreview_forCoding.xlsx
│ └── java
│ ├── loader
│ ├── TestDiasendTreatmentInsCarbNotMerged.java
│ ├── BaseTestEntry.java
│ └── BaseTestTreatment.java
│ └── control
│ └── TestMongoConnection.java
├── .project
├── bin
├── loadDiasend.sh
├── loadLibreview.sh
└── NightScoutLoader.bat
├── .classpath
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .settings
2 | target
3 | .classpath
4 | .project
5 | .idea
--------------------------------------------------------------------------------
/src/main/resources/Dawn.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/Dawn.JPG
--------------------------------------------------------------------------------
/src/main/resources/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/Thumbs.db
--------------------------------------------------------------------------------
/src/main/resources/Nightscout.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/Nightscout.jpg
--------------------------------------------------------------------------------
/src/main/resources/images/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/Thumbs.db
--------------------------------------------------------------------------------
/src/main/resources/images/MainPage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/MainPage.jpg
--------------------------------------------------------------------------------
/src/test/resources/Sample_Diasend.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/test/resources/Sample_Diasend.xls
--------------------------------------------------------------------------------
/src/test/resources/Sample_Diasend2.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/test/resources/Sample_Diasend2.xls
--------------------------------------------------------------------------------
/src/main/resources/NightscoutLoader.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/NightscoutLoader.pdf
--------------------------------------------------------------------------------
/src/main/resources/images/FindModify.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/FindModify.JPG
--------------------------------------------------------------------------------
/src/main/resources/images/TrendAnalysis.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/TrendAnalysis.jpg
--------------------------------------------------------------------------------
/src/main/resources/images/AnalysisCGMDates.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/AnalysisCGMDates.JPG
--------------------------------------------------------------------------------
/src/main/resources/images/Autotune_MainPage.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/Autotune_MainPage.JPG
--------------------------------------------------------------------------------
/src/main/resources/images/CGMTrendAnalysis.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/CGMTrendAnalysis.jpg
--------------------------------------------------------------------------------
/src/test/resources/Sample_Diasend_forCoding.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/test/resources/Sample_Diasend_forCoding.xls
--------------------------------------------------------------------------------
/src/main/resources/images/Autotune_ListBackups.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/Autotune_ListBackups.JPG
--------------------------------------------------------------------------------
/src/test/resources/Sample_Libreview_forCoding.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/test/resources/Sample_Libreview_forCoding.xlsx
--------------------------------------------------------------------------------
/src/main/resources/images/AutotuneManagementRun.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/AutotuneManagementRun.JPG
--------------------------------------------------------------------------------
/src/main/resources/images/TreatmentTrendAnalysis.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/TreatmentTrendAnalysis.jpg
--------------------------------------------------------------------------------
/src/main/java/entity/TextLineReceiverInterface.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | public interface TextLineReceiverInterface
4 | {
5 | public void addTextLine(String line);
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/resources/images/Autotune_ProfileEditorPage.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/Autotune_ProfileEditorPage.JPG
--------------------------------------------------------------------------------
/src/main/resources/images/AutotuneManagementListBackups.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/AutotuneManagementListBackups.JPG
--------------------------------------------------------------------------------
/src/main/resources/images/AutotuneManagementProfileEditor.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gh-davidr/NightscoutLoader/HEAD/src/main/resources/images/AutotuneManagementProfileEditor.JPG
--------------------------------------------------------------------------------
/src/main/java/win/WinSetDatesInterface.java:
--------------------------------------------------------------------------------
1 | package win;
2 |
3 | import java.util.Date;
4 |
5 | public interface WinSetDatesInterface
6 | {
7 | void setDates(Date startDate, Date endDate);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/control/MainControlInterface.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | public interface MainControlInterface
4 | {
5 | // Simple interface that allows the command line mechanism to exit cleanly
6 | // once all threads are complete
7 | public void shutdown();
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/loader/DataLoadFile.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.IOException;
4 | import java.sql.SQLException;
5 |
6 | public abstract class DataLoadFile extends DataLoadBase
7 | {
8 | public abstract void loadDBResults(String fileName) throws IOException, SQLException, ClassNotFoundException;
9 |
10 | public abstract void initialize(String filename);
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/OmniPodBinaryFileRecord.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | public class OmniPodBinaryFileRecord extends OmniPodBinaryFileSection
4 | {
5 |
6 | OmniPodBinaryFileRecord(String sectionHeader, String encoding, String[] fieldNames) {
7 | super(sectionHeader, encoding, fieldNames);
8 | // TODO Auto-generated constructor stub
9 | }
10 | // OmniPodBinaryFileRecord
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultInterface.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import com.mongodb.BasicDBObject;
4 |
5 | public interface DBResultInterface
6 | {
7 | public long getM_EpochMillies();
8 |
9 | // Derived classes will implement the concept of proximity duplicates
10 | void setImpactOfProximity();
11 |
12 | void determineWhetherInProximity();
13 |
14 | BasicDBObject createNightScoutObject();
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/analysis/AnalyzerID.java:
--------------------------------------------------------------------------------
1 | package analysis;
2 |
3 | public class AnalyzerID
4 | {
5 | private int m_ID = 0; // Assign an ID to each result created.
6 |
7 | AnalyzerID(Integer static_ID)
8 | {
9 | synchronized(static_ID)
10 | {
11 | static_ID++;
12 | m_ID = static_ID;
13 | }
14 | }
15 |
16 | /**
17 | * @return the m_ID
18 | */
19 | public synchronized int getM_ID() {
20 | return m_ID;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadAutotuneRun.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import miscellaneous.RemoteLinuxServer;
4 |
5 | public class ThreadAutotuneRun extends ThreadAutotune
6 | {
7 |
8 | public ThreadAutotuneRun(RemoteLinuxServer autoTuner)
9 | {
10 | super(autoTuner);
11 | }
12 |
13 | @Override
14 | protected void doAutotuneTask()
15 | {
16 | // TODO Auto-generated method stub
17 | m_Autotuner.runAutotune();
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadAutotuneListBackups.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import miscellaneous.RemoteLinuxServer;
4 |
5 | public class ThreadAutotuneListBackups extends ThreadAutotune
6 | {
7 | public ThreadAutotuneListBackups(RemoteLinuxServer autoTuner)
8 | {
9 | super(autoTuner);
10 | }
11 |
12 | @Override
13 | protected void doAutotuneTask()
14 | {
15 | // TODO Auto-generated method stub
16 | m_Autotuner.listBackupDirectory();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | NightscoutLoaderMaven
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.m2e.core.maven2Nature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultPumpSettingCarbRatio.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import org.apache.poi.hssf.usermodel.HSSFRow;
4 |
5 | public class DBResultPumpSettingCarbRatio extends DBResultPumpSetting
6 | {
7 | public DBResultPumpSettingCarbRatio(HSSFRow row)
8 | {
9 | super(row);
10 | }
11 |
12 | /**
13 | * @return the m_CarbRatioValue
14 | */
15 | public synchronized Double getM_CarbRatioValue() {
16 | return getM_TimeBoundValue();
17 | }
18 |
19 | /**
20 | * @param m_CarbRatioValue the m_CarbRatioValue to set
21 | */
22 | public synchronized void setM_CarbRatioValue(Double m_CarbRatioValue) {
23 | setM_TimeBoundValue(m_CarbRatioValue);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadMongoDBAlerterEntries.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 | import java.text.ParseException;
5 |
6 | import utils.CommonUtils;
7 |
8 | public class ThreadMongoDBAlerterEntries extends ThreadMongoDBAlerter
9 | {
10 | private static String m_What = new String("Entries");
11 |
12 | @Override
13 | protected void checkDBForUpdates() throws IOException, ParseException
14 | {
15 | String result = this.m_DataLoader.getLatestEntriesTime();
16 |
17 | if (result != null)
18 | {
19 | m_CurrentResultAt = CommonUtils.convertDateString(result);
20 | }
21 | }
22 |
23 | @Override
24 | protected String whatIsChecked()
25 | {
26 | return m_What;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/OmniPodBinaryLogFileSection.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | public class OmniPodBinaryLogFileSection
4 | {
5 | private int m_FileOffset;
6 | private OmniPodBinaryFileSection m_OmniPodBinaryFileSection;
7 |
8 | public OmniPodBinaryLogFileSection(int offset,
9 | OmniPodBinaryFileSection fileSection)
10 | {
11 | m_FileOffset = offset;
12 | m_OmniPodBinaryFileSection = fileSection;
13 | }
14 |
15 | /**
16 | * @return the m_FileOffset
17 | */
18 | public synchronized int getM_FileOffset() {
19 | return m_FileOffset;
20 | }
21 |
22 | /**
23 | * @return the m_OmniPodBinaryFileSection
24 | */
25 | public synchronized OmniPodBinaryFileSection getM_OmniPodBinaryLogFileSection() {
26 | return m_OmniPodBinaryFileSection;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultOmniPod.java:
--------------------------------------------------------------------------------
1 | //package entity;
2 | //
3 | //import java.util.ArrayList;
4 | //
5 | //import org.DavidRichardson.NightscoutLoaderMaven.OmniPodBinaryFileSection;
6 | //
7 | //public class DBResultOmniPod extends DBResult
8 | //{
9 | // // For now, keep each record with its own reference to
10 | // // how file should be read.
11 | // private ArrayList m_OmniPodBinaryFileSections = null;
12 | // private byte[] m_OmniPodBytes = null;
13 | //
14 | // DBResultOmniPod(ArrayList fileSections,
15 | // byte[] fileContents, int offset)
16 | // {
17 | // m_OmniPodBinaryFileSections = fileSections;
18 | // m_OmniPodBytes = fileContents;
19 | // }
20 | //
21 | // private void unpack()
22 | // {
23 | //
24 | // }
25 | //}
26 |
--------------------------------------------------------------------------------
/src/main/java/utils/DatePatternFormat.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | public class DatePatternFormat
6 | {
7 | private String m_PatternString = null;
8 | private String m_FormatString = null;
9 | private Pattern m_Pattern = null;
10 |
11 | public DatePatternFormat(String m_PatternString, String m_FormatString) {
12 | super();
13 | this.m_PatternString = m_PatternString;
14 | this.m_FormatString = m_FormatString;
15 |
16 | m_Pattern = Pattern.compile(m_PatternString);
17 | }
18 |
19 | /**
20 | * @return the m_PatternString
21 | */
22 | public synchronized String getM_PatternString() {
23 | return m_PatternString;
24 | }
25 |
26 | /**
27 | * @return the m_FormatString
28 | */
29 | public synchronized String getM_FormatString() {
30 | return m_FormatString;
31 | }
32 |
33 | /**
34 | * @return the m_Pattern
35 | */
36 | public synchronized Pattern getM_Pattern() {
37 | return m_Pattern;
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/control/ThreadMongoDBAlerterTreatments.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 | import java.text.ParseException;
5 | import java.util.regex.Matcher;
6 | import java.util.regex.Pattern;
7 |
8 | import utils.CommonUtils;
9 |
10 | public class ThreadMongoDBAlerterTreatments extends ThreadMongoDBAlerter
11 | {
12 | private static String m_What = new String("Treatments");
13 |
14 | @Override
15 | protected void checkDBForUpdates() throws IOException, ParseException
16 | {
17 | String result = this.m_DataLoader.getLatestTreatmentsTimeAndWho();
18 | if (result != null)
19 | {
20 | String pattern = "(.*)( by )(.*)";
21 | Pattern r = Pattern.compile(pattern);
22 | Matcher m = r.matcher(result);
23 | if (m.find())
24 | {
25 | m_CurrentResultAt = CommonUtils.convertDateString(m.group(1));
26 | m_CurrentResultBy = m.group(3);
27 | }
28 | }
29 | }
30 |
31 | @Override
32 | protected String whatIsChecked()
33 | {
34 | return m_What;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultPumpSettingISF.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import org.apache.poi.hssf.usermodel.HSSFRow;
4 |
5 | public class DBResultPumpSettingISF extends DBResultPumpSetting
6 | {
7 | private String m_BGUnits;
8 |
9 | public DBResultPumpSettingISF(HSSFRow row, String bgUnits)
10 | {
11 | super(row);
12 |
13 | m_BGUnits = new String(bgUnits);
14 | }
15 |
16 | /**
17 | * @return the m_ISFValue
18 | */
19 | public synchronized Double getM_ISFValue() {
20 | return getM_TimeBoundValue();
21 | }
22 |
23 | /**
24 | * @param m_ISFValue the m_ISFValue to set
25 | */
26 | public synchronized void setM_ISFValue(Double m_ISFValue) {
27 | setM_TimeBoundValue(m_ISFValue);
28 | }
29 |
30 | /**
31 | * @return the m_BGUnits
32 | */
33 | public synchronized String getM_BGUnits() {
34 | return m_BGUnits;
35 | }
36 |
37 | /**
38 | * @param m_BGUnits the m_BGUnits to set
39 | */
40 | public synchronized void setM_BGUnits(String m_BGUnits) {
41 | this.m_BGUnits = m_BGUnits;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadAutotuneRemoteSaveAs.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 | import java.util.logging.Level;
5 | import java.util.logging.Logger;
6 |
7 | import miscellaneous.RemoteLinuxServer;
8 |
9 | public class ThreadAutotuneRemoteSaveAs extends ThreadAutotune
10 | {
11 | private static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
12 |
13 | private String m_JSON;
14 | private String m_LocalFile;
15 |
16 | public ThreadAutotuneRemoteSaveAs(RemoteLinuxServer autoTuner,
17 | String json, String localFile)
18 | {
19 | super(autoTuner);
20 | m_JSON = new String(json);
21 | m_LocalFile = new String(localFile);
22 | }
23 |
24 | @Override
25 | protected void doAutotuneTask()
26 | {
27 | // TODO Auto-generated method stub
28 | try
29 | {
30 | m_Autotuner.remoteSaveAs(m_JSON, m_LocalFile);
31 | }
32 | catch (IOException e)
33 | {
34 | m_Logger.log(Level.SEVERE, "ThreadAutotuneRemoteSaveAs.doAutotuneTask exception caught " + e.getMessage());
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadAutotuneDownloadBackups.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 | import java.util.logging.Level;
5 | import java.util.logging.Logger;
6 |
7 | import miscellaneous.RemoteLinuxServer;
8 |
9 | public class ThreadAutotuneDownloadBackups extends ThreadAutotune
10 | {
11 | protected static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
12 |
13 | private String m_LocalDirectory;
14 |
15 | public ThreadAutotuneDownloadBackups(RemoteLinuxServer autoTuner, String localDirectory)
16 | {
17 | super(autoTuner);
18 | m_LocalDirectory = new String(localDirectory);
19 | }
20 |
21 | @Override
22 | protected void doAutotuneTask()
23 | {
24 | // TODO Auto-generated method stub
25 | m_Autotuner.downloadAllBackupProfileFiles(m_LocalDirectory);
26 | try
27 | {
28 | Runtime.getRuntime().exec("explorer.exe /select," + m_LocalDirectory);
29 | }
30 | catch (IOException e)
31 | {
32 | m_Logger.log( Level.SEVERE, "ThreadAutotuneDownloadBackups caught exception " + e.getMessage() );
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/BinaryFileFieldValue.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 | //package org.DavidRichardson.NightscoutLoaderMaven;
3 | //
4 | //public class BinaryFileFieldValue
5 | //{
6 | // enum BinaryFileFieldValueType
7 | // {
8 | // fvt_Unknown,
9 | //
10 | // fvt_IntVal,
11 | // fvt_ShortVal,
12 | // fvt_ByteVal,
13 | // fvt_StringVal,
14 | // fvt_FloatVal,
15 | // };
16 | //
17 | // private byte[] m_OmniPodBytes = null;
18 | // private int m_Offset = 0;
19 | // private String m_FieldName = "";
20 | // private BinaryStruct.VarType m_VarType = BinaryStruct.VarType.vt_Unknown;
21 | // private BinaryFileFieldValueType m_FieldType = BinaryFileFieldValueType.fvt_Unknown;
22 | //
23 | // private int m_IntVal = 0;
24 | // private short m_ShortVal = 0;
25 | // private byte m_ByteVal = 0;
26 | // private String m_StringVal = "";
27 | // private float m_FloatVal = 0;
28 | //
29 | //
30 | // BinaryFileFieldValue(int offset, byte[] omniPodBytes, BinaryStruct.VarType varType)
31 | // {
32 | //
33 | // }
34 | //
35 | //
36 | //
37 | //}
38 |
--------------------------------------------------------------------------------
/src/main/java/entity/ResultFromDBComparator.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.util.Comparator;
4 |
5 | public class ResultFromDBComparator implements Comparator
6 | {
7 | private boolean m_DescendingSort = true;
8 | public ResultFromDBComparator()
9 | {
10 | m_DescendingSort = true;
11 | }
12 | public ResultFromDBComparator(boolean descendingSort)
13 | {
14 | m_DescendingSort = descendingSort;
15 | }
16 |
17 | public int compare(DBResultInterface p1, DBResultInterface p2)
18 | {
19 | int result = 0;
20 | long p1_millies = p1.getM_EpochMillies();
21 | long p2_millies = p2.getM_EpochMillies();
22 | long diff = p1_millies - p2_millies;
23 |
24 | // Subtraction is too big for int result
25 | if ((diff) > 0)
26 | {
27 | // 1 to get results in ascending order
28 | // -1 to get results in descending order
29 | result = m_DescendingSort ? -1 : 1;
30 | }
31 | else if ((diff) < 0)
32 | {
33 | // -1 to get results in ascending order
34 | // 1 to get results in descending order
35 | result = m_DescendingSort ? 1 : -1;
36 | }
37 | return result;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/loader/AuditLogComparator.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.util.Comparator;
4 | import java.util.Date;
5 |
6 | public class AuditLogComparator implements Comparator
7 | {
8 | private boolean m_DescendingSort = true;
9 | AuditLogComparator()
10 | {
11 | m_DescendingSort = true;
12 | }
13 | public AuditLogComparator(boolean descendingSort)
14 | {
15 | m_DescendingSort = descendingSort;
16 | }
17 |
18 | public int compare(AuditLog p1, AuditLog p2)
19 | {
20 | int result = 0;
21 |
22 | Date alD1 = p1.getM_UploadDate();
23 | Date alD2 = p2.getM_UploadDate();
24 |
25 | long p1_millies = alD1.getTime();
26 | long p2_millies = alD2.getTime();
27 | long diff = p1_millies - p2_millies;
28 |
29 | // Subtraction is too big for int result
30 | if ((diff) > 0)
31 | {
32 | // 1 to get results in ascending order
33 | // -1 to get results in descending order
34 | result = m_DescendingSort ? -1 : 1;
35 | }
36 | else if ((diff) < 0)
37 | {
38 | // -1 to get results in ascending order
39 | // 1 to get results in descending order
40 | result = m_DescendingSort ? 1 : -1;
41 | }
42 | return result;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/bin/loadDiasend.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Linux script to run NightScoutLoader to load all Diasend files from the $inDir
5 | # in succession, one after the other.
6 | # As each file gets processed, the file is moved to $arDir archive directory and
7 | # timestamped with processing date/time
8 | #
9 | # Variables below need to be set carefully
10 | #
11 |
12 | dir="" # Directory of the NightScoutLoader.jar file and probably this script too
13 | inDir="" # Directory where Diasend files to upload are put
14 | arDir="" # Directory where Diasend files once processed get archived
15 | log="${dir}/loadDiasend.log"
16 | jarLog="${dir}/NightscoutLoader_Diasend.log"
17 | jar="${dir}/NightScoutLoader.jar"
18 | msr="" # Set to your MongoDB URI
19 | mdb="" # Set to your MongoDB DB
20 | weeks=104
21 |
22 | processFile()
23 | {
24 | file=$1
25 | ofile=`basename "${file}" .xls`.`echo $(date +%FT%H%M%S)`.xls
26 |
27 | echo "$(date +%FT%H%M%S) - Processing Diasend file $file" | tee -a $log
28 | java -Xmx1024m -Xms128m -jar $jar -m diasend -f "${file}" -s $msr -d $mdb -w $weeks -l "$jarLog" | tee -a $log
29 | echo "Archiving file as $ofile in $arDir"
30 | mv "${file}" "${arDir}/${ofile}"
31 | }
32 |
33 | for f in ${inDir}/*;
34 | do
35 | processFile "$f"
36 | done
37 |
--------------------------------------------------------------------------------
/bin/loadLibreview.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Linux script to run NightScoutLoader to load all LibreView files from the $inDir
5 | # in succession, one after the other.
6 | # As each file gets processed, the file is moved to $arDir archive directory and
7 | # timestamped with processing date/time
8 | #
9 | # Variables below need to be set carefully
10 | #
11 |
12 | dir="" # Directory of the NightScoutLoader.jar file and probably this script too
13 | inDir="" # Directory where LibreView files to upload are put
14 | arDir="" # Directory where LibreView files once processed get archived
15 | log="${dir}/loadLibreview.log"
16 | jarLog="${dir}/NightscoutLoader_Libre.log"
17 | jar="${dir}/NightScoutLoader.jar"
18 | msr="" # Set to your MongoDB URI
19 | mdb="" # Set to your MongoDB DB
20 | weeks=104
21 |
22 | processFile()
23 | {
24 | file=$1
25 | ofile=`basename "${file}" .csv`.`echo $(date +%FT%H%M%S)`.csv
26 |
27 | echo "$(date +%FT%H%M%S) - Processing Libreview file $file" | tee -a $log
28 | java -Xmx1024m -Xms128m -jar $jar -m libreview -f "${file}" -s $msr -d $mdb -w $weeks -l "$jarLog" | tee -a $log
29 | echo "Archiving file as $ofile in $arDir"
30 | mv "${file}" "${arDir}/${ofile}"
31 | }
32 |
33 | for f in ${inDir}/*;
34 | do
35 | processFile "$f"
36 | done
37 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/OmniPodBinaryFileSectionComparator.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | import java.util.Comparator;
4 | //import java.util.Date;
5 |
6 | public class OmniPodBinaryFileSectionComparator implements Comparator
7 | {
8 |
9 | private boolean m_DescendingSort = true;
10 | OmniPodBinaryFileSectionComparator()
11 | {
12 | m_DescendingSort = true;
13 | }
14 | OmniPodBinaryFileSectionComparator(boolean descendingSort)
15 | {
16 | m_DescendingSort = descendingSort;
17 | }
18 |
19 | public int compare(OmniPodBinaryFileSection p1, OmniPodBinaryFileSection p2)
20 | {
21 | int result = 0;
22 |
23 | String alD1 = p1.getM_SectionHeader();
24 | String alD2 = p2.getM_SectionHeader();
25 |
26 | int hash1 = alD1.hashCode();
27 | int hash2 = alD2.hashCode();
28 | int diff = hash1 - hash2;
29 |
30 | // Subtraction is too big for int result
31 | if ((diff) > 0)
32 | {
33 | // 1 to get results in ascending order
34 | // -1 to get results in descending order
35 | result = m_DescendingSort ? -1 : 1;
36 | }
37 | else if ((diff) < 0)
38 | {
39 | // -1 to get results in ascending order
40 | // 1 to get results in descending order
41 | result = m_DescendingSort ? 1 : -1;
42 | }
43 | return result;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultPumpSettingTarget.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import org.apache.poi.hssf.usermodel.HSSFRow;
4 |
5 | public class DBResultPumpSettingTarget extends DBResultPumpSetting
6 | {
7 | private String m_BGUnits;
8 | private Double m_TargetLowValue;
9 | private Double m_TargetHighValue;
10 |
11 | public DBResultPumpSettingTarget(HSSFRow row, String bgUnits)
12 | {
13 | super(row);
14 |
15 | m_BGUnits = new String(bgUnits);
16 | }
17 |
18 | /**
19 | * @return the m_BGUnits
20 | */
21 | public synchronized String getM_BGUnits() {
22 | return m_BGUnits;
23 | }
24 |
25 | /**
26 | * @param m_BGUnits the m_BGUnits to set
27 | */
28 | public synchronized void setM_BGUnits(String m_BGUnits) {
29 | this.m_BGUnits = m_BGUnits;
30 | }
31 |
32 | /**
33 | * @return the m_TargetLowValue
34 | */
35 | public synchronized Double getM_TargetLowValue() {
36 | return m_TargetLowValue;
37 | }
38 |
39 | /**
40 | * @param m_TargetLowValue the m_TargetLowValue to set
41 | */
42 | public synchronized void setM_TargetLowValue(Double m_TargetLowValue) {
43 | this.m_TargetLowValue = m_TargetLowValue;
44 | }
45 |
46 | /**
47 | * @return the m_TargetHighValue
48 | */
49 | public synchronized Double getM_TargetHighValue() {
50 | return m_TargetHighValue;
51 | }
52 |
53 | /**
54 | * @param m_TargetHighValue the m_TargetHighValue to set
55 | */
56 | public synchronized void setM_TargetHighValue(Double m_TargetHighValue) {
57 | this.m_TargetHighValue = m_TargetHighValue;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/java/analysis/AnalyzerEntriesCGMDay.java:
--------------------------------------------------------------------------------
1 | package analysis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Date;
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 |
8 | import control.MyLogger;
9 | import entity.DBResultEntry;
10 |
11 | public class AnalyzerEntriesCGMDay
12 | {
13 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
14 |
15 | private static Integer m_Static_ID = 0; // Assign an ID to each result created.
16 | private int m_ID = 0; // Assign an ID to each result created.
17 |
18 | private Date m_Date;
19 | private ArrayList m_DBResultEntries;
20 |
21 | AnalyzerEntriesCGMDay(Date date)
22 | {
23 | m_Static_ID++;
24 | m_ID = m_Static_ID;
25 |
26 | m_Logger.log(Level.FINE, "Just built AnalyzerEntriesCGMDay " + m_ID + " @" +
27 | date.toString());
28 |
29 |
30 | m_Date = new Date(date.getTime());
31 | m_DBResultEntries = new ArrayList();
32 | }
33 |
34 | public void addDBResultEntry(DBResultEntry e)
35 | {
36 | m_DBResultEntries.add(e);
37 | }
38 |
39 | public synchronized static void resetStaticID()
40 | {
41 | m_Static_ID = 0;
42 | }
43 |
44 | /**
45 | * @return the m_ID
46 | */
47 | public synchronized int getM_ID() {
48 | return m_ID;
49 | }
50 |
51 |
52 | /**
53 | * @return the m_Date
54 | */
55 | public synchronized Date getM_Date() {
56 | return m_Date;
57 | }
58 |
59 | /**
60 | * @return the m_DBResultEntries
61 | */
62 | public synchronized ArrayList getM_DBResultEntries() {
63 | return m_DBResultEntries;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/DateLabelFormatter.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | import java.text.ParseException;
4 | import java.text.SimpleDateFormat;
5 | import java.util.Calendar;
6 | import java.util.Date;
7 |
8 | import javax.swing.JFormattedTextField.AbstractFormatter;
9 |
10 | // Used to format dates in JDatePicker
11 | public class DateLabelFormatter extends AbstractFormatter
12 | {
13 |
14 | /**
15 | *
16 | */
17 | private static final long serialVersionUID = 1L;
18 |
19 | private String datePattern = "dd-MMM-yyyy";
20 | private SimpleDateFormat dateFormatter = new SimpleDateFormat(datePattern);
21 |
22 | @Override
23 | public Object stringToValue(String text) throws ParseException {
24 | return dateFormatter.parseObject(text);
25 | }
26 |
27 | @Override
28 | public String valueToString(Object value) throws ParseException {
29 | if (value != null)
30 | {
31 | // Date dateVal = (Date)value;
32 | // return dateFormatter.format(dateVal.getTime());
33 |
34 | if (value.getClass().getName().equals("java.util.GregorianCalendar"))
35 | {
36 | // David - 30 Aug 2016
37 | Calendar cal = (Calendar)value; // Get exception about casting a Date to Calendar
38 | // Seems to happen on analyzer when setting days back, clicking off then running analyze
39 | return dateFormatter.format(cal.getTime());
40 | }
41 | else if (value.getClass().getName().equals("java.util.Date"))
42 | {
43 | // David - 30 Aug 2016
44 | Date cal = (Date)value; // Get exception about casting a Date to Calendar
45 | // Seems to happen on analyzer when setting days back, clicking off then running analyze
46 | return dateFormatter.format(cal.getTime());
47 | }
48 | else
49 | {
50 | System.out.println("Unexpected Class type here " + value.getClass().getName());
51 | }
52 | }
53 |
54 | return "";
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/OmniPodValidator.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | public abstract class OmniPodValidator
4 | {
5 | // private OmniPodBinaryFileSection m_OmniPodBinaryFileSection;
6 |
7 | public class OmniPodDetails
8 | {
9 |
10 | };
11 |
12 | // --------------------------------
13 | // Class for handling Bolus details
14 | // --------------------------------
15 | public class OmniPodDetailsBolus extends OmniPodDetails
16 | {
17 | private int m_VolumeUnits = 0;
18 | private int m_ExtendedDurationMSec = 0;
19 | private int m_ImmediateDurationMSec = 0;
20 | /**
21 | * @return the m_VolumeUnits
22 | */
23 | public synchronized int getM_VolumeUnits() {
24 | return m_VolumeUnits;
25 | }
26 | /**
27 | * @param m_VolumeUnits the m_VolumeUnits to set
28 | */
29 | public synchronized void setM_VolumeUnits(int m_VolumeUnits) {
30 | this.m_VolumeUnits = m_VolumeUnits;
31 | }
32 | /**
33 | * @return the m_ExtendedDurationMSec
34 | */
35 | public synchronized int getM_ExtendedDurationMSec() {
36 | return m_ExtendedDurationMSec;
37 | }
38 | /**
39 | * @param m_ExtendedDurationMSec the m_ExtendedDurationMSec to set
40 | */
41 | public synchronized void setM_ExtendedDurationMSec(int m_ExtendedDurationMSec) {
42 | this.m_ExtendedDurationMSec = m_ExtendedDurationMSec;
43 | }
44 | /**
45 | * @return the m_ImmediateDurationMSec
46 | */
47 | public synchronized int getM_ImmediateDurationMSec() {
48 | return m_ImmediateDurationMSec;
49 | }
50 | /**
51 | * @param m_ImmediateDurationMSec the m_ImmediateDurationMSec to set
52 | */
53 | public synchronized void setM_ImmediateDurationMSec(int m_ImmediateDurationMSec) {
54 | this.m_ImmediateDurationMSec = m_ImmediateDurationMSec;
55 | }
56 | };
57 |
58 | public abstract boolean valid();
59 | public abstract OmniPodDetails getDetails();
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultPumpSetting.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import org.apache.poi.hssf.usermodel.HSSFCell;
4 | import org.apache.poi.hssf.usermodel.HSSFRow;
5 | import org.apache.poi.ss.usermodel.Cell;
6 |
7 | public class DBResultPumpSetting
8 | {
9 | private int m_Index;
10 | private String m_Time;
11 | private Double m_TimeBoundValue;
12 |
13 | private final int m_SettingsFields = 3;
14 |
15 | // Utility Function for getting a cell from row as string even if numeric
16 | public static String getCellAsString(HSSFRow row, int index)
17 | {
18 | String result = "";
19 | Cell cell = row.getCell(index);
20 | if (cell != null)
21 | {
22 | // Check type of this cell first
23 | if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING)
24 | {
25 | result = cell.getStringCellValue();
26 | }
27 | else
28 | {
29 | Double result_num = cell.getNumericCellValue();
30 | result = result_num.toString();
31 | }
32 | }
33 | return result;
34 | }
35 |
36 | DBResultPumpSetting(HSSFRow row)
37 | {
38 | int maxColumns = row.getPhysicalNumberOfCells();
39 | if (maxColumns == m_SettingsFields)
40 | {
41 | Double cell1 = row.getCell(0).getNumericCellValue();
42 | String cell2 = row.getCell(1).getStringCellValue();
43 | Double cell3 = row.getCell(2).getNumericCellValue();
44 |
45 | m_Index = cell1.intValue();
46 | m_Time = cell2;
47 | m_TimeBoundValue = cell3;
48 | }
49 | }
50 |
51 | public String toString()
52 | {
53 | return String.format("Index: %d, Time: %s, Value: %g",
54 | m_Index, m_Time, m_TimeBoundValue);
55 | }
56 |
57 | /**
58 | * @return the m_Index
59 | */
60 | public synchronized int getM_Index() {
61 | return m_Index;
62 | }
63 |
64 | /**
65 | * @param m_Index the m_Index to set
66 | */
67 | public synchronized void setM_Index(int m_Index) {
68 | this.m_Index = m_Index;
69 | }
70 |
71 | /**
72 | * @return the m_Time
73 | */
74 | public synchronized String getM_Time() {
75 | return m_Time;
76 | }
77 |
78 | /**
79 | * @param m_Time the m_Time to set
80 | */
81 | public synchronized void setM_Time(String m_Time) {
82 | this.m_Time = m_Time;
83 | }
84 |
85 | /**
86 | * @return the m_TimeBoundValue
87 | */
88 | public synchronized Double getM_TimeBoundValue() {
89 | return m_TimeBoundValue;
90 | }
91 |
92 | /**
93 | * @param m_TimeBoundValue the m_TimeBoundValue to set
94 | */
95 | public synchronized void setM_TimeBoundValue(Double m_TimeBoundValue) {
96 | this.m_TimeBoundValue = m_TimeBoundValue;
97 | }
98 |
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/control/MainNightScoutLoader.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.awt.EventQueue;
4 | import java.io.IOException;
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 |
8 | import win.WinNightScoutLoader;
9 |
10 | public class MainNightScoutLoader implements MainControlInterface
11 | {
12 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
13 | // private static final MyLogger m_MyLogger = new MyLogger(true);
14 |
15 | private CommandLineHandlerSingleThreaded commandLineHandler;
16 | // private CommandLineHandlerMultiThreaded commandLineHandler;
17 |
18 | public MainNightScoutLoader(String[] args)
19 | {
20 | commandLineHandler = new CommandLineHandlerSingleThreaded(args, this);
21 | // commandLineHandler = new CommandLineHandlerMultiThreaded(args, this);
22 | }
23 |
24 | /**
25 | * Launch the application.
26 | */
27 | public static void main(String[] args)
28 | {
29 | // Initialise the Logging mechanism.
30 | try
31 | {
32 | Boolean consolLoggingBoolean = args == null || args.length == 0 ? false : true;
33 |
34 | MyLogger.setup(consolLoggingBoolean);
35 | }
36 | catch (IOException e1)
37 | {
38 | // Can;t use the logging mechanism, so simply output to SYSTEM
39 | // TODO Auto-generated catch block
40 | e1.printStackTrace();
41 | }
42 |
43 | MainNightScoutLoader mainNightScoutLoader = new MainNightScoutLoader(args);
44 |
45 | if (mainNightScoutLoader.commandLineHandler.launchWindow())
46 | {
47 | mainNightScoutLoader.launchWindow();
48 | }
49 | else
50 | {
51 | mainNightScoutLoader.launchCommandLineLoader();
52 | }
53 | }
54 |
55 | private void launchWindow()
56 | {
57 | EventQueue.invokeLater(new Runnable()
58 | {
59 | public void run()
60 | {
61 | try
62 | {
63 | //http://stackoverflow.com/questions/7612592/jframe-and-nimbus-look-and-feel
64 | // JFrame.setDefaultLookAndFeelDecorated(true); //before creating JFrames
65 |
66 | WinNightScoutLoader mainWin;
67 | mainWin = new WinNightScoutLoader();
68 | mainWin.setVisible(true);
69 | }
70 | catch (Exception e)
71 | {
72 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "Main: unhandled exception " + e.getLocalizedMessage());
73 | System.out.println("SEVERE ERROR : " + e.getLocalizedMessage());
74 | }
75 | }
76 | });
77 | }
78 |
79 | private void launchCommandLineLoader()
80 | {
81 | commandLineHandler.runWithoutWindow();
82 | }
83 |
84 | @Override
85 | public void shutdown()
86 | {
87 | m_Logger.log(Level.INFO, "Operation complete. Shutting down");
88 |
89 | Runtime rtRuntime = Runtime.getRuntime();
90 | rtRuntime.exit(0);
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/win/WinAbout.java:
--------------------------------------------------------------------------------
1 | package win;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.FlowLayout;
5 | import java.awt.Font;
6 |
7 | import javax.swing.ImageIcon;
8 | import javax.swing.JButton;
9 | import javax.swing.JDialog;
10 | import javax.swing.JPanel;
11 | import javax.swing.border.EmptyBorder;
12 |
13 | import control.MainNightScoutLoader;
14 |
15 | import javax.swing.JTextArea;
16 | import java.awt.event.ActionListener;
17 | import java.net.URL;
18 | import java.awt.event.ActionEvent;
19 | import javax.swing.JScrollPane;
20 | import control.Version;
21 |
22 | public class WinAbout extends JDialog {
23 |
24 | /**
25 | *
26 | */
27 | private static final long serialVersionUID = -51832866421758739L;
28 |
29 | private final JPanel contentPanel = new JPanel();
30 |
31 | private String m_AboutText;
32 |
33 | /**
34 | * Create the dialog.
35 | */
36 | public WinAbout(String title)
37 | {
38 | super.setTitle(title);
39 |
40 | URL url = MainNightScoutLoader.class.getResource("/Nightscout.jpg");
41 | ImageIcon img = new ImageIcon(url);
42 | setIconImage(img.getImage());
43 |
44 | m_AboutText = new String();
45 |
46 | m_AboutText = Version.getInstance().getM_AboutText();
47 |
48 | setBounds(100, 100, 750, 600);
49 | getContentPane().setLayout(new BorderLayout());
50 | contentPanel.setLayout(new FlowLayout());
51 | contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
52 | getContentPane().add(contentPanel, BorderLayout.CENTER);
53 |
54 | JPanel buttonPane = new JPanel();
55 | buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
56 | getContentPane().add(buttonPane, BorderLayout.SOUTH);
57 | {
58 | JButton okButton = new JButton("OK");
59 | okButton.addActionListener(new ActionListener() {
60 | public void actionPerformed(ActionEvent arg0) {
61 | setVisible(false);
62 | }
63 | });
64 | okButton.setActionCommand("OK");
65 | buttonPane.add(okButton);
66 | getRootPane().setDefaultButton(okButton);
67 | }
68 | {
69 | JButton cancelButton = new JButton("Cancel");
70 | cancelButton.addActionListener(new ActionListener() {
71 | public void actionPerformed(ActionEvent arg0) {
72 | setVisible(false);
73 | }
74 | });
75 | cancelButton.setActionCommand("Cancel");
76 | buttonPane.add(cancelButton);
77 | }
78 |
79 | Font font = new Font("Courier", Font.BOLD, 12);
80 |
81 |
82 | JTextArea txtrNightscoutloader = new JTextArea();
83 | getContentPane().add(txtrNightscoutloader, BorderLayout.WEST);
84 | txtrNightscoutloader.setFont(font);
85 |
86 | txtrNightscoutloader.setText(m_AboutText);
87 |
88 | JScrollPane scrollPane = new JScrollPane(txtrNightscoutloader);
89 | getContentPane().add(scrollPane, BorderLayout.CENTER);
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/BinaryFileFieldAccess.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.nio.ByteOrder;
5 |
6 | public class BinaryFileFieldAccess
7 | {
8 | // private byte[] m_RawData = null;
9 |
10 | BinaryFileFieldAccess(byte[] rawdata)
11 | {
12 | // m_RawData = rawdata;
13 | }
14 |
15 | public int extractInt(byte[] rawdata, int offset)
16 | {
17 | int result = ByteBuffer.wrap(rawdata,offset,4).order(ByteOrder.LITTLE_ENDIAN).getInt();
18 | return result;
19 | }
20 | public int extractSignedInt(byte[] rawdata, int offset)
21 | {
22 | int result = extractInt(rawdata, offset);
23 | return result;
24 | }
25 |
26 | public short extractShort(byte[] rawdata, int offset)
27 | {
28 | short result = ByteBuffer.wrap(rawdata,offset,4).order(ByteOrder.LITTLE_ENDIAN).getShort();
29 | return result;
30 | }
31 | public short extractSignedShort(byte[] rawdata, int offset)
32 | {
33 | short result = extractShort(rawdata, offset);
34 | return result;
35 | }
36 |
37 | public byte extractbyte(byte[] rawdata, int offset)
38 | {
39 | return rawdata[offset];
40 | }
41 |
42 | public byte extractSignedbyte(byte[] rawdata, int offset)
43 | {
44 | byte result = extractbyte(rawdata, offset);
45 |
46 | result = (byte) ((result & 127) - (result & 128));
47 | return result;
48 | }
49 |
50 | public String extractbytes(byte[] rawdata, int offset, int len)
51 | {
52 | String result = new String();
53 | for (int c = offset; c < offset + len; c++)
54 | {
55 | result += rawdata[c];
56 | }
57 |
58 | return result;
59 | }
60 |
61 | public float extractFloat(byte[] rawdata, int offset)
62 | {
63 | float result = ByteBuffer.wrap(rawdata,offset,4).order(ByteOrder.LITTLE_ENDIAN).getFloat();
64 | return result;
65 | }
66 |
67 | public int extractBEInt(byte[] rawdata, int offset)
68 | {
69 | int result = ByteBuffer.wrap(rawdata,offset,4).order(ByteOrder.BIG_ENDIAN).getInt();
70 | return result;
71 | }
72 |
73 | public int extractBESignedInt(byte[] rawdata, int offset)
74 | {
75 | int result = extractBEInt(rawdata, offset);
76 | return result;
77 | }
78 |
79 | public short extractBEShort(byte[] rawdata, int offset)
80 | {
81 | short result = ByteBuffer.wrap(rawdata,offset,4).order(ByteOrder.BIG_ENDIAN).getShort();
82 | return result;
83 | }
84 |
85 | public short extractBESignedShort(byte[] rawdata, int offset)
86 | {
87 | short result = extractBEShort(rawdata, offset);
88 | return result;
89 | }
90 |
91 | public String extractZString(byte[] rawdata, int offset, int len)
92 | {
93 | String result = extractbytes(rawdata, offset, len);
94 | return result;
95 | }
96 | public String extractString(byte[] rawdata, int offset, int len)
97 | {
98 | String result = extractbytes(rawdata, offset, len);
99 | return result;
100 | }
101 | }
102 |
103 |
104 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/OmniPodBinaryFileSection.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class OmniPodBinaryFileSection
6 | {
7 | protected String m_SectionHeader;
8 | protected String m_Encoding;
9 | protected ArrayList m_FieldNames;
10 | protected ArrayList m_FieldValues;
11 | protected OmniPodValidator m_Validator = null;
12 |
13 | public OmniPodBinaryFileSection(String sectionHeader, String encoding, String[] fieldNames)
14 | {
15 | m_SectionHeader = new String(sectionHeader);
16 | m_Encoding = new String(encoding);
17 | m_FieldNames = new ArrayList();
18 | m_FieldValues = new ArrayList();
19 |
20 | if (fieldNames != null)
21 | {
22 | for (String f : fieldNames)
23 | {
24 | m_FieldNames.add(f);
25 | }
26 | }
27 | }
28 |
29 | public OmniPodBinaryFileSection(String sectionHeader, String encoding,
30 | String[] fieldNames,
31 | OmniPodValidator validator)
32 | {
33 | m_SectionHeader = new String(sectionHeader);
34 | m_Encoding = new String(encoding);
35 | m_FieldNames = new ArrayList();
36 | m_FieldValues = new ArrayList();
37 |
38 | for (String f : fieldNames)
39 | {
40 | m_FieldNames.add(f);
41 | }
42 | m_Validator = validator;
43 | }
44 |
45 | public OmniPodBinaryFileSection(String sectionHeader, String encoding,
46 | String[] fieldNames, String[] fieldValues)
47 | {
48 | m_SectionHeader = new String(sectionHeader);
49 | m_Encoding = new String(encoding);
50 | m_FieldNames = new ArrayList();
51 | m_FieldValues = new ArrayList();
52 |
53 | for (String f : fieldNames)
54 | {
55 | m_FieldNames.add(f);
56 | }
57 | for (String f : fieldValues)
58 | {
59 | m_FieldValues.add(f);
60 | }
61 | }
62 |
63 | public OmniPodBinaryFileSection(String sectionHeader, String encoding,
64 | String[] fieldNames, String[] fieldValues,
65 | OmniPodValidator validator)
66 | {
67 | m_SectionHeader = new String(sectionHeader);
68 | m_Encoding = new String(encoding);
69 | m_FieldNames = new ArrayList();
70 | m_FieldValues = new ArrayList();
71 |
72 | for (String f : fieldNames)
73 | {
74 | m_FieldNames.add(f);
75 | }
76 | for (String f : fieldValues)
77 | {
78 | m_FieldValues.add(f);
79 | }
80 | m_Validator = validator;
81 | }
82 |
83 | /**
84 | * @return the m_SectionHeader
85 | */
86 | public synchronized String getM_SectionHeader() {
87 | return m_SectionHeader;
88 | }
89 |
90 | /**
91 | * @param m_SectionHeader the m_SectionHeader to set
92 | */
93 | public synchronized void setM_SectionHeader(String m_SectionHeader) {
94 | this.m_SectionHeader = m_SectionHeader;
95 | }
96 |
97 | /**
98 | * @return the m_Encoding
99 | */
100 | public synchronized String getM_Encoding() {
101 | return m_Encoding;
102 | }
103 |
104 | /**
105 | * @param m_Encoding the m_Encoding to set
106 | */
107 | public synchronized void setM_Encoding(String m_Encoding) {
108 | this.m_Encoding = m_Encoding;
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/java/analysis/AnalyzerTrendResultEntryComparator.java:
--------------------------------------------------------------------------------
1 | package analysis;
2 |
3 | import java.util.Comparator;
4 |
5 | import analysis.AnalyzerResultEntryInterval.DBResultEntryProfileDirection;
6 |
7 |
8 | public class AnalyzerTrendResultEntryComparator implements Comparator
9 | {
10 | private boolean m_DescendingSort = true;
11 | private AnalyzerTrendResultEntryComparatorType m_CompType = AnalyzerTrendResultEntryComparatorType.NumericSort;
12 |
13 | public enum AnalyzerTrendResultEntryComparatorType
14 | {
15 | NumericSort,
16 | TimeSort,
17 | TypeSort,
18 | };
19 |
20 | AnalyzerTrendResultEntryComparator()
21 | {
22 | m_DescendingSort = true;
23 | }
24 | AnalyzerTrendResultEntryComparator(boolean descendingSort)
25 | {
26 | m_DescendingSort = descendingSort;
27 | }
28 | AnalyzerTrendResultEntryComparator(boolean descendingSort,
29 | AnalyzerTrendResultEntryComparatorType compType)
30 | {
31 | m_DescendingSort = descendingSort;
32 | m_CompType = compType;
33 | }
34 |
35 | public int compare(AnalyzerTrendResultEntry p1, AnalyzerTrendResultEntry p2)
36 | {
37 | int result = 0;
38 |
39 | int p1_entries = p1.getM_ResultEntryIntervals().size();
40 | int p2_entries = p2.getM_ResultEntryIntervals().size();
41 |
42 | // DBResultEntryProfileChange p1_profile = p1.getM_DBResultEntryProfileChange();
43 | // DBResultEntryProfileChange p2_profile = p2.getM_DBResultEntryProfileChange();
44 |
45 | DBResultEntryProfileDirection p1_direction = p1.getM_ProfileDirection();
46 | DBResultEntryProfileDirection p2_direction = p2.getM_ProfileDirection();
47 |
48 |
49 | // Subtraction is too big for int result
50 | long diff = p1_entries - p2_entries;
51 | int timeDiff = p1.getM_StartHour() - p2.getM_StartHour();
52 | int profileDiff = p1_direction.hashCode() - p2_direction.hashCode(); // this will do
53 |
54 | // Sort based on number of entries and then also by time
55 | if ( // Numeric Sort
56 | (m_CompType == AnalyzerTrendResultEntryComparatorType.NumericSort
57 | && (diff > 0) || (diff == 0 && timeDiff < 0) )
58 |
59 | ||
60 | // Time Sort
61 | ((m_CompType == AnalyzerTrendResultEntryComparatorType.TimeSort
62 | && timeDiff < 0))
63 |
64 | ||
65 | // Type Sort
66 | ((m_CompType == AnalyzerTrendResultEntryComparatorType.TypeSort
67 | && profileDiff < 0))
68 | )
69 | {
70 | // 1 to get results in ascending order
71 | // -1 to get results in descending order
72 | result = m_DescendingSort ? -1 : 1;
73 | }
74 | // else if ( (diff < 0) || (diff == 0 && timeDiff > 0) )
75 | else if ( // Numeric Sort
76 | (m_CompType == AnalyzerTrendResultEntryComparatorType.NumericSort
77 | && (diff < 0) || (diff == 0 && timeDiff > 0) )
78 |
79 | ||
80 | // Time Sort
81 | ((m_CompType == AnalyzerTrendResultEntryComparatorType.TimeSort
82 | && timeDiff > 0))
83 |
84 | ||
85 | // Type Sort
86 | ((m_CompType == AnalyzerTrendResultEntryComparatorType.TypeSort
87 | && profileDiff < 0))
88 | )
89 |
90 | {
91 | // -1 to get results in ascending order
92 | // 1 to get results in descending order
93 | result = m_DescendingSort ? 1 : -1;
94 | }
95 |
96 | return result;
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/test/java/loader/TestDiasendTreatmentInsCarbNotMerged.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.text.SimpleDateFormat;
4 |
5 | import org.junit.jupiter.api.Assertions;
6 | import org.junit.jupiter.api.Test;
7 | import org.junit.runner.RunWith;
8 | import org.mockito.junit.MockitoJUnitRunner;
9 |
10 | @RunWith(MockitoJUnitRunner.class)
11 | public class TestDiasendTreatmentInsCarbNotMerged extends BaseTestTreatment {
12 |
13 | private static final String RESOURCE_FILE_NAME_STRING = "Sample_Diasend2.xls";
14 |
15 |
16 | private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm");
17 |
18 | private static Object[][] EXPECTED_TREATMENT_RESULTS =
19 | {
20 | // Date of Reading BG INS CARBS DUPE?
21 | { "20/03/2021 19:01", 0.0, 6.80, 0.00, "NO"},
22 | { "28/03/2021 15:41", 0.0, 4.05, 45.00, "YES"},
23 | { "28/03/2021 15:41", 0.0, 4.05, 45.00, "NO"},
24 | { "06/04/2021 00:00", 0.0, 1.30, 0.00, "NO"},
25 | { "09/04/2021 00:00", 0.0, 1.60, 0.00, "NO"},
26 | { "13/04/2021 19:44", 0.0, 5.00, 50.00, "YES"},
27 | { "13/04/2021 19:44", 0.0, 5.00, 50.00, "NO"},
28 | { "15/04/2021 00:00", 0.0, 2.70, 0.00, "NO"},
29 | { "27/05/2021 00:00", 0.0, 0.95, 0.00, "NO"},
30 | { "12/06/2021 00:00", 0.0, 3.05, 0.00, "NO"},
31 | { "08/07/2021 20:44", 0.0, 4.00, 40.00, "YES"},
32 | { "08/07/2021 20:44", 0.0, 4.00, 40.00, "NO"},
33 | { "23/07/2021 00:00", 0.0, 0.35, 0.00, "NO"},
34 | { "10/09/2021 00:00", 0.0, 0.95, 0.00, "NO"},
35 | { "03/10/2021 17:45", 0.0, 3.15, 35.00, "YES"},
36 | { "03/10/2021 17:45", 0.0, 3.15, 35.00, "NO"},
37 | { "04/10/2021 11:52", 0.0, 4.05, 45.00, "YES"},
38 | { "04/10/2021 11:52", 0.0, 4.05, 45.00, "NO"},
39 |
40 | };
41 |
42 | DataLoadFile dataLoadFile = new DataLoadDiasend();
43 |
44 | @Test
45 | public void doTestLoad()
46 | {
47 | String nameofCurrMethod = new Throwable()
48 | .getStackTrace()[0]
49 | .getMethodName();
50 | System.out.println("[INFO] *** TEST *** " + this.getClass().getSimpleName() + "." + nameofCurrMethod);
51 | performTestLoad();
52 | }
53 |
54 | @Test
55 | public void doTestCount()
56 | {
57 | String nameofCurrMethod = new Throwable()
58 | .getStackTrace()[0]
59 | .getMethodName();
60 | System.out.println("[INFO] *** TEST *** " + this.getClass().getSimpleName() + "." + nameofCurrMethod);
61 | doDataLoad();
62 |
63 | int dlEntries = this.countDataLoadEntries(false);
64 | int exEntries = this.countExpectedResults();
65 |
66 | Assertions.assertTrue( dlEntries == exEntries, "Expect record counts of entries without BG to match data set provided. "
67 | + dlEntries + " in data load, "
68 | + exEntries + " in data set provided.");
69 | }
70 |
71 | @Override
72 | protected Object[][] getExpectedTestResults() {
73 | return EXPECTED_TREATMENT_RESULTS;
74 | }
75 |
76 | @Override
77 | protected String getResourceFileName() {
78 | return RESOURCE_FILE_NAME_STRING;
79 | }
80 |
81 | @Override
82 | protected DataLoadFile getDataLoadFile() {
83 | return dataLoadFile;
84 | }
85 |
86 | @Override
87 | protected SimpleDateFormat getSimpleDateFormat() {
88 | return DATE_FORMAT;
89 | }
90 |
91 | @Override
92 | protected String getDateFormat() {
93 | return "dd/MM/yyyy HH:mm";
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/analysis/AnalyzerTrendResultEntryAggregate.java:
--------------------------------------------------------------------------------
1 | package analysis;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class AnalyzerTrendResultEntryAggregate
6 | {
7 | // David -- getting tired
8 | // Group these into a single class for easier access.
9 | // 16 Dec 2016
10 |
11 | private static Integer m_Static_ID = 0; // Assign an ID to each result created.
12 | private int m_ID = 0; // Assign an ID to each result created.
13 |
14 | private AnalyzerTrendResultAggregateGroup m_OffsetMinusTwoAggregateGroup;
15 | private AnalyzerTrendResultAggregateGroup m_OffsetMinusOneAggregateGroup;
16 | private AnalyzerTrendResultAggregateGroup m_NoOffsetAggregateGroup;
17 | private AnalyzerTrendResultAggregateGroup m_OffsetPlusOneAggregateGroup;
18 | private AnalyzerTrendResultAggregateGroup m_OffsetPlusTwoAggregateGroup;
19 |
20 | AnalyzerTrendResultEntryAggregate()
21 | {
22 | m_Static_ID++;
23 | m_ID = m_Static_ID;
24 |
25 | m_OffsetMinusTwoAggregateGroup = new AnalyzerTrendResultAggregateGroup();
26 | m_OffsetMinusOneAggregateGroup = new AnalyzerTrendResultAggregateGroup();
27 | m_NoOffsetAggregateGroup = new AnalyzerTrendResultAggregateGroup();
28 | m_OffsetPlusOneAggregateGroup = new AnalyzerTrendResultAggregateGroup();
29 | m_OffsetPlusTwoAggregateGroup = new AnalyzerTrendResultAggregateGroup();
30 | }
31 |
32 | public void initialize(ArrayList trendResultEntries,
33 | ArrayList trendResultEntriesPlusOne,
34 | ArrayList trendResultEntriesPlusTwo,
35 | ArrayList trendResultEntriesMinusOne,
36 | ArrayList trendResultEntriesMinusTwo)
37 | {
38 | m_OffsetMinusTwoAggregateGroup.initialize(trendResultEntriesMinusTwo);
39 | m_OffsetMinusOneAggregateGroup.initialize(trendResultEntriesMinusOne);
40 | m_NoOffsetAggregateGroup.initialize(trendResultEntries);
41 | m_OffsetPlusOneAggregateGroup.initialize(trendResultEntriesPlusOne);
42 | m_OffsetPlusTwoAggregateGroup.initialize(trendResultEntriesPlusTwo);
43 | }
44 |
45 | public synchronized static void resetStaticID()
46 | {
47 | m_Static_ID = 0;
48 | }
49 |
50 | /**
51 | * @return the m_ID
52 | */
53 | public synchronized int getM_ID() {
54 | return m_ID;
55 | }
56 |
57 |
58 | /**
59 | * @return the m_OffsetMinusTwoAggregateGroup
60 | */
61 | public synchronized AnalyzerTrendResultAggregateGroup getM_OffsetMinusTwoAggregateGroup() {
62 | return m_OffsetMinusTwoAggregateGroup;
63 | }
64 |
65 | /**
66 | * @return the m_OffsetMinusOneAggregateGroup
67 | */
68 | public synchronized AnalyzerTrendResultAggregateGroup getM_OffsetMinusOneAggregateGroup() {
69 | return m_OffsetMinusOneAggregateGroup;
70 | }
71 |
72 | /**
73 | * @return the m_NoOffsetAggregateGroup
74 | */
75 | public synchronized AnalyzerTrendResultAggregateGroup getM_NoOffsetAggregateGroup() {
76 | return m_NoOffsetAggregateGroup;
77 | }
78 |
79 | /**
80 | * @return the m_OffsetPlusOneAggregateGroup
81 | */
82 | public synchronized AnalyzerTrendResultAggregateGroup getM_OffsetPlusOneAggregateGroup() {
83 | return m_OffsetPlusOneAggregateGroup;
84 | }
85 |
86 | /**
87 | * @return the m_OffsetPlusTwoAggregateGroup
88 | */
89 | public synchronized AnalyzerTrendResultAggregateGroup getM_OffsetPlusTwoAggregateGroup() {
90 | return m_OffsetPlusTwoAggregateGroup;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadHelpLauncher.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.awt.Desktop;
4 | import java.io.File;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.util.ArrayList;
9 | import java.util.logging.Level;
10 | import java.util.logging.Logger;
11 |
12 | public class ThreadHelpLauncher implements Runnable
13 | {
14 | private static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
15 |
16 | // Separate thread for Analyzer to run
17 | private Thread m_HelpLauncherThread;
18 |
19 | private ArrayList m_RequestList = new ArrayList();
20 |
21 | // static Object m_Lock = new Object();
22 | private Object m_Lock;
23 |
24 | // Thread Synchronization
25 | public void waitUntilFree()
26 | {
27 | synchronized(m_Lock)
28 | {
29 | while (m_RequestList.isEmpty())
30 | {
31 | try
32 | {
33 | m_Logger.log( Level.FINE, "ThreadHelpLauncher Wait - Running & about to try lock: " + this );
34 | m_Lock.wait();
35 | m_Logger.log( Level.FINE, "ThreadHelpLauncher Wait - Running & notified : " + this );
36 | }
37 | catch (InterruptedException e)
38 | {
39 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "ThreadHelpLauncher Wait - EXCEPTION CAUGHT.", e);
40 | }
41 | }
42 | m_Logger.log( Level.FINE, "ThreadHelpLauncher Wait - No longer running: " + this);
43 | }
44 | }
45 |
46 | public ThreadHelpLauncher()
47 | {
48 | // Start thread immediately on creation
49 | m_HelpLauncherThread = new Thread(this);
50 | m_HelpLauncherThread.start();
51 |
52 | // Thread synchronization
53 | m_Lock = new Object();
54 | }
55 |
56 |
57 | public synchronized void addHelpRequest(String resName)
58 | {
59 | this.m_RequestList.add(resName);
60 | }
61 |
62 | public void run()
63 | {
64 | // Endless loop for this thread
65 | while(true)
66 | {
67 | waitUntilFree();
68 |
69 | synchronized(m_Lock)
70 | {
71 | // Launch the analyze method
72 | if (!m_RequestList.isEmpty())
73 | {
74 | String file = m_RequestList.get(0);
75 | m_RequestList.remove(0);
76 |
77 | openPdf(file);
78 |
79 | m_Lock.notifyAll();
80 | }
81 | }
82 | }
83 | }
84 |
85 | public void openPdf(String pdf)
86 | {
87 | if (Desktop.isDesktopSupported())
88 | {
89 | m_Logger.log(Level.INFO, "Opening the help file. Will take a few seconds ...");
90 |
91 | // InputStream jarPdf = getClass().getClassLoader().getResourceAsStream(pdf);
92 | InputStream jarPdf = MainNightScoutLoader.class.getResourceAsStream(pdf);
93 |
94 | try
95 | {
96 | File pdfTemp = new File("NightscoutLoader_Temp.pdf");
97 | // Extraction du PDF qui se situe dans l'archive
98 | FileOutputStream fos = new FileOutputStream(pdfTemp);
99 | while (jarPdf.available() > 0)
100 | {
101 | fos.write(jarPdf.read());
102 | } // while (pdfInJar.available() > 0)
103 | fos.close();
104 | // Ouverture du PDF
105 | Desktop.getDesktop().open(pdfTemp);
106 | } // try
107 |
108 | catch (IOException e)
109 | {
110 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + " openPdf Exception caught opening " + pdf, e);
111 |
112 | } // catch (IOException e)
113 |
114 | m_Logger.log(Level.INFO, "Help file opened");
115 | }
116 |
117 | else
118 | {
119 | m_Logger.log(Level.WARNING, "<"+this.getClass().getName()+">" + " Desktop Not Supported ");
120 | }
121 |
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/loader/DataLoadNightScoutEntries.java:
--------------------------------------------------------------------------------
1 | package loader;
2 | import com.mongodb.BasicDBObject;
3 | import com.mongodb.BasicDBObjectBuilder;
4 | import com.mongodb.DBCollection;
5 | import com.mongodb.DBCursor;
6 | import com.mongodb.DBObject;
7 | import control.MyLogger;
8 | import control.PrefsNightScoutLoader;
9 | import entity.DBResultEntry;
10 | import mongo.NightscoutMongoDB;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Date;
14 | import java.util.logging.Level;
15 | import java.util.logging.Logger;
16 | import java.net.UnknownHostException;
17 |
18 | public class DataLoadNightScoutEntries extends DataLoadNightScout
19 | {
20 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
21 | // private static final int m_FailedTestLimit = 2;
22 |
23 | // private static Integer m_FailedTests = 0;
24 |
25 | private ArrayList resultsFromDB;
26 |
27 | public DataLoadNightScoutEntries()
28 | {
29 | super();
30 | resultsFromDB = new ArrayList();
31 | }
32 |
33 | static public Date getEntryLoadStartDate()
34 | {
35 | int weeksBack = PrefsNightScoutLoader.getInstance().getM_WeeksBackToLoadEntries();
36 | Date now = new Date();
37 | long nowLong = now.getTime();
38 | long thenLong = nowLong - ((long)weeksBack * 7 * 24 * 3600 * 1000); // Arrghh - need to cast this weeks back else get garbage future date!
39 | Date result = new Date(thenLong);
40 |
41 | return result;
42 | }
43 |
44 | public void loadDBResults() throws UnknownHostException
45 | {
46 | /*
47 | * int weeksBack = PrefsNightScoutLoader.getInstance().getM_WeeksBackToLoadEntries();
48 | Date now = new Date();
49 | long nowLong = now.getTime();
50 | long thenLong = nowLong - ((long)weeksBack * 7 * 24 * 3600 * 1000); // Arrghh - need to cast this weeks back else get garbage future date!
51 | Date startDate = new Date(thenLong);
52 |
53 | // final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
54 | // String nowString = new String(df.format(now));
55 | // String startDatetring = new String(df.format(startDate));
56 |
57 | loadDBResults(startDate);
58 | */
59 |
60 | loadDBResults(getEntryLoadStartDate());
61 | }
62 |
63 | public void loadDBResults(Date startDate) throws UnknownHostException
64 | {
65 | testMongo();
66 |
67 | if (m_ServerState == MongoDBServerStateEnum.accessible)
68 | {
69 | String timeFld = new String("date");
70 |
71 | NightscoutMongoDB nsMongoDB = new NightscoutMongoDB();
72 | DBCollection coll = nsMongoDB.getSensorV2xCollection();
73 |
74 | resultsFromDB = new ArrayList();
75 |
76 | BasicDBObject query = new BasicDBObject();
77 | // Load *all* results
78 | query.put(timeFld, BasicDBObjectBuilder.start("$gte", startDate.getTime()).get());
79 |
80 | m_Logger.log(Level.FINE, "loadDBResults Mongo Query is now " + query.toString());
81 |
82 | DBCursor cursor = coll.find(query);
83 | // Sort by time
84 | cursor.sort(new BasicDBObject(timeFld, 1));
85 |
86 | for (DBObject rs: cursor)
87 | {
88 | // Now create Result objects for each document and store into array
89 | //ResultFromDB res = new ResultFromDB(rs);
90 |
91 | // Switch to new object type
92 | DBResultEntry res = new DBResultEntry(rs);
93 |
94 | resultsFromDB.add(res);
95 |
96 | m_Logger.log(Level.FINEST, "Result added for Nightscout Sensor Result " + rs.toString());
97 | }
98 |
99 | nsMongoDB.close();
100 | }
101 |
102 | }
103 |
104 | public ArrayList getResultsFromDB()
105 | {
106 | return resultsFromDB;
107 | }
108 |
109 |
110 | @Override
111 | protected String getDevice()
112 | {
113 | return new String(""); // Not used
114 | }
115 |
116 | @Override
117 | protected String getRequestType()
118 | {
119 | return new String ("Data Load Entries ");
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/loader/DataLoadRocheCSV.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | import control.MyLogger;
11 | import entity.DBResult;
12 | import entity.DBResultRoche;
13 |
14 | public class DataLoadRocheCSV extends DataLoadCSVFile
15 | {
16 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
17 | private static final String m_RocheSplitBy = "\t";
18 |
19 | @Override
20 | protected DBResult makeDBResult(String[] res)
21 | {
22 | DBResultRoche result = new DBResultRoche(res);
23 | return result;
24 | }
25 |
26 | @Override
27 | protected String loadStringName()
28 | {
29 | return "Roche";
30 | }
31 |
32 | @Override
33 | protected String getSplitBy()
34 | {
35 | return m_RocheSplitBy;
36 | }
37 |
38 | public static boolean isRoche(String fileName)
39 | {
40 | boolean result = false;
41 | BufferedReader br = null;
42 | String line = "";
43 | String cvsSplitBy = m_RocheSplitBy;
44 |
45 | // Expected Format
46 | boolean ln1Year = false;
47 | boolean ln1Month = false;
48 | boolean ln1Day = false;
49 | boolean ln1DayName = false;
50 | boolean ln1Time = false; // 640
51 | boolean ln1TimeSlot = false; // Veo
52 | boolean ln1Result = false; // Veo
53 | boolean ln1ResultType = false; // Veo
54 | boolean ln1MealType = false; // Veo
55 | boolean ln1Duration = false; // Veo
56 |
57 | int ln = 0;
58 | int maxLines = 1; // Just one line
59 |
60 | try
61 | {
62 | br = new BufferedReader(new FileReader(fileName));
63 | while ((ln <= maxLines) && (line = br.readLine()) != null)
64 | {
65 | ln++;
66 | // use comma as separator
67 | String[] rs = line.split(cvsSplitBy);
68 |
69 | if (ln == 1)
70 | {
71 | int i = 0;
72 | ln1Year = (rs.length > i && rs[i++].equals("Year")) ? true : false;
73 | ln1Month = (rs.length > i && rs[i++].equals("Month")) ? true : false;
74 | ln1Day = (rs.length > i && rs[i++].equals("Day")) ? true : false;
75 | ln1DayName = (rs.length > i && rs[i++].equals("DayName")) ? true : false;
76 | ln1Time = (rs.length > i && rs[i++].equals("Time")) ? true : false;
77 | ln1TimeSlot = (rs.length > i && rs[i++].equals("TimeSlot")) ? true : false;
78 | ln1Result = (rs.length > i && rs[i++].equals("Result")) ? true : false;
79 | ln1ResultType = (rs.length > i && rs[i++].equals("ResultType")) ? true : false;
80 | ln1MealType = (rs.length > i && rs[i++].equals("MealType")) ? true : false;
81 | ln1Duration = (rs.length > i && rs[i++].equals("Duration")) ? true : false;
82 |
83 | }
84 |
85 | }
86 |
87 | result = (ln1Year == true && ln1Month == true && ln1Day == true &&
88 | ln1DayName == true && ln1Time == true && ln1TimeSlot == true &&
89 | ln1Result == true && ln1ResultType == true && ln1MealType == true && ln1Duration == true) ? true : false;
90 |
91 | }
92 | catch (FileNotFoundException e)
93 | {
94 | m_Logger.log(Level.SEVERE, "" + "isRoche: FileNotFoundException. File " + fileName + " Error " + e.getMessage());
95 |
96 | e.printStackTrace();
97 | }
98 | catch (IOException e)
99 | {
100 | m_Logger.log(Level.SEVERE, "" + "isRoche: IOException. File " + fileName + " Error " + e.getMessage());
101 | e.printStackTrace();
102 | }
103 | finally
104 | {
105 | if (br != null)
106 | {
107 | try
108 | {
109 | br.close();
110 | }
111 | catch (IOException e)
112 | {
113 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: IOException closing file. File " + fileName + " Error " + e.getMessage());
114 | e.printStackTrace();
115 | }
116 | }
117 | }
118 |
119 | return result;
120 | }
121 |
122 |
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/src/test/java/control/TestMongoConnection.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 |
5 | import org.junit.jupiter.api.Assertions;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import com.mongodb.MongoClient;
9 | import com.mongodb.MongoClientURI;
10 | import com.mongodb.MongoSocketWriteException;
11 | import com.mongodb.MongoTimeoutException;
12 | import com.mongodb.client.MongoDatabase;
13 | import com.mongodb.client.MongoIterable;
14 |
15 | public class TestMongoConnection {
16 |
17 | private static String m_ValidMongoURIString = null;
18 | private static String m_ValidMongoDBString = null;
19 | private static String m_InValidMongoURIString = null;
20 | private static String m_InValidMongoDBString = null;
21 |
22 |
23 | public TestMongoConnection()
24 | {
25 | setup();
26 | }
27 |
28 | @Test
29 | public void test1()
30 | {
31 | // Support some level of Mongo connection testing without need to hard code sensitive
32 | // connection strings
33 | //
34 | // Instead, these get passed in through the mvn command as follows:
35 | //
36 | //
37 | // mvn -DVALID_MONGO_URI="mongodb+srv://valid_user:pass@heroku.mongo.net/db?retryWrites=true&w=majority" ^
38 | // -DVALID_MONGO_DB="db" ^
39 | // -DINVALID_MONGO_URI="mongodb+srv://invalid_user:pass@heroku.mongo.net/db?retryWrites=true&w=majority" ^
40 | // -DINVALID_MONGO_DB="db"
41 |
42 | m_ValidMongoURIString = System.getProperty("VALID_MONGO_URI");
43 | m_ValidMongoDBString = System.getProperty("VALID_MONGO_DB");
44 | m_InValidMongoURIString = System.getProperty("INVALID_MONGO_URI");
45 | m_InValidMongoDBString = System.getProperty("INVALID_MONGO_DB");
46 |
47 | testConnection(m_ValidMongoURIString, m_ValidMongoDBString, true);
48 | testConnection(m_InValidMongoURIString, m_InValidMongoDBString, false);
49 |
50 | // testConnection(uri3, db3);
51 | // testConnection(uri4, db4);
52 | }
53 |
54 | private void testConnection(String uri, String dbString, Boolean expectSucceed)
55 | {
56 | if (uri != null && uri.length() > 0 && dbString != null && dbString.length() > 0)
57 | {
58 | MongoClientURI dbURI = new MongoClientURI(uri);
59 | MongoClient mongo = new MongoClient(dbURI);
60 |
61 | Boolean connectionSuccessBoolean = true;
62 |
63 | try {
64 | MongoDatabase database = mongo.getDatabase(dbString);
65 |
66 | MongoIterable list = database.listCollectionNames();
67 | for (String name : list) {
68 | System.out.println(uri + " has " + name);
69 | }
70 | }
71 | catch (MongoSocketWriteException e)
72 | {
73 | connectionSuccessBoolean = false;
74 | }
75 | catch (MongoTimeoutException e)
76 | {
77 | connectionSuccessBoolean = false;
78 | }
79 | catch (Exception e)
80 | {
81 | connectionSuccessBoolean = false;
82 | }
83 |
84 | Assertions.assertTrue(expectSucceed == connectionSuccessBoolean,
85 | "Attempted connection to " + uri + ":" + dbString + ". Expected "
86 | + (expectSucceed == true ? "successful connection " : "failed connection")
87 | + " but got "
88 | + (connectionSuccessBoolean == true ? "successful connection " : "failed connection")
89 | );
90 |
91 | mongo.close();
92 | }
93 | else
94 | {
95 | System.out.println("**** Mongo Connection tests skipped. ****"
96 | + " (Test for connection success " + expectSucceed + ") "
97 | + "Use mvn parameters to set valid and invalid URIs for testing: "
98 | + " -DVALID_MONGO_URI & -DVALID_MONGO_DB, and -DINVALID_MONGO_URI & -DINVALID_MONGO_DB"
99 | );
100 | }
101 | }
102 |
103 | private void setup()
104 | {
105 | try {
106 |
107 | // Set log level to 10 (warning). Other new option is 20 (severe)
108 | // This quietens down the output significantly
109 | PrefsNightScoutLoader.getInstance().setM_LogLevel(10);
110 |
111 | MyLogger.setup(true);
112 | } catch (IOException e) {
113 | // TODO Auto-generated catch block
114 | e.printStackTrace();
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadAutotune.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.util.logging.Level;
4 | import java.util.logging.Logger;
5 |
6 | import miscellaneous.RemoteLinuxServer;
7 |
8 | abstract
9 | public class ThreadAutotune implements Runnable
10 | {
11 | protected static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
12 |
13 | // Separate thread for RemoteLinuxServer
14 | protected Thread m_AututuneThread;
15 |
16 | // Data Loader used by thread
17 | protected RemoteLinuxServer m_Autotuner;
18 |
19 | protected Boolean m_LoadRunning;
20 | // static Object m_Lock = new Object();
21 | protected Object m_Lock;
22 |
23 | // Sub classes must override this
24 | abstract protected void doAutotuneTask();
25 |
26 | // Thread Synchronization
27 | public void waitUntilFree()
28 | {
29 | synchronized(m_Lock)
30 | {
31 | while (m_LoadRunning)
32 | {
33 | try
34 | {
35 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - Running & about to try lock: " + this );
36 | m_Lock.wait();
37 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - Running & notified : " + this );
38 | }
39 | catch (InterruptedException e)
40 | {
41 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "ThreadDataLoad Wait - EXCEPTION CAUGHT.", e);
42 | }
43 | }
44 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - No longer running: " + this);
45 | }
46 | }
47 | // Handler to notify when load completes
48 | AutotuneCompleteHandler m_CompleteHandler;
49 |
50 | // Thread Handler for resynchronization
51 | public static abstract class AutotuneCompleteHandler
52 | {
53 | private Object m_Object;
54 | public AutotuneCompleteHandler(Object obj)
55 | {
56 | m_Object = obj;
57 | }
58 | public abstract void runAutotuneComplete(Object obj, String message);
59 | public abstract void exceptionRaised(String message);
60 |
61 | public Object getM_Object()
62 | {
63 | return m_Object;
64 | }
65 | }
66 |
67 | public ThreadAutotune(RemoteLinuxServer autoTuner)
68 | {
69 | m_LoadRunning = true; // Initialise the thread in running state
70 | m_AututuneThread = new Thread(this);
71 | m_Autotuner = autoTuner;
72 | m_CompleteHandler = null;
73 |
74 | // Thread synchronization
75 | m_Lock = new Object();
76 | }
77 |
78 | public void runThreadCommand(AutotuneCompleteHandler completeHandler)
79 | {
80 | m_CompleteHandler = completeHandler;
81 | m_AututuneThread.start();
82 | }
83 |
84 | public void run()
85 | {
86 | m_LoadRunning = true;
87 | synchronized(m_Lock)
88 | {
89 | // Launch the data load read method
90 | try
91 | {
92 | doAutotuneTask();
93 | }
94 |
95 | catch (Exception e)
96 | {
97 | m_CompleteHandler.exceptionRaised("Thread Exception: " + e.getLocalizedMessage());
98 | }
99 | finally
100 | {
101 | m_CompleteHandler.runAutotuneComplete(m_CompleteHandler.getM_Object(), "");
102 | }
103 | m_LoadRunning = false;
104 | m_Lock.notifyAll();
105 |
106 | // Kill the thread
107 | m_AututuneThread.interrupt();
108 | }
109 | }
110 |
111 | /**
112 | * @return the m_AututuneThread
113 | */
114 | public synchronized Thread getM_AututuneThread() {
115 | return m_AututuneThread;
116 | }
117 |
118 | /**
119 | * @param m_AututuneThread the m_AututuneThread to set
120 | */
121 | public synchronized void setM_AututuneThread(Thread m_AututuneThread) {
122 | this.m_AututuneThread = m_AututuneThread;
123 | }
124 |
125 | /**
126 | * @return the m_LoadRunning
127 | */
128 | public Boolean getM_LoadRunning() {
129 | return m_LoadRunning;
130 | }
131 |
132 | /**
133 | * @param m_LoadRunning the m_LoadRunning to set
134 | */
135 | public void setM_LoadRunning(Boolean m_LoadRunning) {
136 | this.m_LoadRunning = m_LoadRunning;
137 | }
138 |
139 | /**
140 | * @return the m_Autotuner
141 | */
142 | public synchronized RemoteLinuxServer getM_Autotuner() {
143 | return m_Autotuner;
144 | }
145 |
146 | /**
147 | * @param m_Autotuner the m_Autotuner to set
148 | */
149 | public synchronized void setM_Autotuner(RemoteLinuxServer m_Autotuner) {
150 | this.m_Autotuner = m_Autotuner;
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/main/java/analysis/AnalyzerTabs.java:
--------------------------------------------------------------------------------
1 | package analysis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.logging.Level;
5 | import java.util.logging.Logger;
6 |
7 | import control.MyLogger;
8 | import control.PrefsNightScoutLoader;
9 |
10 | public class AnalyzerTabs
11 | {
12 | // Implements the Singleton Design Pattern
13 | private static AnalyzerTabs m_Instance=null;
14 |
15 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
16 |
17 | public static AnalyzerTabs getInstance()
18 | {
19 | if (m_Instance == null)
20 | {
21 | m_Instance = new AnalyzerTabs();
22 | }
23 | return m_Instance;
24 | }
25 |
26 | class Tab
27 | {
28 | private String m_TabName;
29 | private boolean m_Enabled;
30 |
31 | Tab(String tabName, boolean enabled)
32 | {
33 | m_TabName = new String(tabName);
34 | m_Enabled = enabled;
35 | }
36 |
37 | /**
38 | * @return the m_TabName
39 | */
40 | public synchronized String getM_TabName() {
41 | return m_TabName;
42 | }
43 |
44 | /**
45 | * @param m_TabName the m_TabName to set
46 | */
47 | public synchronized void setM_TabName(String m_TabName) {
48 | this.m_TabName = m_TabName;
49 | }
50 |
51 | /**
52 | * @return the m_Enabled
53 | */
54 | public synchronized boolean isM_Enabled() {
55 | return m_Enabled;
56 | }
57 |
58 | /**
59 | * @param m_Enabled the m_Enabled to set
60 | */
61 | public synchronized void setM_Enabled(boolean m_Enabled) {
62 | this.m_Enabled = m_Enabled;
63 | }
64 | }
65 |
66 | private ArrayList m_ListOfTabs;
67 | private ArrayList m_MinimalListOfTabs;
68 |
69 |
70 | private AnalyzerTabs()
71 | {
72 | m_ListOfTabs = new ArrayList();
73 | m_MinimalListOfTabs = new ArrayList();
74 | }
75 |
76 | boolean isTabEnabled(String tabName)
77 | {
78 | boolean advancedSettings = PrefsNightScoutLoader.getInstance().isM_AdvancedSettings();
79 |
80 | // Only if advanced is true do we use the set values.
81 | // Else ignore and use the minimal list instead.
82 | ArrayList searchList = advancedSettings == true ? m_ListOfTabs : m_MinimalListOfTabs;
83 |
84 | boolean result = false;
85 | for (Tab t : searchList)
86 | {
87 | // if (t.getM_TabName().equals(tabName))
88 | if (tabName.equals(t.getM_TabName()))
89 | {
90 | result = t.isM_Enabled();
91 | break;
92 | }
93 | }
94 | return result;
95 | }
96 |
97 | public void setupListOfTabs()
98 | {
99 | int excelOutputLevel = PrefsNightScoutLoader.getInstance().getM_AnalyzerExcelOutputLevel();
100 | setupListOfTabs(this.m_ListOfTabs, excelOutputLevel);
101 | setupListOfTabs(this.m_MinimalListOfTabs, 0);
102 |
103 | m_Logger.log(Level.FINE, "Added full list");
104 | }
105 |
106 |
107 | private void setupListOfTabs(ArrayList searchList, int level)
108 | {
109 | searchList.clear();
110 |
111 | // level = 0 ==> Minimal
112 | // level = 1 ==> Moderate
113 | // level = 2 ==> Maximum
114 |
115 | if (level >= 0) searchList.add(new Tab("Guide to Tabs", true));
116 | if (level >= 0) searchList.add(new Tab("Autotune", true));
117 | if (level >= 0) searchList.add(new Tab("Recurring Trends", true));
118 | if (level == 2) searchList.add(new Tab("Trends", true));
119 | if (level >= 1) searchList.add(new Tab("Skipped Meal Trends", true));
120 | if (level >= 0) searchList.add(new Tab("CGM Summary", true));
121 | if (level >= 0) searchList.add(new Tab("CGM Heat Map", true));
122 | if (level >= 1) searchList.add(new Tab("BGs Outside Range", true));
123 | if (level >= 1) searchList.add(new Tab("Day Summaries", true));
124 | if (level == 2) searchList.add(new Tab("Single Results", true));
125 | if (level == 2) searchList.add(new Tab("Treatment Data Analyzed", true));
126 | if (level == 2) searchList.add(new Tab("In Range CGM Trend Result Entries", true));
127 | if (level == 2) searchList.add(new Tab("In Range CGM Entry Intervals", true));
128 | if (level == 2) searchList.add(new Tab("In Range CGM Results", true));
129 | if (level == 2) searchList.add(new Tab("Full History Trends", true));
130 | if (level >= 1) searchList.add(new Tab("Comparison to Full History", true));
131 | if (level >= 0) searchList.add(new Tab("Parameters", true));
132 | if (level >= 0) searchList.add(new Tab("Settings", true));
133 | if (level >= 0) searchList.add(new Tab("Trend Explanations", true));
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/FileChecker.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 |
3 | import loader.DataLoadCellNovo;
4 | import loader.DataLoadDiasend;
5 | import loader.DataLoadLibreView;
6 | import loader.DataLoadMedtronic;
7 | import loader.DataLoadOmniPod;
8 | import loader.DataLoadRocheCSV;
9 | import loader.DataLoadTandem;
10 |
11 | public class FileChecker
12 | {
13 |
14 | // Opens supplied file and checks validity against known types...
15 | public enum FileCheckType
16 | {
17 | INVALID,
18 |
19 | Medtronic,
20 | Diasend,
21 | LibreView,
22 | OmniPod,
23 | RocheSQLExtract,
24 | Tandem,
25 | CellNovo
26 | }
27 |
28 | public static String getFileTypeStr(FileCheckType fct)
29 | {
30 | String result = new String("");
31 |
32 | switch (fct)
33 | {
34 | case INVALID : result = "INVALID"; break;
35 | case Medtronic : result = "Medtronic"; break;
36 | case Diasend : result = "Diasend"; break;
37 | case LibreView : result = "LibreView"; break;
38 | case OmniPod : result = "OmniPod"; break;
39 | case RocheSQLExtract : result = "Roche SQL Extract"; break;
40 | case Tandem : result = "Tandem"; break;
41 | case CellNovo : result = "CellNovo"; break;
42 |
43 | default : result = "UNKNOWN"; break;
44 | }
45 |
46 | return result;
47 | }
48 |
49 | public static FileCheckType checkFile(String filename)
50 | {
51 | FileCheckType result = FileChecker.FileCheckType.INVALID;
52 |
53 | // Protect these checks by file name type
54 | if (filename.contains(".xls"))
55 | {
56 | if (isDiasend(filename))
57 | {
58 | result = FileChecker.FileCheckType.Diasend;
59 | }
60 | }
61 | else if (filename.contains(".csv"))
62 | {
63 | if (isLibreView(filename))
64 | {
65 | result = FileChecker.FileCheckType.LibreView;
66 | }
67 | else if (isMedtronic(filename))
68 | {
69 | result = FileChecker.FileCheckType.Medtronic;
70 | }
71 | else if (isRocheCSV(filename))
72 | {
73 | result = FileChecker.FileCheckType.RocheSQLExtract;
74 | }
75 | else if (isTandem(filename))
76 | {
77 | result = FileChecker.FileCheckType.Tandem;
78 | }
79 | else if (isCellNovo(filename))
80 | {
81 | result = FileChecker.FileCheckType.CellNovo;
82 | }
83 | }
84 | else if (filename.contains(".ibf") && isOmniPod(filename))
85 | {
86 | result = FileChecker.FileCheckType.OmniPod;
87 | }
88 |
89 | return result;
90 | }
91 |
92 | public static FileCheckType checkBinaryFile(String filename)
93 | {
94 | FileCheckType result = FileChecker.FileCheckType.INVALID;
95 |
96 | if (isLibreView(filename))
97 | {
98 | result = FileChecker.FileCheckType.LibreView;
99 | }
100 | else if (isMedtronic(filename))
101 | {
102 | result = FileChecker.FileCheckType.Medtronic;
103 | }
104 | else if (isDiasend(filename))
105 | {
106 | result = FileChecker.FileCheckType.Diasend;
107 | }
108 | else if (isRocheCSV(filename))
109 | {
110 | result = FileChecker.FileCheckType.RocheSQLExtract;
111 | }
112 | else if (isTandem(filename))
113 | {
114 | result = FileChecker.FileCheckType.Tandem;
115 | }
116 | else if (isCellNovo(filename))
117 | {
118 | result = FileChecker.FileCheckType.CellNovo;
119 | }
120 |
121 | return result;
122 | }
123 |
124 |
125 | private static boolean isLibreView(String fileName)
126 | {
127 | boolean result = DataLoadLibreView.isLibreView(fileName);
128 | return result;
129 | }
130 |
131 | private static boolean isMedtronic(String fileName)
132 | {
133 | boolean result = DataLoadMedtronic.isMedtronic(fileName);
134 | return result;
135 | }
136 |
137 | private static boolean isDiasend(String fileName)
138 | {
139 | boolean result = DataLoadDiasend.isDiasend(fileName);
140 | return result;
141 | }
142 | private static boolean isOmniPod(String fileName)
143 | {
144 | boolean result = DataLoadOmniPod.isOmniPod(fileName);
145 | return result;
146 | }
147 |
148 | private static boolean isRocheCSV(String fileName)
149 | {
150 | boolean result = DataLoadRocheCSV.isRoche(fileName);
151 | return result;
152 | }
153 |
154 | private static boolean isTandem(String fileName)
155 | {
156 | boolean result = DataLoadTandem.isTandem(fileName);
157 | return result;
158 | }
159 |
160 | private static boolean isCellNovo(String fileName)
161 | {
162 | boolean result = DataLoadCellNovo.isCellNovo(fileName);
163 | return result;
164 | }
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/bin/NightScoutLoader.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | REM ---------------------------------------------------------------------------
3 | REM
4 | REM Run script for launching the NightScoutLoader application
5 | REM
6 | REM 1 Checks that jar file is correctly installed in folder
7 | REM 2 Checks that the C:\Temp folder exists for log file
8 | REM 3 Ensures that correct parameters are passed to runtime JVM
9 | REM
10 | REM ---------------------------------------------------------------------------
11 | SETLOCAL enabledelayedexpansion
12 |
13 | REM
14 | REM Set some variables up
15 | REM
16 | SET jarfile=NightScoutLoader.jar
17 | SET tmpdir=C:\Temp
18 | SET msgdir=%temp%
19 |
20 | REM
21 | REM Ensure that the script runs from the same directory the script resides in
22 | REM The assumption is that both the BAT script and the JAR file are in the same
23 | REM directory.
24 | REM
25 | cd /D "%~dp0"
26 |
27 | REM ---------------------------------------------------------------------------
28 | REM
29 | REM Do some basic checks and alert if needed
30 | REM
31 | REM ---------------------------------------------------------------------------
32 |
33 | REM
34 | REM Java file needs to be present
35 | REM
36 | if NOT EXIST %jarfile% (
37 | CALL :displayMessage CRITICAL "NightScoutLoader Jar file needs to be present as '%jarfile%'" "" "Did the download append '(1)' to the filename perhaps?" "" "If so, please rename the Jar file to '%jarfile%' in directory %~dp0"
38 | SET ERRORLEVEL=1
39 | EXIT /B %ERRORLEVEL%
40 | )
41 |
42 | REM
43 | REM NightScoutLoader logs to %tmpdir% so ensure it exists too
44 | REM
45 | if NOT EXIST %tmpdir% (
46 | md %tmpdir%
47 | if NOT EXIST %tmpdir% (
48 | CALL :displayMessage EXCLAMATION "NightScoutLoader relies on %tmpdir% by default for its log file" "" "However, you don't have permission to create this folder" "" "Use elevated permissions to create manually"
49 | SET ERRORLEVEL=1
50 | EXIT /B %ERRORLEVEL%
51 | )
52 | CALL :displayMessage INFORMATION "Successfully created %tmpdir% for NightScoutLoader log file" "" "Select OK to continue"
53 | )
54 |
55 | REM
56 | REM Invoke NightScoutLoader with options to increase memory and also with the TLS option set
57 | REM TLS is needed to successfully connect to Mongo Atlas on Windows
58 | REM
59 | java -Xmx1024m -Xms128m -Djdk.tls.client.protocols=TLSv1.2 -jar %jarfile%
60 | EXIT /B %ERRORLEVEL%
61 |
62 | REM ---------------------------------------------------------------------------
63 | REM
64 | REM Display Message function for notifications
65 | REM
66 | REM %~1 CRITICAL, QUESTION, EXCLAMATION or INFORMATION - sets msgbox symbol
67 | REM %~2 First line message
68 | REM %~2 Second line message
69 | REM ...
70 | REM %~2 Fifth line message
71 | REM ---------------------------------------------------------------------------
72 | :displayMessage
73 | SET symbol=""
74 | SET header=""
75 |
76 | if "%~1"=="CRITICAL" (
77 | SET symbol=, vbCritical + vbOKOnly
78 | SET header="SETUP ERROR:"
79 | )
80 | if "%~1"=="QUESTION" (
81 | SET symbol=, vbQuestion + vbOKOnly
82 | SET header=""
83 | )
84 | if "%~1"=="EXCLAMATION" (
85 | SET symbol=, vbExclamation + vbOKOnly
86 | SET header="SETUP ERROR:"
87 | )
88 | if "%~1"=="INFORMATION" (
89 | SET symbol=, vbInformation + vbOKOnly
90 | SET header="Please Note:"
91 | )
92 | shift
93 |
94 | IF NOT "%~5"=="" goto fiveLines
95 | IF NOT "%~4"=="" goto fourLines
96 | IF NOT "%~3"=="" goto threeLines
97 | IF NOT "%~2"=="" goto twoLines
98 | IF NOT "%~1"=="" goto oneLine
99 |
100 | :oneLine
101 | echo MSGBOX %header% ^& vbCrLf ^& vbCrLf ^& "%~1" %symbol% > %msgdir%\TEMPmessage.vbs
102 | goto runVB
103 | :twoLines
104 | echo MSGBOX %header% ^& vbCrLf ^& vbCrLf ^& "%~1" ^& vbCrLf ^& "%~2" %symbol% > %msgdir%\TEMPmessage.vbs
105 | goto runVB
106 | :threeLines
107 | echo MSGBOX %header% ^& vbCrLf ^& vbCrLf ^& "%~1" ^& vbCrLf ^& "%~2" ^& vbCrLf ^& "%~3" %symbol% > %msgdir%\TEMPmessage.vbs
108 | goto runVB
109 | :fourLines
110 | echo MSGBOX %header% ^& vbCrLf ^& vbCrLf ^& "%~1" ^& vbCrLf ^& "%~2" ^& vbCrLf ^& "%~3" ^& vbCrLf ^& "%~4" %symbol% > %msgdir%\TEMPmessage.vbs
111 | goto runVB
112 | :fiveLines
113 | echo MSGBOX %header% ^& vbCrLf ^& vbCrLf ^& "%~1" ^& vbCrLf ^& "%~2" ^& vbCrLf ^& "%~3" ^& vbCrLf ^& "%~4" ^& vbCrLf ^& "%~5" %symbol% > %msgdir%\TEMPmessage.vbs
114 | goto runVB
115 |
116 | :runVB
117 | call %msgdir%\TEMPmessage.vbs
118 | del %msgdir%\TEMPmessage.vbs /f /q
119 | EXIT /B 0
--------------------------------------------------------------------------------
/src/main/java/miscellaneous/BinaryStruct.java:
--------------------------------------------------------------------------------
1 | package miscellaneous;
2 | //package org.DavidRichardson.NightscoutLoaderMaven;
3 | //
4 | //import java.util.ArrayList;
5 | //import java.util.regex.Matcher;
6 | //import java.util.regex.Pattern;
7 | //
8 | //public class BinaryStruct
9 | //{
10 | //
11 | // enum VarType
12 | // {
13 | // vt_Unknown,
14 | //
15 | // vt_short,
16 | // vt_signed_short,
17 | // vt_int,
18 | // vt_signed_int,
19 | // vt_byte,
20 | // vt_signed_byte,
21 | // vt_float,
22 | // vt_BE_short,
23 | // vt_BE_signed_short,
24 | // vt_BE_float,
25 | // vt_BE_int,
26 | // vt_BE_signed_int,
27 | // vt_ZString,
28 | // vt_String,
29 | // };
30 | //
31 | // private static FieldType[] m_FieldType = new FieldType[15];
32 | // private static boolean m_Initialized = false;
33 | //
34 | // private int m_Count = 0;
35 | // private String m_Expression = "";
36 | //
37 | // private class FieldType
38 | // {
39 | // private char m_fieldType;
40 | // private int m_length;
41 | // private VarType m_VarType;
42 | //
43 | // FieldType(char f, int l, VarType v)
44 | // {
45 | // m_fieldType = f;
46 | // m_length = l;
47 | // m_VarType = v;
48 | // }
49 | //
50 | // /**
51 | // * @return the m_fieldType
52 | // */
53 | // public synchronized char getM_fieldType() {
54 | // return m_fieldType;
55 | // }
56 | //
57 | // /**
58 | // * @param m_fieldType the m_fieldType to set
59 | // */
60 | // public synchronized void setM_fieldType(char m_fieldType) {
61 | // this.m_fieldType = m_fieldType;
62 | // }
63 | //
64 | // /**
65 | // * @return the m_length
66 | // */
67 | // public synchronized int getM_length() {
68 | // return m_length;
69 | // }
70 | //
71 | // /**
72 | // * @param m_length the m_length to set
73 | // */
74 | // public synchronized void setM_length(int m_length) {
75 | // this.m_length = m_length;
76 | // }
77 | //
78 | // /**
79 | // * @return the m_VarType
80 | // */
81 | // public synchronized VarType getM_VarType() {
82 | // return m_VarType;
83 | // }
84 | //
85 | // /**
86 | // * @param m_VarType the m_VarType to set
87 | // */
88 | // public synchronized void setM_VarType(VarType m_VarType) {
89 | // this.m_VarType = m_VarType;
90 | // }
91 | // }
92 | //
93 | // // See parseformat in struct.js from tidepool on which this is modeled
94 | // public static ArrayList parseFormat(String format)
95 | // {
96 | // ArrayList result = new ArrayList();
97 | //
98 | // int count = 0;
99 | // String exp = new String("");
100 | //
101 | // Pattern formatPattern = Pattern.compile("(([0-9]*)([a-zA-Z.]))+");
102 | // Matcher formatMatcher = formatPattern.matcher(format);
103 | //
104 | // while (formatMatcher.find())
105 | // {
106 | // count = Integer.parseInt(formatMatcher.group(1));
107 | // exp = formatMatcher.group(2);
108 | // BinaryStruct entry = new BinaryStruct(count, exp);
109 | // result.add(entry);
110 | // }
111 | //
112 | // return result;
113 | // }
114 | //
115 | // public BinaryStruct(int count, String exp)
116 | // {
117 | // initialize();
118 | // m_Count = count;
119 | // m_Expression = new String(exp);
120 | // }
121 | //
122 | // public BinaryStruct()
123 | // {
124 | // initialize();
125 | // }
126 | //
127 | // private void initialize()
128 | // {
129 | // if (m_Initialized == false)
130 | // {
131 | // m_Initialized = true;
132 | //
133 | // int i = 0;
134 | //
135 | // m_FieldType[i++] = new FieldType('i', 4, VarType.vt_int);
136 | // m_FieldType[i++] = new FieldType('n', 4, VarType.vt_signed_int);
137 | // m_FieldType[i++] = new FieldType('s', 2, VarType.vt_short);
138 | // m_FieldType[i++] = new FieldType('h', 2, VarType.vt_signed_short);
139 | // m_FieldType[i++] = new FieldType('b', 1, VarType.vt_byte);
140 | // m_FieldType[i++] = new FieldType('y', 1, VarType.vt_signed_byte);
141 | // m_FieldType[i++] = new FieldType('B', 0, VarType.vt_String); // was bytes ...
142 | // m_FieldType[i++] = new FieldType('f', 4, VarType.vt_float);
143 | // m_FieldType[i++] = new FieldType('F', 4, VarType.vt_BE_float);
144 | // m_FieldType[i++] = new FieldType('I', 4, VarType.vt_BE_int);
145 | // m_FieldType[i++] = new FieldType('N', 4, VarType.vt_BE_signed_int);
146 | // m_FieldType[i++] = new FieldType('S', 2, VarType.vt_BE_short);
147 | // m_FieldType[i++] = new FieldType('H', 2, VarType.vt_BE_signed_short);
148 | // m_FieldType[i++] = new FieldType('z', 0, VarType.vt_ZString);
149 | // m_FieldType[i++] = new FieldType('Z', 0, VarType.vt_String);
150 | //
151 | // }
152 | // }
153 | //}
154 | //
155 | //
156 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultPumpSettingBasal.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import org.apache.poi.hssf.usermodel.HSSFRow;
4 |
5 | public class DBResultPumpSettingBasal extends DBResultPumpSetting
6 | {
7 | private String m_BasalProfileName;
8 |
9 | public DBResultPumpSettingBasal(String basalProfileName, HSSFRow row)
10 | {
11 | super(row);
12 | m_BasalProfileName = new String(basalProfileName);
13 | }
14 |
15 | public String toString()
16 | {
17 | return String.format("Profile Name: %s, Index: %d, Time: %s, Value: %g",
18 | m_BasalProfileName, getM_Index(), getM_Time(), getM_BasalValue());
19 | }
20 |
21 |
22 | /**
23 | * @return the m_BasalProfileName
24 | */
25 | public synchronized String getM_BasalProfileName() {
26 | return m_BasalProfileName;
27 | }
28 |
29 | /**
30 | * @param m_BasalProfileName the m_BasalProfileName to set
31 | */
32 | public synchronized void setM_BasalProfileName(String m_BasalProfileName) {
33 | this.m_BasalProfileName = m_BasalProfileName;
34 | }
35 |
36 | /**
37 | * @return the m_BasalValue
38 | */
39 | public synchronized Double getM_BasalValue() {
40 | return getM_TimeBoundValue();
41 | }
42 |
43 | /**
44 | * @param m_BasalValue the m_BasalValue to set
45 | */
46 | public synchronized void setM_BasalValue(Double m_BasalValue) {
47 | setM_TimeBoundValue(m_BasalValue);
48 | }
49 | }
50 |
51 |
52 | //Original class definition
53 | //
54 | //package davidRichardson;
55 | //
56 | //import org.apache.poi.hssf.usermodel.HSSFCell;
57 | //import org.apache.poi.hssf.usermodel.HSSFRow;
58 | //
59 | //public class DBResultDiasendBasalSetting
60 | //{
61 | // private String m_BasalProfileName;
62 | // private int m_Index;
63 | // private String m_Time;
64 | // private Double m_BasalValue;
65 | //
66 | // private final int m_SettingsFields = 3;
67 | //
68 | // // Utility Function for getting a cell from row as string even if numeric
69 | // static String getCellAsString(HSSFRow row, int index)
70 | // {
71 | // String result;
72 | // // Check type of this cell first
73 | // if (row.getCell(index).getCellType() == HSSFCell.CELL_TYPE_STRING)
74 | // {
75 | // result = row.getCell(index).getStringCellValue();
76 | // }
77 | // else
78 | // {
79 | // Double result_num = row.getCell(index).getNumericCellValue();
80 | // result = result_num.toString();
81 | // }
82 | // return result;
83 | // }
84 | //
85 | // DBResultDiasendBasalSetting(String basalProfileName, HSSFRow row)
86 | // {
87 | // m_BasalProfileName = new String(basalProfileName);
88 | //
89 | // int maxColumns = row.getPhysicalNumberOfCells();
90 | // if (maxColumns == m_SettingsFields)
91 | // {
92 | // Double cell1 = row.getCell(0).getNumericCellValue();
93 | // String cell2 = row.getCell(1).getStringCellValue();
94 | // Double cell3 = row.getCell(2).getNumericCellValue();
95 | //
96 | // m_Index = cell1.intValue();
97 | // m_Time = cell2;
98 | // m_BasalValue = cell3;
99 | // }
100 | // }
101 | //
102 | // public String toString()
103 | // {
104 | // return String.format("Profile Name: %s, Index: %d, Time: %s, Value: %g",
105 | // m_BasalProfileName, m_Index, m_Time, m_BasalValue);
106 | // }
107 | //
108 | //
109 | // /**
110 | // * @return the m_BasalProfileName
111 | // */
112 | // public synchronized String getM_BasalProfileName() {
113 | // return m_BasalProfileName;
114 | // }
115 | //
116 | // /**
117 | // * @param m_BasalProfileName the m_BasalProfileName to set
118 | // */
119 | // public synchronized void setM_BasalProfileName(String m_BasalProfileName) {
120 | // this.m_BasalProfileName = m_BasalProfileName;
121 | // }
122 | //
123 | // /**
124 | // * @return the m_Index
125 | // */
126 | // public synchronized int getM_Index() {
127 | // return m_Index;
128 | // }
129 | //
130 | // /**
131 | // * @param m_Index the m_Index to set
132 | // */
133 | // public synchronized void setM_Index(int m_Index) {
134 | // this.m_Index = m_Index;
135 | // }
136 | //
137 | // /**
138 | // * @return the m_Time
139 | // */
140 | // public synchronized String getM_Time() {
141 | // return m_Time;
142 | // }
143 | //
144 | // /**
145 | // * @param m_Time the m_Time to set
146 | // */
147 | // public synchronized void setM_Time(String m_Time) {
148 | // this.m_Time = m_Time;
149 | // }
150 | //
151 | // /**
152 | // * @return the m_BasalValue
153 | // */
154 | // public synchronized Double getM_BasalValue() {
155 | // return m_BasalValue;
156 | // }
157 | //
158 | // /**
159 | // * @param m_BasalValue the m_BasalValue to set
160 | // */
161 | // public synchronized void setM_BasalValue(Double m_BasalValue) {
162 | // this.m_BasalValue = m_BasalValue;
163 | // }
164 | //
165 | //
166 | //}
--------------------------------------------------------------------------------
/src/main/java/control/ThreadDataLoad.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 | import java.sql.SQLException;
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 |
8 | import loader.DataLoadBase;
9 |
10 |
11 | public class ThreadDataLoad implements Runnable
12 | {
13 | private static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
14 |
15 | // Separate thread for data loads
16 | private Thread m_LoadThread;
17 |
18 | private String m_ThreadNameString;
19 |
20 | /**
21 | * @return the m_LoadThread
22 | */
23 | public synchronized Thread getM_LoadThread() {
24 | return m_LoadThread;
25 | }
26 |
27 | /**
28 | * @param m_LoadThread the m_LoadThread to set
29 | */
30 | public synchronized void setM_LoadThread(Thread m_LoadThread) {
31 | this.m_LoadThread = m_LoadThread;
32 | }
33 |
34 | // Data Loader used by thread
35 | private DataLoadBase m_DataLoader;
36 |
37 | private Boolean m_LoadRunning;
38 | // static Object m_Lock = new Object();
39 | private Object m_Lock;
40 |
41 | // Thread Synchronization
42 | public void waitUntilFree()
43 | {
44 | synchronized(m_Lock)
45 | {
46 | while (m_LoadRunning)
47 | {
48 | try
49 | {
50 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - Running & about to try lock: " + this );
51 | m_Lock.wait();
52 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - Running & notified : " + this );
53 | }
54 | catch (InterruptedException e)
55 | {
56 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "ThreadDataLoad Wait - EXCEPTION CAUGHT.", e);
57 | }
58 | }
59 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - No longer running: " + this);
60 | }
61 | }
62 | // Handler to notify when load completes
63 | DataLoadCompleteHandler m_CompleteHandler;
64 |
65 | // Thread Handler for resynchronization
66 | public static abstract class DataLoadCompleteHandler
67 | {
68 | private Object m_Object;
69 | public DataLoadCompleteHandler(Object obj)
70 | {
71 | m_Object = obj;
72 | }
73 | public abstract void dataLoadComplete(Object obj, String message);
74 | public abstract void exceptionRaised(String message);
75 |
76 | public Object getM_Object()
77 | {
78 | return m_Object;
79 | }
80 | }
81 |
82 | public ThreadDataLoad(DataLoadBase dataLoader, String threadName)
83 | {
84 | m_LoadRunning = true; // Initialise the thread in running state
85 | m_LoadThread = new Thread(this);
86 | m_DataLoader = dataLoader;
87 | m_CompleteHandler = null;
88 | m_ThreadNameString = threadName;
89 |
90 | // Thread synchronization
91 | m_Lock = new Object();
92 | }
93 |
94 | public void loadDBResults(DataLoadCompleteHandler completeHandler)
95 | {
96 | m_CompleteHandler = completeHandler;
97 | m_LoadThread.start();
98 | }
99 |
100 | public void run()
101 | {
102 | m_LoadRunning = true;
103 | synchronized(m_Lock)
104 | {
105 | // Launch the data load read method
106 | try
107 | {
108 | m_DataLoader.loadDBResults();
109 | m_Logger.log(Level.INFO, "Thread Name '" + m_ThreadNameString + "' has loaded : " +
110 | m_DataLoader.getRawEntryResultsFromDB().size() + " rows");
111 | }
112 |
113 | catch (ClassNotFoundException | SQLException | IOException e)
114 | {
115 | m_CompleteHandler.exceptionRaised("Thread Exception: " + e.getLocalizedMessage());
116 | }
117 | finally
118 | {
119 | m_CompleteHandler.dataLoadComplete(m_CompleteHandler.getM_Object(), "");
120 | }
121 | m_LoadRunning = false;
122 | m_Lock.notifyAll();
123 |
124 | // Kill the thread
125 | // m_LoadThread.interrupt();
126 | }
127 | }
128 |
129 | /**
130 | * @return the m_LoadRunning
131 | */
132 | public Boolean getM_LoadRunning() {
133 | return m_LoadRunning;
134 | }
135 |
136 | /**
137 | * @param m_LoadRunning the m_LoadRunning to set
138 | */
139 | public void setM_LoadRunning(Boolean m_LoadRunning) {
140 | this.m_LoadRunning = m_LoadRunning;
141 | }
142 |
143 | /**
144 | * @return the m_DataLoader
145 | */
146 | public synchronized DataLoadBase getM_DataLoader() {
147 | return m_DataLoader;
148 | }
149 |
150 | /**
151 | * @param m_DataLoader the m_DataLoader to set
152 | */
153 | public synchronized void setM_DataLoader(DataLoadBase m_DataLoader) {
154 | this.m_DataLoader = m_DataLoader;
155 | }
156 |
157 | /**
158 | * @return the m_ThreadNameString
159 | */
160 | public synchronized String getM_ThreadNameString() {
161 | return m_ThreadNameString;
162 | }
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/src/test/java/loader/BaseTestEntry.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.net.URISyntaxException;
6 | import java.net.URL;
7 | import java.net.UnknownHostException;
8 | import java.sql.SQLException;
9 | import java.text.ParseException;
10 | import java.text.SimpleDateFormat;
11 | import java.time.LocalDateTime;
12 | import java.time.ZoneOffset;
13 | import java.time.format.DateTimeFormatter;
14 | import java.util.ArrayList;
15 | import org.junit.jupiter.api.Assertions;
16 | import org.junit.runner.RunWith;
17 | import org.mockito.junit.MockitoJUnitRunner;
18 | import control.MyLogger;
19 | import control.PrefsNightScoutLoader;
20 | import entity.DBResult;
21 | import entity.DBResultEntry;
22 |
23 | @RunWith(MockitoJUnitRunner.class)
24 | public abstract class BaseTestEntry {
25 |
26 | protected static Double DOUBLE_THRESHOLD = 0.001;
27 |
28 | public BaseTestEntry() {
29 | try {
30 | MyLogger.setup(true);
31 | } catch (IOException e) {
32 | // TODO Auto-generated catch block
33 | e.printStackTrace();
34 | }
35 | }
36 |
37 | protected abstract Object[][] getExpectedTestResults();
38 | protected abstract String getResourceFileName();
39 | protected abstract DataLoadFile getDataLoadFile();
40 | protected abstract SimpleDateFormat getSimpleDateFormat();
41 | protected abstract String getDateFormat();
42 |
43 | public ArrayList getDBResultArrayList()
44 | {
45 | return getDataLoadFile().getResultTreatments();
46 | }
47 |
48 | public ArrayList getDBResultEntryArrayList()
49 | {
50 | return getDataLoadFile().getRawEntryResultsFromDB();
51 | }
52 |
53 | public void performTestLoad()
54 | {
55 | doDataLoad();
56 | DataLoadFile dataLoadDiasend = getDataLoadFile();
57 | Assertions.assertTrue(dataLoadDiasend != null);
58 | try {
59 | assertionTests(dataLoadDiasend);
60 | } catch (ParseException e) {
61 | // TODO Auto-generated catch block
62 | e.printStackTrace();
63 | }
64 | }
65 |
66 |
67 | public void doDataLoad()
68 | {
69 | // This disables any MongoDB connection attempts
70 | PrefsNightScoutLoader.getInstance().setM_NightscoutMongoServer("");
71 |
72 | // Disable inferring any temp basals
73 | PrefsNightScoutLoader.getInstance().setM_InferTempBasals(false);
74 |
75 | URL url = this.getClass().getClassLoader().getResource(getResourceFileName());
76 | Assertions.assertTrue(url != null);
77 |
78 | DataLoadFile dataLoadDiasend = getDataLoadFile();
79 | try {
80 | dataLoadDiasend.initialize(new File(url.toURI()).getAbsolutePath());
81 | dataLoadDiasend.loadDBResults();
82 | } catch (URISyntaxException e) {
83 | Assertions.assertTrue(false, e.toString());
84 | } catch (UnknownHostException e) {
85 | Assertions.assertTrue(false, e.toString());
86 | } catch (ClassNotFoundException e) {
87 | Assertions.assertTrue(false, e.toString());
88 | } catch (SQLException e) {
89 | Assertions.assertTrue(false, e.toString());
90 | } catch (IOException e) {
91 | Assertions.assertTrue(false, e.toString());
92 | }
93 |
94 | }
95 |
96 |
97 | private void assertionTests(DataLoadFile dataLoadDiasend) throws ParseException
98 | {
99 | Assertions.assertTrue(dataLoadDiasend != null);
100 |
101 | for (int c = 0; c < getExpectedTestResults().length; c++)
102 | {
103 | Object[] treatmentObject = getExpectedTestResults()[c];
104 | int i = 0;
105 |
106 | // Integer indexInteger = (Integer) treatmentObject[i++];
107 | String dateString = (String) treatmentObject[i++];
108 |
109 | // Better way of date parsing Java 8
110 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(getDateFormat());
111 | LocalDateTime parseDate = LocalDateTime.parse(dateString, formatter);
112 | long ldtEpoch = parseDate.toEpochSecond(ZoneOffset.UTC);
113 |
114 |
115 | Double bgDouble = (Double)treatmentObject[i++];
116 | String dupeString = (String)treatmentObject[i++];
117 |
118 |
119 | DBResultEntry result = dataLoadDiasend.getRawEntryResultHashMap().get(ldtEpoch * 1000);
120 | if (result != null)
121 | {
122 | String messgString = " for Entry " + c + " Date " + dateString + " Treatment Id: " + result.getIdentity();
123 | Assertions.assertTrue(result != null);
124 |
125 | if (dupeString.equals("NO"))
126 | assertEquals(result.getM_BG(), bgDouble,
127 | "BG Differs" + messgString
128 | + " Result BG: " + result.getM_BG()
129 | + " Treatment BG: " + bgDouble);
130 | }
131 |
132 | }
133 |
134 | }
135 |
136 | protected void assertEquals(Double dbl1, Double dbl2, String messageString)
137 | {
138 | Assertions.assertTrue(Math.abs(dbl1 - dbl2) < DOUBLE_THRESHOLD, messageString);
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultRoche.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.sql.ResultSet;
4 | import java.sql.SQLException;
5 | import java.text.ParseException;
6 | //import java.util.logging.Logger;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | import control.MyLogger;
11 | import utils.CommonUtils;
12 |
13 | public class DBResultRoche extends DBResult
14 | {
15 | // private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
16 | protected static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
17 |
18 | private boolean m_Valid = true;
19 |
20 | static private String[] m_FieldNames =
21 | {
22 | "Year",
23 | "Month",
24 | "Day",
25 | "DayName",
26 | "Time",
27 | "TimeSlot",
28 | "Result",
29 | "ResultType",
30 | "MealType",
31 | "Duration",
32 | };
33 |
34 | static private boolean m_indexesInitialized = false;
35 | static private int m_YearIndex = 0;
36 | static private int m_MonthIndex = 0;
37 | static private int m_DayIndex = 0;
38 | static private int m_DayNameIndex = 0;
39 | static private int m_TimeIndex = 0;
40 | static private int m_TimeSlotIndex = 0;
41 | static private int m_ResultIndex = 0;
42 | static private int m_ResultTypeIndex = 0;
43 | static private int m_MealTypeIndex = 0;
44 | static private int m_DurationIndex = 0;
45 |
46 |
47 |
48 |
49 | public DBResultRoche(ResultSet rs) throws SQLException
50 | {
51 | super();
52 |
53 | // Get this error if try to check resultset:
54 | // We just caught an error: The requested operation is not supported on forward only result sets. - The requested operation is not supported on forward only result sets.
55 |
56 | m_Year = rs.getInt("Year");
57 | m_Month = rs.getInt("Month");
58 | m_Day = rs.getInt("Day");
59 | m_DayName = rs.getString("DayName");
60 | m_Time = rs.getTimestamp("Time");
61 | m_TimeSlot = rs.getString("TimeSlot");
62 | m_Result = rs.getString("Result");
63 | m_ResultType = rs.getString("ResultType");
64 | m_MealType = rs.getString("MealType");
65 | m_Duration = rs.getString("Duration");
66 | }
67 |
68 | public DBResultRoche(String[] recordSet)
69 | {
70 | super();
71 |
72 | if (m_indexesInitialized == false)
73 | {
74 | m_Valid = false;
75 | }
76 |
77 | initialize();
78 |
79 | // Check for a repeat load and seeing the header line again.
80 | if (recordSet[m_YearIndex].equals("Year"))
81 |
82 | {
83 | m_Valid = false;
84 | }
85 |
86 | try
87 | {
88 | if (m_Valid == true)
89 | {
90 | m_Year = Integer.parseInt(recordSet[m_YearIndex]);
91 | m_Month = Integer.parseInt(recordSet[m_MonthIndex]);
92 | m_Day = Integer.parseInt(recordSet[m_DayIndex]);
93 | m_DayName = recordSet[m_DayNameIndex];
94 | //m_Time = parseFileDate(recordSet[m_TimeIndex]);
95 | m_Time = CommonUtils.convertDateString(recordSet[m_TimeIndex]);
96 | m_TimeSlot = recordSet[m_TimeSlotIndex];
97 | m_Result = recordSet[m_ResultIndex];
98 | m_ResultType = recordSet[m_ResultTypeIndex];
99 | m_MealType = recordSet[m_MealTypeIndex];
100 | m_Duration = recordSet[m_DurationIndex];
101 |
102 | // If meal type or duration == "null" then reset strings to empty
103 | if (m_MealType.equals("(null)"))
104 | {
105 | m_MealType = "";
106 | }
107 | if (m_Duration.equals("(null)"))
108 | {
109 | m_Duration = "";
110 | }
111 |
112 | String rawString = rawToString();
113 | m_Logger.log(Level.FINE, "Just processed: " + rawString);
114 |
115 | }
116 | }
117 | catch (ParseException e)
118 | {
119 | m_Valid = false;
120 | }
121 | }
122 |
123 | public DBResultRoche()
124 | {
125 | super();
126 | }
127 |
128 | private void initialize()
129 | {
130 | // Set values in underdlying ResultFromDB from record set
131 | if (m_indexesInitialized == false)
132 | {
133 | m_YearIndex = fieldLocation("Year");
134 | m_MonthIndex = fieldLocation("Month");
135 | m_DayIndex = fieldLocation("Day");
136 | m_DayNameIndex = fieldLocation("DayName");
137 | m_TimeIndex = fieldLocation("Time");
138 | m_TimeSlotIndex = fieldLocation("TimeSlot");
139 | m_ResultIndex = fieldLocation("Result");
140 | m_ResultTypeIndex = fieldLocation("ResultType");
141 | m_MealTypeIndex = fieldLocation("MealType");
142 | m_DurationIndex = fieldLocation("Duration");
143 |
144 | m_indexesInitialized = true;
145 | }
146 | }
147 |
148 | private int fieldLocation(String f)
149 | {
150 | int result=-1;
151 | for (int i=0; result < 0 && i < m_FieldNames.length; i++)
152 | {
153 | if (m_FieldNames[i] == f)
154 | {
155 | result=i;
156 | }
157 | }
158 | return result;
159 | }
160 |
161 | @Override
162 | public boolean isValid()
163 | {
164 | return m_Valid;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultEntryLibreView.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.text.ParseException;
4 | import java.util.Date;
5 | import java.util.HashMap;
6 | import com.mongodb.DBObject;
7 | import loader.AuditHistory;
8 | import utils.CommonUtils;
9 | import loader.DataLoadLibreView;
10 |
11 | public class DBResultEntryLibreView extends DBResultEntry
12 | {
13 |
14 | // Collection of items to handle the CGM tab
15 | static private boolean m_CGMIndexesInitialized = false;
16 | static private String[] m_CGMFieldNames =
17 | {
18 | // These field names are stripped of space
19 | "Device Timestamp",
20 | "Historic Glucose mmol/L",
21 | "Scan Glucose mmol/L"
22 | };
23 | static private int m_CGMTimeIndex = 0;
24 | static private int m_HistoricCGMBGIndex = 0;
25 | static private int m_ScanCGMBGIndex = 0;
26 |
27 | protected boolean m_Valid = false;
28 |
29 |
30 | public DBResultEntryLibreView(DBObject rs) {
31 | super(rs);
32 | // TODO Auto-generated constructor stub
33 | }
34 |
35 | public DBResultEntryLibreView(String m_ID, Double m_Unfiltered, Double m_Filtered, String m_Direction, String m_Device,
36 | Double m_RSSI, Double m_SGV, String m_DateString, String m_Type, Double m_Date, Integer m_Noise) throws ParseException
37 | {
38 | super(m_ID, m_Unfiltered, m_Filtered, m_Direction, m_Device,
39 | m_RSSI, m_SGV, m_DateString, m_Type, m_Date, m_Noise);
40 | }
41 |
42 | public DBResultEntryLibreView(String[] row)
43 | {
44 | // Handle aa CGM record
45 | loadRawCGM(row);
46 | }
47 |
48 | public static void resetCGMHeaders()
49 | {
50 | m_CGMIndexesInitialized = false;
51 | }
52 |
53 | public static Boolean initializeCGMHeaders(String[] row)
54 | {
55 | Boolean result = false;
56 |
57 | if (m_CGMIndexesInitialized == false)
58 | {
59 | m_CGMTimeIndex = -1;
60 | m_HistoricCGMBGIndex = -1;
61 | m_ScanCGMBGIndex = -1;
62 |
63 | if (row.length >= m_CGMFieldNames.length)
64 | {
65 | HashMap fieldPosHashMap = new HashMap();
66 |
67 | for (int i = 0; i < row.length; i++)
68 | {
69 | fieldPosHashMap.put(row[i], Integer.valueOf(i));
70 | }
71 |
72 | for (int i = 0; i < m_CGMFieldNames.length; i++)
73 | {
74 | Integer posInteger = fieldPosHashMap.get(m_CGMFieldNames[i]);
75 | if (posInteger != null)
76 | {
77 | switch (i)
78 | {
79 | case 0 : m_CGMTimeIndex = posInteger.intValue(); break;
80 | case 1 : m_HistoricCGMBGIndex = posInteger.intValue(); break;
81 | case 2 : m_ScanCGMBGIndex = posInteger.intValue(); break;
82 | default : break;
83 | }
84 | }
85 | }
86 |
87 | m_CGMIndexesInitialized = true;
88 | }
89 | }
90 | result = (m_CGMTimeIndex != -1) && (m_HistoricCGMBGIndex != -1) && (m_ScanCGMBGIndex != -1) ? true : false;
91 |
92 | return result;
93 | }
94 |
95 | private void loadRawCGM(String[] row)
96 | {
97 | String timeStr = row[m_CGMTimeIndex];
98 | Double historicBGDouble = getBGValue(m_HistoricCGMBGIndex, row);
99 | Double scanBGDouble = getBGValue(m_ScanCGMBGIndex, row);
100 | Double bgValueDouble = historicBGDouble == null ? scanBGDouble : historicBGDouble;
101 |
102 | m_Device = AuditHistory.getInstance().getM_NextUploadID();
103 | // Boolean scannedValBoolean = scanBGDouble == null ? false : true; // Would like to mark this as a scan but have nowhere to put it
104 |
105 | m_Type = "sgv";
106 | if (bgValueDouble != null)
107 | {
108 | m_SGV = bgValueDouble * 18; // Values held in mgDl
109 | m_BG = bgValueDouble;
110 | }
111 |
112 | if (timeStr != null)
113 | {
114 | setM_UTCDateTime(DataLoadLibreView.parseFileLocalDateTime(timeStr));
115 |
116 | Date d = new Date(0);
117 | // d = parseFileDate(timeStr);
118 | d = DataLoadLibreView.parseFileDateTime(timeStr);
119 | if (d.getTime() != 0)
120 | {
121 | //This isn't working, it's applying the offset twice, I suspect something to
122 | //do with Date.getTime() always returning results for display in local TZ
123 | //Date utcD = new Date(CommonUtils.toUTC(d.getTime()));
124 | Date utcD = new Date(d.getTime());
125 | this.setM_UTCDate(utcD);
126 |
127 | try {
128 | this.setM_DateString(CommonUtils.convertDateString(d, "dd/MM/yyyy HH:mm:ss"));
129 | } catch (ParseException e) {
130 | m_Logger.severe("Error converting Date to NSZDateString : " + timeStr);
131 |
132 | // TODO Auto-generated catch block
133 | e.printStackTrace();
134 | }
135 |
136 |
137 | // Essential for use in comparator
138 | setEpochMilliesFromUTC();
139 | }
140 | }
141 |
142 | m_Valid = (getM_BG() == null || getM_SGV() == null || getM_UTCDate() == null) ? false : true;
143 | }
144 |
145 | private Double getBGValue(int index, String[] rowStrings)
146 | {
147 | Double resultDouble = null;
148 | if (rowStrings.length >= index)
149 | {
150 | if (rowStrings[index] != null && rowStrings[index].length() > 0)
151 | {
152 | resultDouble = Double.parseDouble(rowStrings[index]);
153 | }
154 | }
155 | return resultDouble;
156 | }
157 |
158 | public boolean isValid()
159 | {
160 | return m_Valid;
161 | }
162 |
163 | /**
164 | * @return the m_CGMTimeIndex
165 | */
166 | public static synchronized int getM_CGMTimeIndex() {
167 | return m_CGMTimeIndex;
168 | }
169 |
170 | }
171 |
--------------------------------------------------------------------------------
/src/main/java/loader/DataLoadLibreView.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.text.ParseException;
8 | import java.time.LocalDateTime;
9 | import java.util.Collections;
10 | import java.util.Date;
11 | import java.util.logging.Level;
12 | import java.util.logging.Logger;
13 |
14 | import control.MyLogger;
15 | import entity.DBResult;
16 | import entity.DBResultEntry;
17 | import entity.DBResultEntryLibreView;
18 | import entity.ResultFromDBComparator;
19 | import utils.CommonUtils;
20 |
21 | public class DataLoadLibreView extends DataLoadCSVFile
22 | {
23 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
24 | private static final String m_LibreViewSplitBy = ",";
25 |
26 | private static final String VARIABLE_STRING = "VARIES_BY_EXPORT_DO_NOT_COMPARE";
27 |
28 | private static final String LINE_1_HEADERS[] =
29 | {
30 | "Glucose Data",
31 | "Generated on",
32 | "VARIES_BY_EXPORT_DO_NOT_COMPARE",
33 | "Generated by",
34 | "VARIES_BY_EXPORT_DO_NOT_COMPARE",
35 |
36 | };
37 |
38 | private static final String LINE_2_HEADERS[] =
39 | {
40 | "Device",
41 | "Serial Number",
42 | "Device Timestamp",
43 | "Record Type",
44 | "Historic Glucose mmol/L",
45 | "Scan Glucose mmol/L",
46 | "Non-numeric Rapid-Acting Insulin",
47 | "Rapid-Acting Insulin (units)",
48 | "Non-numeric Food",
49 | "Carbohydrates (grams)",
50 | "Carbohydrates (servings)",
51 | "Non-numeric Long-Acting Insulin",
52 | "Long-Acting Insulin Value (units)",
53 | "Notes",
54 | "Strip Glucose mmol/L",
55 | "Ketone mmol/L",
56 | "Meal Insulin (units)",
57 | "Correction Insulin (units)",
58 | "User Change Insulin (units)",
59 | };
60 |
61 | public DataLoadLibreView()
62 | {
63 | m_SkipLines = 2;
64 | m_HeaderLine = 2;
65 | }
66 |
67 | static public Date parseFileDateTime(String date)
68 | {
69 | Date result = null;
70 |
71 | try {
72 | result = CommonUtils.convertDateString(date);
73 | } catch (ParseException e1) {
74 | m_Logger.log(Level.SEVERE, " " + "parseFileDate - Unexpected error parsing date: " + date);
75 |
76 | }
77 | return result;
78 | }
79 |
80 | static public LocalDateTime parseFileLocalDateTime(String date)
81 | {
82 | LocalDateTime result = null;
83 |
84 | try {
85 | result = CommonUtils.convertLocalDateTimeString(date);
86 | } catch (ParseException e1) {
87 | m_Logger.log(Level.SEVERE, " " + "parseFileLocalDateTime - Unexpected error parsing date: " + date);
88 |
89 | }
90 | return result;
91 | }
92 |
93 |
94 | @Override
95 | protected DBResult makeDBResult(String[] res) {
96 | return null;
97 | }
98 |
99 | @Override
100 | protected DBResultEntry makeDBResultEntry(String[] res)
101 | {
102 | DBResultEntry resultEntry = null;
103 |
104 | resultEntry = new DBResultEntryLibreView(res);
105 |
106 | return resultEntry;
107 | }
108 |
109 | @Override
110 | protected void initializeHeaders(String[] res)
111 | {
112 | DBResultEntryLibreView.initializeCGMHeaders(res);
113 | }
114 |
115 | @Override
116 | protected void resetCGMHeaders()
117 | {
118 | DBResultEntryLibreView.resetCGMHeaders();
119 | }
120 |
121 | @Override
122 | protected void orderRawResults()
123 | {
124 | Collections.sort(rawResultsFromDB, new ResultFromDBComparator(false));
125 | }
126 |
127 | @Override
128 | protected String loadStringName()
129 | {
130 | // TODO Auto-generated method stub
131 | return null;
132 | }
133 |
134 | @Override
135 | protected String getSplitBy()
136 | {
137 | return m_LibreViewSplitBy;
138 | }
139 |
140 | public static boolean isLibreView(String fileName)
141 | {
142 | boolean result = true; // Assume it is to start with
143 | BufferedReader br = null;
144 | String line = "";
145 | String cvsSplitBy = m_LibreViewSplitBy;
146 |
147 | int ln = 0;
148 | int maxLines = 2;
149 |
150 | try
151 | {
152 | br = new BufferedReader(new FileReader(fileName));
153 | while (result && (ln <= maxLines) && (line = br.readLine()) != null)
154 | {
155 | ln++;
156 | // use comma as separator
157 | String[] rs = line.split(cvsSplitBy);
158 |
159 | result = ln == 1 ? doesLineMatch(rs, LINE_1_HEADERS, VARIABLE_STRING) : result;
160 | result = ln == 2 ? doesLineMatch(rs, LINE_2_HEADERS, VARIABLE_STRING) : result;
161 | }
162 |
163 | }
164 | catch (FileNotFoundException e)
165 | {
166 | m_Logger.log(Level.SEVERE, "" + "isLibreView: FileNotFoundException. File " + fileName + " Error " + e.getMessage());
167 |
168 | e.printStackTrace();
169 | }
170 | catch (IOException e)
171 | {
172 | m_Logger.log(Level.SEVERE, "" + "isLibreView: IOException. File " + fileName + " Error " + e.getMessage());
173 | e.printStackTrace();
174 | }
175 | finally
176 | {
177 | if (br != null)
178 | {
179 | try
180 | {
181 | br.close();
182 | }
183 | catch (IOException e)
184 | {
185 | m_Logger.log(Level.SEVERE, "" + "isLibreView: IOException closing file. File " + fileName + " Error " + e.getMessage());
186 | e.printStackTrace();
187 | }
188 | }
189 | }
190 |
191 | return result;
192 | }
193 |
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultEntryDiasend.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.text.ParseException;
4 | import java.util.Date;
5 | import org.apache.poi.hssf.usermodel.HSSFRow;
6 |
7 | import com.mongodb.DBObject;
8 |
9 | import loader.AuditHistory;
10 | import utils.CommonUtils;
11 | import loader.DataLoadDiasend;
12 |
13 | public class DBResultEntryDiasend extends DBResultEntry
14 | {
15 | // Collection of items to handle the CGM tab
16 | static private boolean m_CGMIndexesInitialized = false;
17 | static private String[] m_CGMFieldNames =
18 | {
19 | "Time",
20 | "mmol/L mg/dl", // We can see either string come through
21 | "", // This field is empty
22 | "Serial number"
23 | };
24 | static private int m_CGMTimeIndex = 0;
25 | static private int m_CGMBGIndex = 0;
26 |
27 |
28 | public DBResultEntryDiasend(DBObject rs) {
29 | super(rs);
30 | // TODO Auto-generated constructor stub
31 | }
32 |
33 | public DBResultEntryDiasend(String m_ID, Double m_Unfiltered, Double m_Filtered, String m_Direction, String m_Device,
34 | Double m_RSSI, Double m_SGV, String m_DateString, String m_Type, Double m_Date, Integer m_Noise) throws ParseException
35 | {
36 | super(m_ID, m_Unfiltered, m_Filtered, m_Direction, m_Device,
37 | m_RSSI, m_SGV, m_DateString, m_Type, m_Date, m_Noise);
38 | }
39 |
40 | public DBResultEntryDiasend(HSSFRow row)
41 | {
42 | // Handle aa CGM record
43 | loadRawCGM(row);
44 | }
45 |
46 | public static void resetCGMHeaders()
47 | {
48 | m_CGMIndexesInitialized = false;
49 | }
50 |
51 | public static Boolean initializeCGMHeaders(HSSFRow row)
52 | {
53 | Boolean result = false;
54 |
55 | if (m_CGMIndexesInitialized == false)
56 | {
57 | m_CGMTimeIndex = -1;
58 | m_CGMBGIndex = -1;
59 |
60 | int maxColumns = row.getPhysicalNumberOfCells();
61 |
62 | // Diasend now has an empty column
63 | int cols = 0;
64 | for (int i = 0; i < m_CGMFieldNames.length; i++) cols += m_CGMFieldNames[i].length() > 0 ? 1 : 0;
65 |
66 | if (maxColumns >= cols)
67 | {
68 | int c = 0;
69 |
70 | for (c=0; c < m_CGMFieldNames.length; c++)
71 | {
72 | if (row.getCell(c) != null)
73 | {
74 | String cell = row.getCell(c).getStringCellValue();
75 | if (m_CGMFieldNames[c].contains(cell))
76 | {
77 | switch (c)
78 | {
79 | case 0 : m_CGMTimeIndex = c; break;
80 | case 1 : m_CGMBGIndex = c; break;
81 | default : break;
82 | }
83 | }
84 | }
85 | }
86 | m_CGMIndexesInitialized = true;
87 | }
88 | }
89 |
90 | result = (m_CGMTimeIndex != -1) && (m_CGMBGIndex != -1) ? true : false;
91 |
92 | return result;
93 | }
94 |
95 | private void loadRawCGM(HSSFRow row)
96 | {
97 | String timeStr = CommonUtils.getStringCellValue(row, m_CGMTimeIndex);
98 | Double bgDouble = CommonUtils.getDoubleCellValue(row, m_CGMBGIndex);
99 |
100 | m_Device = AuditHistory.getInstance().getM_NextUploadID();
101 |
102 | m_Type = "sgv";
103 | if (bgDouble != null)
104 | {
105 | m_SGV = bgDouble * 18; // Values held in mgDl
106 | m_BG = bgDouble;
107 | }
108 |
109 | if (timeStr != null)
110 | {
111 | Date d = new Date(0);
112 | // d = parseFileDate(timeStr);
113 | d = DataLoadDiasend.parseFileDateTime(timeStr);
114 | if (d.getTime() != 0)
115 | {
116 | //This isn't working, it's applying the offset twice, I suspect something to
117 | //do with Date.getTime() always returning results for display in local TZ
118 | //Date utcD = new Date(CommonUtils.toUTC(d.getTime()));
119 | Date utcD = new Date(d.getTime());
120 | this.setM_UTCDate(utcD);
121 |
122 | try {
123 | this.setM_DateString(CommonUtils.convertNSZDateString(d));
124 | } catch (ParseException e) {
125 | m_Logger.severe("Error converting Date to NSZDateString : " + timeStr);
126 | }
127 |
128 |
129 | // Essential for use in comparator
130 | setEpochMilliesFromUTC();
131 | }
132 | }
133 | }
134 |
135 | /**
136 | * @return the m_CGMTimeIndex
137 | */
138 | public static synchronized int getM_CGMTimeIndex() {
139 | return m_CGMTimeIndex;
140 | }
141 |
142 | // private Date parseFileDateTime(String date)
143 | // {
144 | // Date result = new Date(0);
145 | // // Combined Date Time
146 | //
147 | //// final String defSlashFormat = new String("dd/MM/yy HH:mm"); -- Changed with Glooko?
148 | // // In fact, now find that it changes between dd/MM/yyyy and MM/dd/yyyy, so we hold a preference
149 | // // and set the preference during an initial file scan
150 | //
151 | // final String defSlashFormat = new String(
152 | // PrefsNightScoutLoader.getInstance().getM_DiasendDateFormat() + " HH:mm");
153 | //
154 | // String prefDateFormat = PrefsNightScoutLoader.getInstance().getM_InputDateFormat();
155 | // DateFormat slashformat = new SimpleDateFormat((prefDateFormat.contains("/") ? prefDateFormat : defSlashFormat), Locale.ENGLISH);
156 | // // DateFormat slashformat = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.ENGLISH);
157 | //
158 | // try
159 | // {
160 | // result = slashformat.parse(date);
161 | // }
162 | // catch (ParseException e)
163 | // {
164 | // m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+"> " + "parseFileDate - Unexpected error parsing date: " + date);
165 | // }
166 | //
167 | // return result;
168 | // }
169 |
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/java/win/WinTextWin.java:
--------------------------------------------------------------------------------
1 | package win;
2 | import java.awt.BorderLayout;
3 | import java.awt.EventQueue;
4 |
5 | import javax.swing.JPanel;
6 | import java.awt.FlowLayout;
7 | import java.awt.Font;
8 |
9 | import javax.swing.JFileChooser;
10 | import javax.swing.JFrame;
11 | import javax.swing.JMenu;
12 | import javax.swing.JMenuBar;
13 | import javax.swing.JMenuItem;
14 | import javax.swing.border.EmptyBorder;
15 | import javax.swing.filechooser.FileNameExtensionFilter;
16 |
17 | import control.MyLogger;
18 | import entity.TextLineReceiverInterface;
19 |
20 | import javax.swing.JTextArea;
21 | import java.awt.event.ActionListener;
22 | import java.awt.event.MouseAdapter;
23 | import java.awt.event.MouseEvent;
24 | import java.io.IOException;
25 | import java.io.PrintWriter;
26 | import java.util.ArrayList;
27 | import java.util.logging.Level;
28 | import java.util.logging.Logger;
29 | import java.awt.event.ActionEvent;
30 | import javax.swing.JScrollPane;
31 | import javax.swing.JSeparator;
32 |
33 | // public class WinTextWin extends JDialog implements TextLineReceiverInterface
34 | public class WinTextWin extends JFrame implements TextLineReceiverInterface
35 | {
36 |
37 | /**
38 | *
39 | */
40 | private static final long serialVersionUID = -51832866421758739L;
41 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
42 |
43 | private final JPanel contentPanel = new JPanel();
44 | private JTextArea txtrNightscoutloader = new JTextArea();
45 |
46 | private String m_Text;
47 | private ArrayList m_AppendedLines;
48 |
49 | protected JMenuBar m_MenuBar;
50 | protected JMenu m_mnFile;
51 | protected JMenuItem m_mntmFileSave;
52 | protected JMenuItem m_mntmFileClose;
53 | protected boolean m_Enabled;
54 |
55 |
56 | /**
57 | * Create the dialog.
58 | */
59 | public WinTextWin(String title)
60 | {
61 | super.setTitle(title);
62 |
63 | // URL url = MainNightScoutLoader.class.getResource("/Nightscout.jpg");
64 | // ImageIcon img = new ImageIcon(url);
65 | // setIconImage(img.getImage());
66 |
67 | m_MenuBar = new JMenuBar();
68 | setJMenuBar(m_MenuBar);
69 |
70 | m_mnFile = new JMenu("File");
71 | m_mnFile.addMouseListener(new MouseAdapter() {
72 | @Override
73 | public void mouseClicked(MouseEvent arg0)
74 | {
75 | // Nothing needed here
76 | }
77 | });
78 |
79 | m_MenuBar.add(m_mnFile);
80 |
81 | m_mntmFileSave = new JMenuItem("Save Text");
82 | m_mntmFileSave.addActionListener(new ActionListener() {
83 | public void actionPerformed(ActionEvent e)
84 | {
85 | doSaveText();
86 | }
87 | });
88 | m_mnFile.add(m_mntmFileSave);
89 | m_mnFile.add(new JSeparator()); // SEPARATOR
90 |
91 | m_mntmFileClose = new JMenuItem("Close");
92 | m_mntmFileClose.addActionListener(new ActionListener() {
93 | public void actionPerformed(ActionEvent e)
94 | {
95 | setVisible(false);
96 | }
97 | });
98 | m_mnFile.add(m_mntmFileClose);
99 |
100 |
101 | m_Text = new String();
102 | m_AppendedLines = new ArrayList();
103 |
104 | setBounds(100, 100, 750, 620);
105 | getContentPane().setLayout(new BorderLayout());
106 | contentPanel.setLayout(new FlowLayout());
107 | contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
108 | getContentPane().add(contentPanel, BorderLayout.CENTER);
109 |
110 | Font font = new Font("Courier", Font.BOLD, 12);
111 |
112 | getContentPane().add(txtrNightscoutloader, BorderLayout.WEST);
113 | txtrNightscoutloader.setFont(font);
114 |
115 | JScrollPane scrollPane = new JScrollPane(txtrNightscoutloader);
116 | getContentPane().add(scrollPane, BorderLayout.CENTER);
117 | }
118 |
119 | public void setText(String text)
120 | {
121 | m_Text = text;
122 | txtrNightscoutloader.setText(m_Text);
123 | }
124 |
125 | @Override
126 | public void addTextLine(String line)
127 | {
128 | m_Text += line;
129 | m_AppendedLines.add(line);
130 |
131 | // Do this in the GUI thread
132 | EventQueue.invokeLater(new
133 | Runnable()
134 | {
135 | public void run()
136 | {
137 | String line = null;
138 | if (m_AppendedLines.size() > 0)
139 | {
140 | line = m_AppendedLines.get(0);
141 | txtrNightscoutloader.append(line);
142 | m_AppendedLines.remove(0);
143 | }
144 | }
145 | });
146 | }
147 |
148 | protected void setMenusEnabled(JMenu m)
149 | {
150 | for (int i = 0; i < m.getItemCount(); i++)
151 | {
152 | JMenuItem mi = m.getItem(i);
153 | if (mi != null)
154 | {
155 | mi.setEnabled(m_Enabled);
156 | }
157 | }
158 | }
159 |
160 |
161 | private void doSaveText()
162 | {
163 | // Popup a dialog to select the file for saving contents to
164 | JFileChooser chooser = new JFileChooser();
165 | FileNameExtensionFilter filter = new FileNameExtensionFilter(
166 | "Text Files", "txt");
167 | chooser.setFileFilter(filter);
168 | // File selectedFile = new File(PrefsNightScoutLoader.getInstance().getM_AnalysisFilePath());
169 | // chooser.setSelectedFile(selectedFile);
170 | int returnVal = chooser.showOpenDialog(getContentPane());
171 | if(returnVal == JFileChooser.APPROVE_OPTION)
172 | {
173 | m_Logger.log(Level.INFO, "You chose to Save to this file: " +
174 | chooser.getSelectedFile().getAbsolutePath());
175 |
176 | try
177 | {
178 | PrintWriter writer = new PrintWriter(chooser.getSelectedFile().getAbsolutePath(), "UTF-8");
179 | writer.print(m_Text);
180 |
181 | writer.close();
182 | }
183 | catch (IOException e)
184 | {
185 | // do something
186 | }
187 | }
188 |
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/java/mongo/NightscoutMongoDB.java:
--------------------------------------------------------------------------------
1 | package mongo;
2 |
3 | import java.lang.management.ManagementFactory;
4 | import java.lang.management.RuntimeMXBean;
5 | import java.util.List;
6 | import org.bson.Document;
7 |
8 | import com.mongodb.DB;
9 | import com.mongodb.DBCollection;
10 | import com.mongodb.MongoClient;
11 | import com.mongodb.MongoClientURI;
12 | import com.mongodb.WriteConcern;
13 | import com.mongodb.client.MongoCollection;
14 | import com.mongodb.client.MongoDatabase;
15 | import control.PrefsNightScoutLoader;
16 |
17 | public class NightscoutMongoDB {
18 |
19 | private final String m_MongoHost = PrefsNightScoutLoader.getInstance().getM_NightscoutMongoServer();
20 | private final String m_MongoDB = PrefsNightScoutLoader.getInstance().getM_NightscoutMongoDB();
21 | private final String m_TreatmentsCollection = PrefsNightScoutLoader.getInstance().getM_NightscoutMongoCollection();
22 | private final String m_RocheDebugCollection = PrefsNightScoutLoader.getInstance().getM_MongoMeterCollection();
23 | private final String m_AuditCollection = PrefsNightScoutLoader.getInstance().getM_NightscoutAuditCollection();
24 | private final String m_SensorCollection = PrefsNightScoutLoader.getInstance().getM_NightscoutSensorMongoCollection();
25 | private final String m_ProfileCollection = PrefsNightScoutLoader.getInstance().getM_NightscoutProfileCollection();
26 |
27 | private MongoClient m_DbClient = null;
28 | private DB m_Db = null;
29 | private MongoDatabase m_MongoDatabase = null;
30 |
31 | private Boolean m_TLSValidBoolean = false;
32 |
33 | public NightscoutMongoDB()
34 | {
35 | initialise();
36 | }
37 |
38 | public NightscoutMongoDB(String mongoHost)
39 | {
40 | initialise(mongoHost);
41 | }
42 |
43 | public NightscoutMongoDB(String mongoHost, String mongoDB)
44 | {
45 | initialise(mongoHost, mongoDB);
46 | }
47 |
48 | // Original V2.x interface used when NightscoutLoader was first written 2015
49 | public DBCollection getTreatmentsV2xCollection()
50 | {
51 | return m_Db.getCollection(m_TreatmentsCollection);
52 | }
53 |
54 | public DBCollection getAuditV2xCollection()
55 | {
56 | return m_Db.getCollection(m_AuditCollection);
57 | }
58 |
59 | public DBCollection getSensorV2xCollection()
60 | {
61 | return m_Db.getCollection(m_SensorCollection);
62 | }
63 |
64 | public DBCollection getRocheDebugMeterV2xCollection()
65 | {
66 | return m_Db.getCollection(m_RocheDebugCollection);
67 | }
68 |
69 | public DBCollection getProfileCollectionV2xCollection()
70 | {
71 | return m_Db.getCollection(m_ProfileCollection);
72 | }
73 |
74 |
75 |
76 | // V3.0.0 interface
77 | public MongoCollection getTreatmentsCollection()
78 | {
79 | return m_MongoDatabase.getCollection(m_TreatmentsCollection);
80 | }
81 |
82 | public MongoCollection getAuditCollection()
83 | {
84 | return m_MongoDatabase.getCollection(m_AuditCollection);
85 | }
86 |
87 | public MongoCollection getSensorCollection()
88 | {
89 | return m_MongoDatabase.getCollection(m_SensorCollection);
90 | }
91 |
92 | public MongoCollection getRocheDebugMeterCollection()
93 | {
94 | return m_MongoDatabase.getCollection(m_RocheDebugCollection);
95 | }
96 |
97 | public MongoCollection getProfileCollectionCollection()
98 | {
99 | return m_MongoDatabase.getCollection(m_ProfileCollection);
100 | }
101 |
102 | public void close()
103 | {
104 | m_DbClient.close();
105 | }
106 |
107 | private void initialise()
108 | {
109 | initialise(m_MongoHost, m_MongoDB);
110 | }
111 |
112 | private void initialise(String mongoHost)
113 | {
114 | initialise(mongoHost, null);
115 | }
116 |
117 |
118 | @SuppressWarnings("deprecation")
119 | private void initialise(String mongoHost, String mongoDB)
120 | {
121 | initialiseTLSValid();
122 |
123 | MongoClientURI dbURI;
124 |
125 | if (mongoHost.contains("@"))
126 | {
127 | // Create full URI with DB too. This is straight from the https://mongolab.com/databases/dexcom_db page
128 | // dbURI = new MongoClientURI(m_MongoHost + ":" + mongoPort + "/" + mongoDB);
129 |
130 | // Left like below after a few days not using server but not working clearly :-(
131 | //dbURI = new MongoClientURI(m_MongoHost + ":" + "/" + mongoDB);
132 |
133 | dbURI = new MongoClientURI(mongoHost);
134 | m_DbClient = new MongoClient(dbURI);
135 | }
136 | else
137 | {
138 | m_DbClient = new MongoClient(mongoHost);
139 | }
140 |
141 | if (mongoDB != null)
142 | {
143 | m_Db = m_DbClient.getDB(mongoDB);
144 |
145 | m_MongoDatabase = m_DbClient.getDatabase(mongoDB).withWriteConcern(WriteConcern.MAJORITY);
146 | }
147 | }
148 |
149 | private void initialiseTLSValid()
150 | {
151 | RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
152 | List list = runtimeMxBean.getInputArguments();
153 |
154 | for (String s : list)
155 | {
156 | m_TLSValidBoolean = s.contains("jdk.tls.client.protocols") && s.contains("TLSv1.2") ? true : m_TLSValidBoolean;
157 | }
158 | }
159 |
160 | /**
161 | * @return the m_DbClient
162 | */
163 | public synchronized MongoClient getM_DbClient() {
164 | return m_DbClient;
165 | }
166 |
167 | /**
168 | * @return the m_Db
169 | */
170 | public synchronized DB getM_Db() {
171 | return m_Db;
172 | }
173 |
174 | /**
175 | * @return the m_MongoDatabase
176 | */
177 | public synchronized MongoDatabase getM_MongoDatabase() {
178 | return m_MongoDatabase;
179 | }
180 |
181 | /**
182 | * @return the m_TLSValidBoolean
183 | */
184 | public synchronized Boolean getM_TLSValidBoolean() {
185 | return m_TLSValidBoolean;
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultCore.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.text.DateFormat;
4 | import java.text.SimpleDateFormat;
5 | import java.util.Date;
6 |
7 | import com.mongodb.BasicDBObject;
8 |
9 | import control.PrefsNightScoutLoader;
10 |
11 | public abstract class DBResultCore implements DBResultInterface
12 | {
13 | // Sep 2016
14 | // Proximity checks are for where we have a new Meter/Pump entry coming into an
15 | // existing NightScout Care Portal data set, and there's a possible duplicate
16 | // among them.
17 | protected static boolean m_ProximityCheck = false;
18 | protected static boolean m_ProximityCheckSecondPass = false;
19 |
20 | // Proximity match with an existing record
21 | private boolean m_ProximityPossibleDuplicate = false;
22 |
23 |
24 | // Can only instantiate derived classes
25 | protected DBResultCore()
26 | {
27 |
28 | }
29 |
30 | public long getProximityAdjustedTime(long time)
31 | {
32 | long result = 0;
33 |
34 | if (m_ProximityCheck == true)
35 | {
36 | // How many minutes apart two entries can be before being considered proximity/duplicate
37 | int proximityMinutes = PrefsNightScoutLoader.getInstance().getM_ProximityMinutes();
38 |
39 | // Since we may have 2 adjacent readings either side of the mid point of proximityMinutes, we do a second
40 | // pass looking for proximity matches but this time slide the time forward by half the proximityMinutes
41 | if (m_ProximityCheckSecondPass == true)
42 | {
43 | long halfProximityMinutesMillis = proximityMinutes * 60 * 1000 / 2;
44 |
45 | time += halfProximityMinutesMillis;
46 | }
47 |
48 | long roundPeriodMins = proximityMinutes * 60 * 1000;
49 | // Adjust time by rounding up or down to nearest proximity minutes approximately.
50 |
51 | long timeUp = time - (time % roundPeriodMins) + roundPeriodMins;
52 | long timeDown = time - (time % roundPeriodMins);
53 |
54 | // Are we closer to Up time or Down
55 | if ( (timeUp - time) > (time - timeDown) )
56 | {
57 | result = timeDown;
58 | }
59 | else
60 | {
61 | result = timeUp;
62 | }
63 | }
64 | else
65 | {
66 | result = time;
67 | }
68 |
69 | return result;
70 | }
71 |
72 | static public void appendToDoc(BasicDBObject doc, String label, String value)
73 | {
74 | if (value.length() > 0)
75 | {
76 | doc.append(label, value);
77 | }
78 | }
79 |
80 | static public void appendToDoc(BasicDBObject doc, String label, Double value)
81 | {
82 | if (value != null)
83 | {
84 | doc.append(label, doubleIsInteger(value) ? value.longValue() : value.doubleValue());
85 | }
86 | }
87 |
88 | static public void appendToDoc(BasicDBObject doc, String label, int value)
89 | {
90 | doc.append(label, value);
91 | }
92 |
93 | static public void appendToDoc(BasicDBObject doc, String label, Date value)
94 | {
95 | if (value != null)
96 | {
97 | // 16 Jun 2016
98 | // Feedback from Mel in Australia that times are shifted
99 | // Realise that I need to convert from local to UTC times!
100 | // final DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'", Locale.ENGLISH);
101 | // final DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); // Try something different
102 |
103 | final DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
104 | // Date utcValue = new Date(CommonUtils.toUTC(value.getTime(), CommonUtils.locTZ));
105 | // String dVal = format.format(utcValue);
106 |
107 | String dVal = format.format(value);
108 |
109 | doc.append(label, dVal);
110 | }
111 |
112 | }
113 |
114 | static public boolean doubleIsInteger(double val)
115 | {
116 | boolean result = false; // Assume not initially
117 |
118 | if (val == Math.floor(val))
119 | {
120 | result = true;
121 | }
122 | return result;
123 | }
124 |
125 |
126 | /**
127 | * @return the m_ProximityCheck
128 | */
129 | public static synchronized boolean isM_ProximityCheck() {
130 | return m_ProximityCheck;
131 | }
132 |
133 | /**
134 | * @param m_ProximityCheck the m_ProximityCheck to set
135 | */
136 | public static synchronized void setM_ProximityCheck(boolean proximityCheck) {
137 | DBResultCore.m_ProximityCheck = proximityCheck;
138 | }
139 |
140 | /**
141 | * @return the m_ProximityCheckSecondPass
142 | */
143 | public static synchronized boolean isM_ProximityCheckSecondPass() {
144 | return m_ProximityCheckSecondPass;
145 | }
146 |
147 | /**
148 | * @param m_ProximityCheckSecondPass the m_ProximityCheckSecondPass to set
149 | */
150 | public static synchronized void setM_ProximityCheckSecondPass(boolean proximityCheckSecondPass) {
151 | DBResultCore.m_ProximityCheckSecondPass = proximityCheckSecondPass;
152 | }
153 |
154 | /**
155 | * @return the m_ProximityPossibleDuplicate
156 | */
157 | public synchronized boolean isM_ProximityPossibleDuplicate()
158 | {
159 | determineWhetherInProximity();
160 | return m_ProximityPossibleDuplicate;
161 | }
162 |
163 | /**
164 | * @param m_ProximityPossibleDuplicate the m_ProximityPossibleDuplicate to set
165 | */
166 | public synchronized void setM_ProximityPossibleDuplicate(boolean m_ProximityPossibleDuplicate)
167 | {
168 | this.m_ProximityPossibleDuplicate = m_ProximityPossibleDuplicate;
169 |
170 | // David - 31 Jan 2018
171 | // This caused java.lang.StackOverflowError
172 | // setImpactOfProximity();
173 | }
174 |
175 | /**
176 | * @param m_ProximityPossibleDuplicate the m_ProximityPossibleDuplicate to set
177 | */
178 |
179 | public synchronized boolean getM_ProximityPossibleDuplicate()
180 | {
181 | return this.m_ProximityPossibleDuplicate;
182 | }
183 |
184 | }
185 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | 4.0.0
7 |
8 | org.Nightscout.NightscoutLoader
9 | NightscoutLoaderMaven
10 | 0.0.1-SNAPSHOT
11 |
12 | NightscoutLoaderMaven
13 | A simple NightscoutLoaderMaven.
14 | https://david50703.wixsite.com/nightscoutloader
15 |
16 |
17 | UTF-8
18 | 1.8
19 | 1.8
20 |
21 |
22 |
23 |
24 |
25 | org.junit.jupiter
26 | junit-jupiter-api
27 | 5.8.1
28 | test
29 |
30 |
31 |
32 | org.junit.jupiter
33 | junit-jupiter-engine
34 | 5.8.1
35 | test
36 |
37 |
38 |
39 |
40 |
41 | org.apache.poi
42 | poi
43 | 3.13
44 |
45 |
46 |
47 | org.apache.poi
48 | poi-ooxml
49 | 3.13
50 |
51 |
52 |
53 |
54 | org.mongodb
55 | mongo-java-driver
56 | 3.12.10
57 |
58 |
59 |
60 |
61 | com.jcraft
62 | jsch
63 | 0.1.55
64 |
65 |
66 |
67 |
68 | com.googlecode.json-simple
69 | json-simple
70 | 1.1.1
71 |
72 |
73 |
74 |
75 | net.sourceforge.jdatepicker
76 | jdatepicker
77 | 1.3.2
78 |
79 |
80 |
81 |
82 | commons-cli
83 | commons-cli
84 | 1.4
85 |
86 |
87 |
88 | org.mockito
89 | mockito-core
90 | 2.23.4
91 | test
92 |
93 |
94 |
95 |
96 |
97 |
98 |
100 |
101 |
102 | maven-clean-plugin
103 | 3.1.0
104 |
105 |
106 | maven-site-plugin
107 | 3.7.1
108 |
109 |
110 | maven-project-info-reports-plugin
111 | 3.0.0
112 |
113 |
114 |
115 |
116 | maven-resources-plugin
117 | 3.0.2
118 |
119 |
120 | maven-compiler-plugin
121 | 3.8.0
122 |
123 |
124 | maven-surefire-plugin
125 | 2.22.1
126 |
127 |
128 | maven-jar-plugin
129 | 3.0.2
130 |
131 |
132 | maven-install-plugin
133 | 2.5.2
134 |
135 |
136 | maven-deploy-plugin
137 | 2.8.2
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | org.apache.maven.plugins
146 | maven-assembly-plugin
147 | 3.0.0
148 |
149 |
150 |
151 | jar-with-dependencies
152 |
153 |
154 | NightScoutLoader
155 | false
156 |
157 |
158 |
159 | control.MainNightScoutLoader
160 |
161 |
162 |
163 |
164 |
165 |
166 | package
167 |
168 | single
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 | maven-project-info-reports-plugin
184 |
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultCellNovoRaw.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.text.ParseException;
4 | import java.util.ArrayList;
5 | import java.util.Date;
6 | import utils.CommonUtils;
7 |
8 | public class DBResultCellNovoRaw extends DBResult
9 | {
10 | static final int m_HourlyValues = 25;
11 | static final int m_FinalHourlyValue = 24;
12 |
13 | String m_Date = new String("");
14 | String m_Type = new String("");
15 |
16 | String[] m_HourlyValuesPlusTotal = new String[m_HourlyValues];
17 |
18 | public DBResultCellNovoRaw(String[] rs)
19 | {
20 | if (rs.length == 27)
21 | {
22 | int i = 0;
23 | m_Date = rs[i++];
24 | m_Type = rs[i++];
25 |
26 | for (int j = 0; j < m_HourlyValues; j++)
27 | {
28 | m_HourlyValuesPlusTotal[j] = rs[i++];
29 | }
30 | }
31 | }
32 |
33 | public ArrayList createDBResults()
34 | {
35 | ArrayList result = new ArrayList();
36 |
37 | // We're not really interested in the final total value
38 | for (int i = 0; i < m_FinalHourlyValue; i++)
39 | {
40 | if (m_Type.equals("Blood Glucose"))
41 | {
42 | ArrayList bgs = this.readBGValues(m_HourlyValuesPlusTotal[i]);
43 |
44 | // How many results do we have?
45 | // Distribute them across the hour evenly.
46 | int minGap = 60 / (bgs.size() > 0 ? bgs.size() : 1);
47 |
48 | int j = 0;
49 | for (Double d : bgs)
50 | {
51 | Date date = createDateFromString(m_Date, i, j++ * minGap);
52 | DBResult dbRes = createDBResult("BG", date, d);
53 | result.add(dbRes);
54 | }
55 | }
56 | else if (m_Type.equals("Food"))
57 | {
58 | if (m_HourlyValuesPlusTotal[i].length() > 0)
59 | {
60 | Date date = createDateFromString(m_Date, i);
61 | DBResult dbRes = createDBResult("Carbs", date, m_HourlyValuesPlusTotal[i]);
62 | result.add(dbRes);
63 | }
64 | }
65 | else if (m_Type.equals("Bolus"))
66 | {
67 | if (m_HourlyValuesPlusTotal[i].length() > 0)
68 | {
69 | Date date = createDateFromString(m_Date, i);
70 | DBResult dbRes = createDBResult("Standard Bolus", date, m_HourlyValuesPlusTotal[i]);
71 | result.add(dbRes);
72 | }
73 | }
74 | }
75 |
76 | return result;
77 | }
78 |
79 | public boolean isValid()
80 | {
81 | boolean result = false;
82 |
83 | if ( (m_Date.length() > 0 && m_Type.length() > 0) &&
84 | !m_Date.equals("Date") )
85 | {
86 |
87 | result = true;
88 | }
89 |
90 | return result;
91 | }
92 |
93 | private DBResult createDBResult(String type, Date date, String val)
94 | {
95 | DBResult result = new DBResult();
96 |
97 | Double d = readValue(val);
98 | result.setM_Time(date);
99 | result.setM_ResultType(type);
100 | result.setM_Result(Double.toString(d));
101 |
102 | // Set epoch millies too for later use in comparator
103 | result.setM_EpochMillies(date.getTime());
104 |
105 | return result;
106 | }
107 |
108 | private DBResult createDBResult(String type, Date date, Double val)
109 | {
110 | DBResult result = new DBResult();
111 |
112 | result.setM_Time(date);
113 | result.setM_ResultType(type);
114 | result.setM_Result(Double.toString(val));
115 |
116 | // Set epoch millies too for later use in comparator
117 | result.setM_EpochMillies(date.getTime());
118 |
119 | return result;
120 | }
121 |
122 |
123 | private Date createDateFromString(String date, int hour)
124 | {
125 | Date result = createDateFromString(date, hour, 0);
126 | return result;
127 | }
128 |
129 | private Date createDateFromString(String date, int hour, int mins)
130 | {
131 | Date result = new Date(0);
132 |
133 | String format = new String("EEEE dd MMM yyyyy HH:mm");
134 | try
135 | {
136 | String dateTime = date + " " + String.format("%02d", hour) + ":" + String.format("%02d", mins);
137 |
138 | result = CommonUtils.convertDateString(dateTime);
139 | }
140 | catch (ParseException e)
141 | {
142 | // TODO Auto-generated catch block
143 | e.printStackTrace();
144 | }
145 |
146 | return result;
147 | }
148 |
149 |
150 | private ArrayList readBGValues(String field)
151 | {
152 | ArrayList result = new ArrayList();
153 |
154 | String[] bgVals = field.split("/ ");
155 |
156 | for (int i = 0; i < bgVals.length; i++)
157 | {
158 | if (bgVals[i].length() > 0)
159 | {
160 | Double val = readValue(bgVals[i]);
161 | result.add(val);
162 | }
163 | }
164 |
165 | return result;
166 | }
167 |
168 | private Double readValue(String val)
169 | {
170 | Double result = 0.0;
171 |
172 | String[] vals = val.split(" ");
173 |
174 | if (vals.length > 0)
175 | {
176 | result = Double.parseDouble(vals[0]);
177 | }
178 |
179 | return result;
180 | }
181 |
182 | /**
183 | * @return the m_Date
184 | */
185 | public synchronized String getM_Date() {
186 | return m_Date;
187 | }
188 |
189 | /**
190 | * @param m_Date the m_Date to set
191 | */
192 | public synchronized void setM_Date(String m_Date) {
193 | this.m_Date = m_Date;
194 | }
195 |
196 | /**
197 | * @return the m_Type
198 | */
199 | public synchronized String getM_Type() {
200 | return m_Type;
201 | }
202 |
203 | /**
204 | * @param m_Type the m_Type to set
205 | */
206 | public synchronized void setM_Type(String m_Type) {
207 | this.m_Type = m_Type;
208 | }
209 |
210 | /**
211 | * @return the m_HourlyValuesPlusTotal
212 | */
213 | public synchronized String[] getM_HourlyValuesPlusTotal() {
214 | return m_HourlyValuesPlusTotal;
215 | }
216 |
217 | /**
218 | * @param m_HourlyValuesPlusTotal the m_HourlyValuesPlusTotal to set
219 | */
220 | public synchronized void setM_HourlyValuesPlusTotal(String[] m_HourlyValuesPlusTotal) {
221 | this.m_HourlyValuesPlusTotal = m_HourlyValuesPlusTotal;
222 | }
223 |
224 |
225 |
226 |
227 |
228 |
229 | }
230 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultMedtronicOld.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.util.Date;
4 | import java.util.logging.Level;
5 | import java.util.logging.Logger;
6 | import control.MyLogger;
7 |
8 | public class DBResultMedtronicOld extends DBResultMedtronic
9 | {
10 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
11 |
12 | private static final String m_DateFormat = "dd/MM/yy";
13 | private static final String m_TimeFormat = "dd/MM/yy H:m:s";
14 |
15 | static protected String m_ReportRange = "Report Range";
16 |
17 | /* private boolean m_Valid;
18 | private boolean m_ReportDateRange;
19 | private Date m_StartDate;
20 | private Date m_EndDate;
21 | */
22 |
23 | static private String[] m_FieldNames =
24 | {
25 | "Index",
26 | "Date",
27 | "Time",
28 | "Timestamp",
29 | "New Device Time",
30 | "BG Reading (mmol/L)",
31 | "Linked BG Meter ID",
32 | "Temp Basal Amount (U/h)",
33 | "Temp Basal Type",
34 | "Temp Basal Duration (hh:mm:ss)",
35 | "Bolus Type",
36 | "Bolus Volume Selected (U)",
37 | "Bolus Volume Delivered (U)",
38 | "Bolus Duration (hh:mm:ss)",
39 | "Prime Type",
40 | "Prime Volume Delivered (U)",
41 | "Suspend",
42 | "Rewind",
43 | "BWZ Estimate (U)",
44 | "BWZ Target High BG (mmol/L)",
45 | "BWZ Target Low BG (mmol/L)",
46 | "BWZ Carb Ratio (grams)",
47 | "BWZ Insulin Sensitivity (mmol/L)",
48 | "BWZ Carb Input (grams)",
49 | "BWZ BG Input (mmol/L)",
50 | "BWZ Correction Estimate (U)",
51 | "BWZ Food Estimate (U)",
52 | "BWZ Active Insulin (U)",
53 | "Alarm",
54 | "Sensor Calibration BG (mmol/L)",
55 | "Sensor Glucose (mmol/L)",
56 | "ISIG Value",
57 | "Daily Insulin Total (U)",
58 | "Raw-Type",
59 | "Raw-Values",
60 | "Raw-ID",
61 | "Raw-Upload ID",
62 | "Raw-Seq Num",
63 | "Raw-Device Type",
64 | };
65 |
66 | static private boolean m_indexesInitialized = false;
67 | static private int m_DateIndex = 0;
68 | static private int m_TimeIndex = 0;
69 | static private int m_BolusTypeIndex = 0;
70 | static private int m_BGIndex = 0;
71 | static private int m_TempBasalAmountIndex = 0;
72 | static private int m_TempBasalDurationIndex = 0;
73 | static private int m_CarbAmountIndex = 0;
74 | static private int m_StandardBolusIndex = 0;
75 | static private int m_BolusDurationIndex = 0;
76 | static private int m_PrimeIndex = 0;
77 |
78 | @Override
79 | public boolean isValid()
80 | {
81 | return m_Valid;
82 | }
83 |
84 | @Override
85 | public boolean isReportRange()
86 | {
87 | return m_ReportDateRange;
88 | }
89 |
90 | public Date getStartReportRange()
91 | {
92 | return m_StartDate;
93 | }
94 | public Date getEndReportRange()
95 | {
96 | return m_EndDate;
97 | }
98 |
99 | public DBResultMedtronicOld(String[] recordSet)
100 | {
101 | super(recordSet);
102 | }
103 |
104 | @Override
105 | protected void initialize()
106 | {
107 | m_StartDate = new Date(0);
108 | m_EndDate = new Date(0);
109 |
110 | m_Valid = true;
111 | m_ReportDateRange = false;
112 |
113 | m_RecordSet = new String[m_FieldNames.length];
114 |
115 | // Set values in underdlying ResultFromDB from record set
116 | if (m_indexesInitialized == false)
117 | {
118 | m_DateIndex = fieldLocation("Date");
119 | m_TimeIndex = fieldLocation("Time");
120 | m_BolusTypeIndex = fieldLocation("Bolus Type");
121 | m_BGIndex = fieldLocation("BG Reading (mmol/L)");
122 | m_TempBasalAmountIndex = fieldLocation("Temp Basal Amount (U/h)");
123 | m_TempBasalDurationIndex = fieldLocation("Temp Basal Duration (hh:mm:ss)");
124 | m_CarbAmountIndex = fieldLocation("BWZ Carb Input (grams)");
125 | m_StandardBolusIndex = fieldLocation("Bolus Volume Delivered (U)");
126 | m_BolusDurationIndex = fieldLocation("Bolus Duration (hh:mm:ss)");
127 | // m_Time = fieldLocation("Timestamp");
128 | m_PrimeIndex = fieldLocation("Prime Type");
129 |
130 | m_indexesInitialized = true;
131 | }
132 | }
133 |
134 | @Override
135 | protected void getDateRangeFromRecordSet(String[] recordSet)
136 | {
137 | // Example:
138 | // Peiro JoanCarles 09/03/2019 00:00 31/05/2019 23:59 Serial Number NG1623501H
139 | // So 3rd field is blank
140 | // 6th says serial number
141 | if (recordSet.length > 1)
142 | {
143 | m_Logger.log(Level.FINE, "DBResultMedtronic Comparing:<" + recordSet[0] + "> and <" + m_ReportRange + ">");
144 | if (recordSet[0].equals(m_ReportRange))
145 | {
146 | m_ReportDateRange = true;
147 | m_StartDate = parseFileDate(recordSet[1]);
148 | m_EndDate = parseFileDate(recordSet[3]);
149 | }
150 | }
151 | }
152 |
153 | @Override
154 | protected String getDateFormat()
155 | {
156 | return m_DateFormat;
157 | }
158 |
159 | @Override
160 | protected String getTimeFormat()
161 | {
162 | return m_TimeFormat;
163 | }
164 |
165 |
166 | private int fieldLocation(String f)
167 | {
168 | int result = super.fieldLocation(f, m_FieldNames);
169 | return result;
170 | }
171 |
172 | @Override
173 | protected int getDateIndex()
174 | {
175 | return m_DateIndex;
176 | }
177 |
178 | @Override
179 | protected int getTimeIndex()
180 | {
181 | return m_TimeIndex;
182 | }
183 |
184 | @Override
185 | protected int getBolusTypeIndex()
186 | {
187 | return m_BolusTypeIndex;
188 | }
189 |
190 | @Override
191 | protected int getBGIndex()
192 | {
193 | return m_BGIndex;
194 | }
195 |
196 | @Override
197 | protected int getTempBasalAmountIndex()
198 | {
199 | return m_TempBasalAmountIndex;
200 | }
201 |
202 | @Override
203 | protected int getTempBasalDurationIndex()
204 | {
205 | return m_TempBasalDurationIndex;
206 | }
207 |
208 | @Override
209 | protected int getCarbAmountIndex()
210 | {
211 | return m_CarbAmountIndex;
212 | }
213 |
214 | @Override
215 | protected int getStandardBolusIndex()
216 | {
217 | return m_StandardBolusIndex;
218 | }
219 |
220 | @Override
221 | protected int getBolusDurationIndex()
222 | {
223 | return m_BolusDurationIndex;
224 | }
225 |
226 | @Override
227 | protected int getPrimeIndex()
228 | {
229 | return m_PrimeIndex;
230 | }
231 |
232 | }
233 |
--------------------------------------------------------------------------------
/src/main/java/analysis/AnalyzerTrendResultEntry.java:
--------------------------------------------------------------------------------
1 | package analysis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.logging.Level;
5 | import java.util.logging.Logger;
6 |
7 | import analysis.AnalyzerResultEntryInterval.DBResultEntryProfile;
8 | import analysis.AnalyzerResultEntryInterval.DBResultEntryProfileChange;
9 | import analysis.AnalyzerResultEntryInterval.DBResultEntryProfileDirection;
10 | import control.MyLogger;
11 | import utils.CommonUtils;
12 |
13 | public class AnalyzerTrendResultEntry
14 | {
15 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
16 |
17 | private static Integer m_Static_ID = 0; // Assign an ID to each result created.
18 | private int m_ID = 0; // Assign an ID to each result created.
19 |
20 | private ArrayList m_ResultEntryIntervals;
21 | private Boolean m_GoesHypo;
22 | private Boolean m_GoesHyper;
23 | private DBResultEntryProfileChange m_DBResultEntryProfileChange;
24 | private DBResultEntryProfile m_StartProfile;
25 | private DBResultEntryProfile m_EndProfile;
26 | private DBResultEntryProfileDirection m_ProfileDirection;
27 |
28 | private int m_StartHour;
29 | private int m_EndHour;
30 | private int m_Offset;
31 |
32 | AnalyzerTrendResultEntry(boolean goesHypo, boolean goesHyper,
33 | DBResultEntryProfile startProfile, DBResultEntryProfile endProfile,
34 | DBResultEntryProfileDirection profileDirection,
35 | int startHour, int endHour, int offset)
36 | {
37 | m_Static_ID++;
38 | m_ID = m_Static_ID;
39 |
40 | m_Logger.log(Level.FINE, "Just built AnalyzerEntriesCGMDay " + m_ID + " Profile Start: " +
41 | startProfile.toString() + " Profile End: " +
42 | endProfile.toString() + " Start Hour: " + startHour + " End Hour: " + endHour);
43 |
44 | m_ResultEntryIntervals = new ArrayList();
45 |
46 | m_GoesHypo = goesHypo;
47 | m_GoesHyper = goesHyper;
48 | m_StartProfile = startProfile;
49 | m_EndProfile = endProfile;
50 | m_StartHour = startHour;
51 | m_EndHour = endHour;
52 | m_ProfileDirection = profileDirection;
53 | m_Offset = offset;
54 | }
55 |
56 | AnalyzerTrendResultEntry(DBResultEntryProfileChange profileChange, int startHour, int endHour, int offset)
57 | {
58 | m_Static_ID++;
59 | m_ID = m_Static_ID;
60 |
61 | m_Logger.log(Level.FINE, "Just built AnalyzerEntriesCGMDay " + m_ID + " Profile: " +
62 | profileChange.toString() + " Start Hour: " + startHour + " End Hour: " + endHour);
63 |
64 | m_ResultEntryIntervals = new ArrayList();
65 |
66 | m_DBResultEntryProfileChange = profileChange;
67 | m_StartHour = startHour;
68 | m_EndHour = endHour;
69 | m_Offset = offset;
70 | }
71 |
72 | public boolean addSingleResultEntry(AnalyzerResultEntryInterval e)
73 | {
74 | boolean result = false;
75 |
76 | boolean profileDirection = e.getM_ProfileDirection() == m_ProfileDirection ? true : false;
77 | /* boolean goesHypo = e.getM_GoesHypo() == m_GoesHypo ? true : false;
78 | boolean goesHyper = e.getM_GoesHyper() == m_GoesHyper ? true : false;
79 | boolean startProfile = e.getM_StartProfile() == m_StartProfile ? true : false;
80 | boolean endProfile = e.getM_EndProfile() == m_EndProfile ? true : false;
81 |
82 |
83 | // We group results with different end profiles together
84 | boolean exactlySameProfile =
85 | (goesHypo == true && goesHyper == true && startProfile == true &&
86 | endProfile == true && profileDirection == true) ? true : false;*/
87 |
88 | boolean sameProfile = (profileDirection == true) ? true : false;
89 |
90 | if ( (sameProfile) && // Same profile
91 | CommonUtils.get24Hour(e.getM_PeriodStart()) >= m_StartHour + m_Offset && // Start time
92 | CommonUtils.get24Hour(e.getM_PeriodEnd()) <= m_EndHour + m_Offset)
93 | {
94 | m_ResultEntryIntervals.add(e);
95 | e.setM_AnalyzerTrendResultEntry(this);
96 | result = true;
97 | }
98 |
99 | return result;
100 | }
101 |
102 |
103 |
104 | public synchronized static void resetStaticID()
105 | {
106 | m_Static_ID = 0;
107 | }
108 |
109 | /**
110 | * @return the m_ID
111 | */
112 | public synchronized int getM_ID()
113 | {
114 | return m_ID;
115 | }
116 |
117 | /**
118 | * @return the m_ResultEntryIntervals
119 | */
120 | public synchronized ArrayList getM_ResultEntryIntervals() {
121 | return m_ResultEntryIntervals;
122 | }
123 |
124 | /**
125 | * @return the m_DBResultEntryProfileChange
126 | */
127 | public synchronized DBResultEntryProfileChange getM_DBResultEntryProfileChange() {
128 | return m_DBResultEntryProfileChange;
129 | }
130 |
131 | /**
132 | * @return the m_StartHour
133 | */
134 | public synchronized int getM_StartHour() {
135 | return m_StartHour;
136 | }
137 |
138 | /**
139 | * @return the m_EndHour
140 | */
141 | public synchronized int getM_EndHour() {
142 | return m_EndHour;
143 | }
144 |
145 | /**
146 | * @return the m_Offset
147 | */
148 | public synchronized int getM_Offset() {
149 | return m_Offset;
150 | }
151 |
152 | /**
153 | * @return the m_GoesHypo
154 | */
155 | public synchronized Boolean getM_GoesHypo() {
156 | return m_GoesHypo;
157 | }
158 |
159 | /**
160 | * @return the m_GoesHyper
161 | */
162 | public synchronized Boolean getM_GoesHyper() {
163 | return m_GoesHyper;
164 | }
165 |
166 | /**
167 | * @return the m_StartProfile
168 | */
169 | public synchronized DBResultEntryProfile getM_StartProfile() {
170 | return m_StartProfile;
171 | }
172 |
173 | /**
174 | * @return the m_EndProfile
175 | */
176 | public synchronized DBResultEntryProfile getM_EndProfile() {
177 | return m_EndProfile;
178 | }
179 |
180 | /**
181 | * @return the m_ProfileDirection
182 | */
183 | public synchronized DBResultEntryProfileDirection getM_ProfileDirection() {
184 | return m_ProfileDirection;
185 | }
186 |
187 | /**
188 | * @return the m_ProfileDirection
189 | */
190 | public synchronized String getM_ProfileDirectionStr(boolean mmol)
191 | {
192 | String result = AnalyzerResultEntryInterval.getProfileDirectionStr(mmol, m_ProfileDirection);
193 | return result;
194 | }
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/src/main/java/win/WinWhy.java:
--------------------------------------------------------------------------------
1 | package win;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.FlowLayout;
5 | //import java.awt.Graphics;
6 | import java.awt.Image;
7 |
8 | import javax.imageio.ImageIO;
9 | import javax.swing.ImageIcon;
10 | import javax.swing.JButton;
11 | import javax.swing.JDialog;
12 | import javax.swing.JLabel;
13 | import javax.swing.JPanel;
14 | import javax.swing.JScrollPane;
15 | import javax.swing.border.EmptyBorder;
16 |
17 | import control.MainNightScoutLoader;
18 | import control.MyLogger;
19 |
20 | import javax.swing.JTextArea;
21 | import java.awt.event.ActionListener;
22 | import java.awt.image.BufferedImage;
23 | import java.io.IOException;
24 | import java.net.URL;
25 | import java.util.logging.Level;
26 | import java.util.logging.Logger;
27 | import java.awt.event.ActionEvent;
28 |
29 | public class WinWhy extends JDialog
30 | {
31 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
32 |
33 | // THIS IS A DELIBERATE CHANGE
34 |
35 | /**
36 | *
37 | */
38 | private static final long serialVersionUID = -51832866421758739L;
39 |
40 | private final JPanel contentPanel = new JPanel();
41 |
42 | // private final ImagePanel imagePanel = new ImagePanel();
43 |
44 | private String m_WhyText;
45 |
46 | /**
47 | * Create the dialog.
48 | */
49 | public WinWhy(String title)
50 | {
51 | URL url = MainNightScoutLoader.class.getResource("/Nightscout.jpg");
52 | ImageIcon img = new ImageIcon(url);
53 | setIconImage(img.getImage());
54 |
55 | super.setTitle(title);
56 |
57 | m_WhyText = new String();
58 |
59 | m_WhyText += "NightScoutLoader\r\n\r\nThe reason behind this application:\r\n\r\n";
60 | m_WhyText += " Dawn was 19 months 21st March 2003 when blue-light rushed from Doctor's surgery to hospital.\r\n";
61 | m_WhyText += " Since then (as every parent with a T1 child knows) life has never been the same.\r\n";
62 | m_WhyText += " She was in hospital for 10 straight days, advanced stage ketoacidosis and in a really bad way.\r\n\r\n";
63 | m_WhyText += " In hindsight, the virus we thought she had was more serious than we realised.\r\n";
64 | m_WhyText += " \r\n";
65 | m_WhyText += " She's pictured left on her 2nd Birthday August 2003.\r\n";
66 | m_WhyText += " \r\n";
67 | m_WhyText += " Since then Debbie & I did what we could to ensure her health was fine.\r\n";
68 | m_WhyText += " In the early days, Dawn was on combination insulin injections - twice a day.\r\n";
69 | m_WhyText += " We soon exhausted all available combinations and within a year were moving to 3 then 4 injections.\r\n";
70 | m_WhyText += " Realising the importance of data, I immediately got on top of meter downloads and \r\n";
71 | m_WhyText += " with my technical skills, I established the process of annotating results with what she ate\r\n";
72 | m_WhyText += " \r\n";
73 | m_WhyText += " In 2008, Dawn went onto a Medtronic pump for the first time. \r\n";
74 | m_WhyText += " Leading up to that date, we needed to firmly establish carb counting. \r\n";
75 | m_WhyText += " Looking around for a mobile device that could help & finding none, I wrote one on Windows Mobile \r\n";
76 | m_WhyText += " that we used for several years until gaining expertise in carb counting. \r\n";
77 | m_WhyText += " I developed a PC tool that would link historical food information to the Medtronic Care Link site too. \r\n";
78 | m_WhyText += " \r\n";
79 | m_WhyText += " In 2012, Dawn moved to Roche. \r\n";
80 | m_WhyText += " Later that year, I reverse engineered the Roche SQL Server Database and developed some spreadsheets \r\n";
81 | m_WhyText += " that could query directly pulling data down into my own tables & graphs.\r\n";
82 | m_WhyText += " \r\n";
83 | m_WhyText += " Once I discovered NightScout in 2015, I realised this early Roche work could be of use\r\n";
84 | m_WhyText += " and so began the project Nightscout Loader in December 2015.\r\n";
85 | m_WhyText += " \r\n";
86 | m_WhyText += " Since then, Dawn moved to OmniPod and with only real access to data being through Diasend,\r\n";
87 | m_WhyText += " I strengthened support for this file type.\r\n";
88 | m_WhyText += " Most recently, I've added the audit and analytical capabililties. I think they're useful. Hope you do too.\r\n";
89 |
90 | setBounds(50, 50, 1250, 650);
91 | getContentPane().setLayout(new BorderLayout());
92 | // getContentPane().setLayout(new FlowLayout());
93 |
94 | contentPanel.setLayout(new FlowLayout());
95 | contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
96 |
97 |
98 | // This code scales the picture but it the app doesn't launch
99 | // when exported
100 |
101 | // Using http://www.mkyong.com/java/how-to-read-an-image-from-file-or-url/
102 | BufferedImage myPicture = null;
103 | try {
104 | URL url2 = MainNightScoutLoader.class.getResource("/Dawn.JPG");
105 | myPicture = ImageIO.read(url2);
106 | } catch (IOException e) {
107 | e.printStackTrace();
108 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "deeperAnalyseResults: Just caught an exception " + e.getMessage());
109 | }
110 |
111 | Image dimg = myPicture.getScaledInstance(600, 400, Image.SCALE_SMOOTH);
112 | JLabel picLabel = new JLabel(new ImageIcon(dimg));
113 |
114 | add(picLabel);
115 | getContentPane().add(picLabel, BorderLayout.WEST);
116 |
117 |
118 |
119 | // getContentPane().add(imagePanel, BorderLayout.NORTH);
120 |
121 | getContentPane().add(contentPanel, BorderLayout.EAST);
122 | {
123 | JTextArea txtrNightscoutloader = new JTextArea();
124 | txtrNightscoutloader.setText(m_WhyText);
125 | contentPanel.add(txtrNightscoutloader);
126 |
127 | JScrollPane scrollPane = new JScrollPane(txtrNightscoutloader);
128 | getContentPane().add(scrollPane, BorderLayout.CENTER);
129 | }
130 |
131 |
132 | {
133 | JPanel buttonPane = new JPanel();
134 | buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
135 | getContentPane().add(buttonPane, BorderLayout.SOUTH);
136 | {
137 | JButton okButton = new JButton("OK");
138 | okButton.addActionListener(new ActionListener() {
139 | public void actionPerformed(ActionEvent arg0) {
140 | setVisible(false);
141 | }
142 | });
143 | okButton.setActionCommand("OK");
144 | buttonPane.add(okButton);
145 | getRootPane().setDefaultButton(okButton);
146 | }
147 | {
148 | JButton cancelButton = new JButton("Cancel");
149 | cancelButton.addActionListener(new ActionListener() {
150 | public void actionPerformed(ActionEvent arg0) {
151 | setVisible(false);
152 | }
153 | });
154 | cancelButton.setActionCommand("Cancel");
155 | buttonPane.add(cancelButton);
156 | }
157 | }
158 | }
159 |
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/loader/DataLoadCellNovo.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.ArrayList;
8 | import java.util.Collections;
9 | import java.util.logging.Level;
10 | import java.util.logging.Logger;
11 |
12 | import control.MyLogger;
13 | import entity.DBResult;
14 | import entity.DBResultCellNovoRaw;
15 | import entity.ResultFromDBComparator;
16 |
17 | public class DataLoadCellNovo extends DataLoadCSVFile
18 | {
19 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
20 | private static final String m_CellNovoSplitBy = ";";
21 |
22 |
23 | @Override
24 | protected DBResult makeDBResult(String[] res)
25 | {
26 | return null;
27 | }
28 |
29 | @Override
30 | protected ArrayList makeDBResultList(String[] res)
31 | {
32 | ArrayList result = null;
33 | DBResultCellNovoRaw rawRes = new DBResultCellNovoRaw(res);
34 | if (rawRes.isValid())
35 | {
36 | result = rawRes.createDBResults();
37 | }
38 | return result;
39 | }
40 |
41 | @Override
42 | protected void orderRawResults()
43 | {
44 | Collections.sort(rawResultsFromDB, new ResultFromDBComparator(false));
45 | }
46 |
47 | @Override
48 | protected String loadStringName()
49 | {
50 | // TODO Auto-generated method stub
51 | return null;
52 | }
53 |
54 | @Override
55 | protected String getSplitBy()
56 | {
57 | return m_CellNovoSplitBy;
58 | }
59 |
60 | public static boolean isCellNovo(String fileName)
61 | {
62 | boolean result = false;
63 | BufferedReader br = null;
64 | String line = "";
65 | String cvsSplitBy = m_CellNovoSplitBy;
66 |
67 | // Expected Format
68 |
69 | boolean ln9Date = false;
70 | boolean ln9Hour0 = false;
71 | boolean ln9Hour1 = false;
72 | boolean ln9Hour2 = false;
73 | boolean ln9Hour3 = false;
74 | boolean ln9Hour4 = false;
75 | boolean ln9Hour5 = false;
76 | boolean ln9Hour6 = false;
77 | boolean ln9Hour7 = false;
78 | boolean ln9Hour8 = false;
79 | boolean ln9Hour9 = false;
80 | boolean ln9Hour10 = false;
81 | boolean ln9Hour11 = false;
82 | boolean ln9Hour12 = false;
83 | boolean ln9Hour13 = false;
84 | boolean ln9Hour14 = false;
85 | boolean ln9Hour15 = false;
86 | boolean ln9Hour16 = false;
87 | boolean ln9Hour17 = false;
88 | boolean ln9Hour18 = false;
89 | boolean ln9Hour19 = false;
90 | boolean ln9Hour20 = false;
91 | boolean ln9Hour21 = false;
92 | boolean ln9Hour22 = false;
93 | boolean ln9Hour23 = false;
94 | boolean ln9Total = false;
95 |
96 |
97 | int ln = 0;
98 | int maxLines = 10;
99 | int lineCheck = 9; // Check line 9 as that's where the data really starts
100 |
101 | try
102 | {
103 | br = new BufferedReader(new FileReader(fileName));
104 | while ((ln <= maxLines) && (line = br.readLine()) != null)
105 | {
106 | ln++;
107 | // use comma as separator
108 | String[] rs = line.split(cvsSplitBy);
109 |
110 | if (ln == lineCheck)
111 | {
112 | int i = 0;
113 | ln9Date = (rs.length > i && rs[i++].equals("Date")) ? true : false;
114 | ln9Hour0 = (rs.length > i && rs[i++].equals("00")) ? true : false;
115 | ln9Hour1 = (rs.length > i && rs[i++].equals("01")) ? true : false;
116 | ln9Hour2 = (rs.length > i && rs[i++].equals("02")) ? true : false;
117 | ln9Hour3 = (rs.length > i && rs[i++].equals("03")) ? true : false;
118 | ln9Hour4 = (rs.length > i && rs[i++].equals("04")) ? true : false;
119 | ln9Hour5 = (rs.length > i && rs[i++].equals("05")) ? true : false;
120 | ln9Hour6 = (rs.length > i && rs[i++].equals("06")) ? true : false;
121 | ln9Hour7 = (rs.length > i && rs[i++].equals("07")) ? true : false;
122 | ln9Hour8 = (rs.length > i && rs[i++].equals("08")) ? true : false;
123 | ln9Hour9 = (rs.length > i && rs[i++].equals("09")) ? true : false;
124 | ln9Hour10 = (rs.length > i && rs[i++].equals("10")) ? true : false;
125 | ln9Hour11 = (rs.length > i && rs[i++].equals("11")) ? true : false;
126 | ln9Hour12 = (rs.length > i && rs[i++].equals("12")) ? true : false;
127 | ln9Hour13 = (rs.length > i && rs[i++].equals("13")) ? true : false;
128 | ln9Hour14 = (rs.length > i && rs[i++].equals("14")) ? true : false;
129 | ln9Hour15 = (rs.length > i && rs[i++].equals("15")) ? true : false;
130 | ln9Hour16 = (rs.length > i && rs[i++].equals("16")) ? true : false;
131 | ln9Hour17 = (rs.length > i && rs[i++].equals("17")) ? true : false;
132 | ln9Hour18 = (rs.length > i && rs[i++].equals("18")) ? true : false;
133 | ln9Hour19 = (rs.length > i && rs[i++].equals("19")) ? true : false;
134 | ln9Hour20 = (rs.length > i && rs[i++].equals("20")) ? true : false;
135 | ln9Hour21 = (rs.length > i && rs[i++].equals("21")) ? true : false;
136 | ln9Hour22 = (rs.length > i && rs[i++].equals("22")) ? true : false;
137 | ln9Hour23 = (rs.length > i && rs[i++].equals("23")) ? true : false;
138 | ln9Total = (rs.length > i && rs[i++].equals("Total"))? true : false;
139 |
140 | }
141 |
142 | }
143 |
144 | result = (ln9Date == true &&
145 | ln9Hour0 == true && ln9Hour1 == true && ln9Hour2 == true && ln9Hour3 == true &&
146 | ln9Hour4 == true && ln9Hour5 == true && ln9Hour6 == true && ln9Hour7 == true &&
147 | ln9Hour8 == true && ln9Hour9 == true && ln9Hour10 == true && ln9Hour11 == true &&
148 | ln9Hour12 == true && ln9Hour13 == true && ln9Hour14 == true && ln9Hour15 == true &&
149 | ln9Hour16 == true && ln9Hour17 == true && ln9Hour18 == true && ln9Hour19 == true &&
150 | ln9Hour20 == true && ln9Hour21 == true && ln9Hour22 == true && ln9Hour23 == true &&
151 | ln9Total == true) ? true : false;
152 |
153 | }
154 | catch (FileNotFoundException e)
155 | {
156 | m_Logger.log(Level.SEVERE, "" + "isCellNovo: FileNotFoundException. File " + fileName + " Error " + e.getMessage());
157 |
158 | e.printStackTrace();
159 | }
160 | catch (IOException e)
161 | {
162 | m_Logger.log(Level.SEVERE, "" + "isCellNovo: IOException. File " + fileName + " Error " + e.getMessage());
163 | e.printStackTrace();
164 | }
165 | finally
166 | {
167 | if (br != null)
168 | {
169 | try
170 | {
171 | br.close();
172 | }
173 | catch (IOException e)
174 | {
175 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: IOException closing file. File " + fileName + " Error " + e.getMessage());
176 | e.printStackTrace();
177 | }
178 | }
179 | }
180 |
181 | return result;
182 | }
183 |
184 | }
185 |
--------------------------------------------------------------------------------
/src/main/java/entity/DBResultMedtronicNew.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.util.Date;
4 | import utils.CommonUtils;
5 |
6 | public class DBResultMedtronicNew extends DBResultMedtronic
7 | {
8 | private static final String m_DateFormat = "yyyy/MM/dd";
9 | private static final String m_TimeFormat = "yyyy/MM/dd HH:mm:ss";
10 |
11 | static protected String m_ReportRange = "Serial Number";
12 |
13 | /* private boolean m_Valid;
14 | private boolean m_ReportDateRange;
15 | private Date m_StartDate;
16 | private Date m_EndDate;
17 | */
18 |
19 | static private String[] m_FieldNames =
20 | {
21 | "Index",
22 | "Date",
23 | "Time",
24 | "New Device Time",
25 | "BG Reading (mmol/L)",
26 | "Linked BG Meter ID",
27 | "Basal Rate (U/h)",
28 | "Temp Basal Amount",
29 | "Temp Basal Type",
30 | "Temp Basal Duration (h:mm:ss)",
31 | "Bolus Type",
32 | "Bolus Volume Selected (U)",
33 | "Bolus Volume Delivered (U)",
34 | "Bolus Duration (h:mm:ss)",
35 | "Prime Type",
36 | "Prime Volume Delivered (U)",
37 | "Alarm",
38 | "Suspend",
39 | "Rewind",
40 | "BWZ Estimate (U)",
41 | "BWZ Target High BG (mmol/L)",
42 | "BWZ Target Low BG (mmol/L)",
43 | "BWZ Carb Ratio (g/U)",
44 | "BWZ Insulin Sensitivity (mg/dL/U)",
45 | "BWZ Carb Input (grams)",
46 | "BWZ BG Input (mmol/L)",
47 | "BWZ Correction Estimate (U)",
48 | "BWZ Food Estimate (U)",
49 | "BWZ Active Insulin (U)",
50 | "Sensor Calibration BG (mmol/L)",
51 | "Sensor Glucose (mmol/L)",
52 | "ISIG Value",
53 | "Event Marker",
54 | "Bolus Number",
55 | "Bolus Cancellation Reason",
56 | "BWZ Unabsorbed Insulin Total (U)",
57 | "Final Bolus Estimate",
58 | "Scroll Step Size",
59 | "Insulin Action Curve Time",
60 | "Sensor Calibration Rejected Reason",
61 | "Preset Bolus",
62 | "Bolus Source",
63 | "Network Device Associated Reason",
64 | "Network Device Disassociated Reason",
65 | "Network Device Disconnected Reason",
66 | "Sensor Exception",
67 | "Preset Temp Basal Name",
68 | };
69 |
70 | static private boolean m_indexesInitialized = false;
71 | static private int m_DateIndex = 0;
72 | static private int m_TimeIndex = 0;
73 | static private int m_BolusTypeIndex = 0;
74 | static private int m_BGIndex = 0;
75 | static private int m_TempBasalAmountIndex = 0;
76 | static private int m_TempBasalDurationIndex = 0;
77 | static private int m_CarbAmountIndex = 0;
78 | static private int m_StandardBolusIndex = 0;
79 | static private int m_BolusDurationIndex = 0;
80 | static private int m_PrimeIndex = 0;
81 |
82 | @Override
83 | public boolean isValid()
84 | {
85 | return m_Valid;
86 | }
87 |
88 | @Override
89 | public boolean isReportRange()
90 | {
91 | return m_ReportDateRange;
92 | }
93 |
94 | public Date getStartReportRange()
95 | {
96 | return m_StartDate;
97 | }
98 | public Date getEndReportRange()
99 | {
100 | return m_EndDate;
101 | }
102 |
103 | public DBResultMedtronicNew(String[] recordSet)
104 | {
105 | super(recordSet);
106 | }
107 |
108 | @Override
109 | protected void initialize()
110 | {
111 | m_StartDate = new Date(0);
112 | m_EndDate = new Date(0);
113 |
114 | m_Valid = true;
115 | m_ReportDateRange = false;
116 |
117 | m_RecordSet = new String[m_FieldNames.length];
118 |
119 | // Set values in underdlying ResultFromDB from record set
120 | if (m_indexesInitialized == false)
121 | {
122 | m_DateIndex = fieldLocation("Date");
123 | m_TimeIndex = fieldLocation("Time");
124 | m_BolusTypeIndex = fieldLocation("Bolus Type");
125 | m_BGIndex = fieldLocation("BG Reading (mmol/L)");
126 | m_TempBasalAmountIndex = fieldLocation("Temp Basal Amount");
127 | m_TempBasalDurationIndex = fieldLocation("Temp Basal Duration (h:mm:ss)");
128 | m_CarbAmountIndex = fieldLocation("BWZ Carb Input (grams)");
129 | m_StandardBolusIndex = fieldLocation("Bolus Volume Delivered (U)");
130 | m_BolusDurationIndex = fieldLocation("Bolus Duration (h:mm:ss)");
131 | // m_Time = fieldLocation("Timestamp");
132 | m_PrimeIndex = fieldLocation("Prime Type");
133 |
134 | m_indexesInitialized = true;
135 | }
136 | }
137 |
138 | @Override
139 | protected void getDateRangeFromRecordSet(String[] recordSet)
140 | {
141 | // Example:
142 | // Peiro JoanCarles 09/03/2019 00:00 31/05/2019 23:59 Serial Number NG1623501H
143 | // So 3rd field is blank
144 | // 6th says serial number
145 | if (recordSet.length > 6)
146 | {
147 | if (CommonUtils.stripDoubleQuotes(recordSet[2]).isEmpty() &&
148 | CommonUtils.stripDoubleQuotes(recordSet[5]).equals(m_ReportRange))
149 | {
150 | m_ReportDateRange = true;
151 |
152 | // All fields in this record have double quotes around them
153 | String field3 = getDateFromLine2DateField(CommonUtils.stripDoubleQuotes(recordSet[3]));
154 | String field4 = getDateFromLine2DateField(CommonUtils.stripDoubleQuotes(recordSet[4]));
155 |
156 | m_StartDate = parseFileDate(field3);
157 | m_EndDate = parseFileDate(field4);
158 | }
159 | }
160 |
161 | }
162 |
163 | @Override
164 | protected String getDateFormat()
165 | {
166 | return m_DateFormat;
167 | }
168 |
169 | @Override
170 | protected String getTimeFormat()
171 | {
172 | return m_TimeFormat;
173 | }
174 |
175 |
176 | private String getDateFromLine2DateField(String val)
177 | {
178 | String result = "";
179 |
180 | // Split by space to lose time... not interested
181 | String[] tokens = val.split(" ");
182 | if (tokens.length > 0)
183 | {
184 | result = tokens[0];
185 |
186 | // Add a leading zero for those lazy dates
187 | if (result.length() == 7)
188 | {
189 | result = "0" + result;
190 | }
191 | }
192 |
193 | return result;
194 | }
195 |
196 | private int fieldLocation(String f)
197 | {
198 | int result = super.fieldLocation(f, m_FieldNames);
199 | return result;
200 | }
201 |
202 | @Override
203 | protected int getDateIndex()
204 | {
205 | return m_DateIndex;
206 | }
207 |
208 | @Override
209 | protected int getTimeIndex()
210 | {
211 | return m_TimeIndex;
212 | }
213 |
214 | @Override
215 | protected int getBolusTypeIndex()
216 | {
217 | return m_BolusTypeIndex;
218 | }
219 |
220 | @Override
221 | protected int getBGIndex()
222 | {
223 | return m_BGIndex;
224 | }
225 |
226 | @Override
227 | protected int getTempBasalAmountIndex()
228 | {
229 | return m_TempBasalAmountIndex;
230 | }
231 |
232 | @Override
233 | protected int getTempBasalDurationIndex()
234 | {
235 | return m_TempBasalDurationIndex;
236 | }
237 |
238 | @Override
239 | protected int getCarbAmountIndex()
240 | {
241 | return m_CarbAmountIndex;
242 | }
243 |
244 | @Override
245 | protected int getStandardBolusIndex()
246 | {
247 | return m_StandardBolusIndex;
248 | }
249 |
250 | @Override
251 | protected int getBolusDurationIndex()
252 | {
253 | return m_BolusDurationIndex;
254 | }
255 |
256 | @Override
257 | protected int getPrimeIndex()
258 | {
259 | return m_PrimeIndex;
260 | }
261 |
262 | }
263 |
--------------------------------------------------------------------------------
/src/test/java/loader/BaseTestTreatment.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.net.URISyntaxException;
6 | import java.net.URL;
7 | import java.net.UnknownHostException;
8 | import java.sql.SQLException;
9 | import java.text.ParseException;
10 | import java.text.SimpleDateFormat;
11 | import java.util.ArrayList;
12 | import java.util.Date;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 | import java.util.Set;
16 |
17 | import org.junit.jupiter.api.Assertions;
18 | import org.junit.runner.RunWith;
19 | import org.mockito.junit.MockitoJUnitRunner;
20 | import control.MyLogger;
21 | import control.PrefsNightScoutLoader;
22 | import entity.DBResult;
23 | import entity.DBResultEntry;
24 |
25 | @RunWith(MockitoJUnitRunner.class)
26 | public abstract class BaseTestTreatment {
27 |
28 | protected static Double DOUBLE_THRESHOLD = 0.001;
29 |
30 | public BaseTestTreatment() {
31 | try {
32 | MyLogger.setup(true);
33 | } catch (IOException e) {
34 | // TODO Auto-generated catch block
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | protected abstract Object[][] getExpectedTestResults();
40 | protected abstract String getResourceFileName();
41 | protected abstract DataLoadFile getDataLoadFile();
42 | protected abstract SimpleDateFormat getSimpleDateFormat();
43 | protected abstract String getDateFormat();
44 |
45 | public ArrayList getDBResultArrayList()
46 | {
47 | return getDataLoadFile().getResultTreatments();
48 | }
49 |
50 | public ArrayList getDBResultEntryArrayList()
51 | {
52 | return getDataLoadFile().getRawEntryResultsFromDB();
53 | }
54 |
55 | public void performTestLoad()
56 | {
57 | doDataLoad();
58 | DataLoadFile dataLoadDiasend = getDataLoadFile();
59 | Assertions.assertTrue(dataLoadDiasend != null);
60 | try {
61 | assertionTests(dataLoadDiasend);
62 | } catch (ParseException e) {
63 | // TODO Auto-generated catch block
64 | e.printStackTrace();
65 | }
66 | }
67 |
68 | public void doDataLoad()
69 | {
70 | // This disables any MongoDB connection attempts
71 | PrefsNightScoutLoader.getInstance().setM_NightscoutMongoServer("");
72 |
73 | // Disable inferring any temp basals
74 | PrefsNightScoutLoader.getInstance().setM_InferTempBasals(false);
75 |
76 |
77 | URL url = this.getClass().getClassLoader().getResource(getResourceFileName());
78 | Assertions.assertTrue(url != null);
79 | DataLoadFile dataLoadDiasend = getDataLoadFile();
80 | try {
81 | dataLoadDiasend.initialize(new File(url.toURI()).getAbsolutePath());
82 | dataLoadDiasend.loadDBResults();
83 | } catch (URISyntaxException e) {
84 | Assertions.assertTrue(false, e.toString());
85 | } catch (UnknownHostException e) {
86 | Assertions.assertTrue(false, e.toString());
87 | } catch (ClassNotFoundException e) {
88 | Assertions.assertTrue(false, e.toString());
89 | } catch (SQLException e) {
90 | Assertions.assertTrue(false, e.toString());
91 | } catch (IOException e) {
92 | Assertions.assertTrue(false, e.toString());
93 | }
94 |
95 | }
96 |
97 | public int countDataLoadEntries(Boolean withBG)
98 | {
99 | int result = 0;
100 |
101 | // Iterate over the HashMap since exact duplicate results at same time
102 | // are filtered out.
103 |
104 | DataLoadFile dataLoadDiasend = getDataLoadFile();
105 | HashMap map = dataLoadDiasend.getResultTreatmentHashMap();
106 | Set> entrySet = map.entrySet();
107 |
108 | for(Map.Entry entry : entrySet)
109 | {
110 | DBResult res = entry.getValue();
111 | result += res.getM_CP_Glucose() == null
112 | ? withBG == false ? 1 : 0
113 | : withBG == true ? 1 : 0;
114 | }
115 |
116 | return result;
117 | }
118 |
119 | @SuppressWarnings("unused")
120 | public int countExpectedResults()
121 | {
122 | int result = 0;
123 |
124 | for (int c = 0; c < getExpectedTestResults().length; c++)
125 | {
126 | Object[] treatmentObject = getExpectedTestResults()[c];
127 | int i = 0;
128 |
129 | String dateString = (String) treatmentObject[i++];
130 | Double bgDouble = (Double)treatmentObject[i++];
131 | Double insDouble = (Double)treatmentObject[i++];
132 | Double carbDouble = (Double)treatmentObject[i++];
133 | String dupeString = (String)treatmentObject[i++];
134 |
135 | result += dupeString.equals("NO") ? 1 : 0;
136 | }
137 |
138 | return result;
139 | }
140 |
141 | private void assertionTests(DataLoadFile dataLoadDiasend) throws ParseException
142 | {
143 | Assertions.assertTrue(dataLoadDiasend != null);
144 |
145 | for (int c = 0; c < getExpectedTestResults().length; c++)
146 | {
147 | Object[] treatmentObject = getExpectedTestResults()[c];
148 | int i = 0;
149 |
150 |
151 | // Integer indexInteger = (Integer) treatmentObject[i++];
152 | String dateString = (String) treatmentObject[i++];
153 | Double bgDouble = (Double)treatmentObject[i++];
154 | Double insDouble = (Double)treatmentObject[i++];
155 | Double carbDouble = (Double)treatmentObject[i++];
156 | String dupeString = (String)treatmentObject[i++];
157 |
158 |
159 | Date date = getSimpleDateFormat().parse(dateString);
160 | DBResult result = dataLoadDiasend.getResultTreatmentHashMap().get(date.getTime());
161 | // DBResult result = dataLoadDiasend.getResultTreatmentHashMap().get(ldtEpoch * 1000);
162 | if (result != null)
163 | {
164 | String messgString = " for Entry " + c + " Date " + dateString + " Treatment Id: " + result.getId();
165 | Assertions.assertTrue(result != null);
166 |
167 | if (dupeString.equals("NO"))
168 | {
169 | if (bgDouble.equals(0.0)) Assertions.assertTrue(result.getM_CP_Glucose() == null, "BG Differs (not null)" + messgString);
170 | else assertEquals(result.getM_CP_Glucose(), bgDouble, "BG Differs" + messgString);
171 | }
172 |
173 | if (insDouble.equals(0.0)) Assertions.assertTrue(result.getM_CP_Insulin() == null, "Insulin Differs (not null)" + messgString);
174 | else assertEquals(result.getM_CP_Insulin(), insDouble, "Insulin Differs" + messgString);
175 |
176 | if (carbDouble.equals(0.0)) Assertions.assertTrue(result.getM_CP_Carbs() == null, "Carbs Differs (not null)" + messgString);
177 | else assertEquals(result.getM_CP_Carbs(), carbDouble, "Carbs Differs" + messgString);
178 |
179 | }
180 |
181 | else {
182 | Boolean mergedBoolean = dupeString.equals("YES");
183 |
184 | // System.out.println(
185 | // (mergedBoolean ? "As expected, " : "As NOT expected, ")
186 | // + "unable to find "
187 | // + " Date: " + dateString
188 | // + " BG: " + bgDouble
189 | // + " Ins: " + insDouble
190 | // + " Carbs: " + carbDouble
191 | // + " Dupe: " + dupeString);
192 |
193 | // Only allow dupes to be not found
194 | Assertions.assertTrue(mergedBoolean);
195 | }
196 | }
197 |
198 | }
199 |
200 | private void assertEquals(Double dbl1, Double dbl2, String messageString)
201 | {
202 | Assertions.assertTrue(Math.abs(dbl1 - dbl2) < DOUBLE_THRESHOLD, messageString);
203 | }
204 |
205 | }
206 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadAnalyzer.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.util.ArrayList;
4 | import java.util.logging.Level;
5 | import java.util.logging.Logger;
6 |
7 | import analysis.Analyzer;
8 | import entity.DBResult;
9 | import entity.DBResultEntry;
10 | import win.WinTextWin;
11 |
12 |
13 | public class ThreadAnalyzer implements Runnable
14 | {
15 | private static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
16 |
17 | // Separate thread for Analyzer to run
18 | private Thread m_AnalyzerThread;
19 |
20 | private String m_ExcelFilename = new String("");
21 | private WinTextWin m_AutotunerWin = null;
22 | private ArrayList m_DBResultList = null;
23 |
24 | // Analyzer used by thread
25 | private Analyzer m_Analyzer;
26 |
27 | private Boolean m_AnalyzerRunning;
28 | // static Object m_Lock = new Object();
29 | private Object m_Lock;
30 |
31 | // Thread Synchronization
32 | public void waitUntilFree()
33 | {
34 | synchronized(m_Lock)
35 | {
36 | while (m_AnalyzerRunning)
37 | {
38 | try
39 | {
40 | m_Logger.log( Level.FINE, "ThreadAnalyzer Wait - Running & about to try lock: " + this );
41 | m_Lock.wait();
42 | m_Logger.log( Level.FINE, "ThreadAnalyzer Wait - Running & notified : " + this );
43 | }
44 | catch (InterruptedException e)
45 | {
46 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "ThreadAnalyzer Wait - EXCEPTION CAUGHT.", e);
47 | }
48 | }
49 | m_Logger.log( Level.FINE, "ThreadAnalyzer Wait - No longer running: " + this);
50 | }
51 | }
52 | // Handler to notify when analyzer completes
53 | AnalyzerCompleteHander m_CompleteHandler;
54 |
55 | // Thread Handler for resynchronization
56 | public static abstract class AnalyzerCompleteHander
57 | {
58 | private Object m_Object;
59 | public AnalyzerCompleteHander(Object obj)
60 | {
61 | m_Object = obj;
62 | }
63 | public abstract void analyzeResultsComplete(Object obj);
64 | public abstract void exceptionRaised(String message);
65 |
66 | public Object getM_Object()
67 | {
68 | return m_Object;
69 | }
70 | }
71 |
72 | public ThreadAnalyzer(Analyzer analyzer)
73 | {
74 | m_AnalyzerRunning = true; // Initialise the thread in running state
75 | m_AnalyzerThread = new Thread(this);
76 | m_Analyzer = analyzer;
77 | m_CompleteHandler = null;
78 |
79 | // Thread synchronization
80 | m_Lock = new Object();
81 | }
82 |
83 | public ThreadAnalyzer(ArrayList results, ArrayList resultEntries)
84 | {
85 | m_AnalyzerRunning = true; // Initialise the thread in running state
86 | m_AnalyzerThread = new Thread(this);
87 | m_Analyzer = new Analyzer(results, resultEntries);
88 | m_CompleteHandler = null;
89 |
90 | // Thread synchronization
91 | m_Lock = new Object();
92 | }
93 |
94 | public ThreadAnalyzer(ArrayList results, ArrayList resultEntries, boolean summaryOnly)
95 | {
96 | m_AnalyzerRunning = true; // Initialise the thread in running state
97 | m_AnalyzerThread = new Thread(this);
98 | m_Analyzer = new Analyzer(results, resultEntries, summaryOnly);
99 | m_CompleteHandler = null;
100 |
101 | // Thread synchronization
102 | m_Lock = new Object();
103 | }
104 |
105 | public ThreadAnalyzer(ArrayList results, ArrayList resultEntries, Analyzer.AnalyzerMode mode)
106 | {
107 | m_AnalyzerRunning = true; // Initialise the thread in running state
108 | m_AnalyzerThread = new Thread(this);
109 | m_Analyzer = new Analyzer(results, resultEntries, mode);
110 | m_CompleteHandler = null;
111 |
112 | // Thread synchronization
113 | m_Lock = new Object();
114 | }
115 |
116 | public void analyzeResults(AnalyzerCompleteHander completeHandler)
117 | {
118 | m_CompleteHandler = completeHandler;
119 | m_AnalyzerThread.start();
120 | }
121 |
122 | public void run()
123 | {
124 | m_AnalyzerRunning = true;
125 | synchronized(m_Lock)
126 | {
127 | // Launch the analyze method
128 |
129 | // Analyzer.AnalyzerResult analyzerResult = m_Analyzer.analyzeResults(m_DBResultList, m_ExcelFilename);
130 | Analyzer.AnalyzerResult analyzerResult = m_Analyzer.analyzeResults(m_DBResultList, m_ExcelFilename, m_AutotunerWin);
131 | m_Logger.log(Level.FINE, "analyzeResults(m_DBResultList, m_ExcelFilename) returned: " + analyzerResult);
132 |
133 | if (analyzerResult == Analyzer.AnalyzerResult.analysisComplete)
134 | {
135 | m_CompleteHandler.analyzeResultsComplete(m_CompleteHandler.getM_Object());
136 | }
137 | else if (analyzerResult == Analyzer.AnalyzerResult.datesAreReversed)
138 | {
139 | m_Logger.log(Level.FINE, "Raising exception now");
140 | m_CompleteHandler.exceptionRaised("Analysis did not run since start and end dates are reversed. Please check and try again.");
141 | }
142 | else if (analyzerResult == Analyzer.AnalyzerResult.noDataToAnalyze)
143 | {
144 | m_Logger.log(Level.FINE, "Raising exception now");
145 | m_CompleteHandler.exceptionRaised("There are no results to analyze");
146 | }
147 |
148 | m_AnalyzerRunning = false;
149 | m_Lock.notifyAll();
150 |
151 | // Kill the thread
152 | m_AnalyzerThread.interrupt();
153 | }
154 | }
155 |
156 | /**
157 | * @return the m_ExcelFilename
158 | */
159 | public synchronized String getM_ExcelFilename() {
160 | return m_ExcelFilename;
161 | }
162 |
163 | /**
164 | * @param m_ExcelFilename the m_ExcelFilename to set
165 | */
166 | public synchronized void setM_ExcelFilename(String m_ExcelFilename) {
167 | this.m_ExcelFilename = m_ExcelFilename;
168 | }
169 |
170 | /**
171 | * @return the m_AutotunerWin
172 | */
173 | public synchronized WinTextWin getM_AutotunerWin() {
174 | return m_AutotunerWin;
175 | }
176 |
177 | /**
178 | * @param m_AutotunerWin the m_AutotunerWin to set
179 | */
180 | public synchronized void setM_AutotunerWin(WinTextWin m_AutotunerWin) {
181 | this.m_AutotunerWin = m_AutotunerWin;
182 | }
183 |
184 | /**
185 | * @return the m_DBResultList
186 | */
187 | public synchronized ArrayList getM_DBResultList() {
188 | return m_DBResultList;
189 | }
190 |
191 | /**
192 | * @param m_DBResultList the m_DBResultList to set
193 | */
194 | public synchronized void setM_DBResultList(ArrayList m_DBResultList) {
195 | this.m_DBResultList = m_DBResultList;
196 | }
197 |
198 | /**
199 | * @return the m_Analyzer
200 | */
201 | public synchronized Analyzer getM_Analyzer() {
202 | return m_Analyzer;
203 | }
204 |
205 | /**
206 | * @param m_Analyzer the m_Analyzer to set
207 | */
208 | public synchronized void setM_Analyzer(Analyzer m_Analyzer) {
209 | this.m_Analyzer = m_Analyzer;
210 | }
211 |
212 | /**
213 | * @return the m_AnalyzerRunning
214 | */
215 | public synchronized Boolean getM_AnalyzerRunning() {
216 | return m_AnalyzerRunning;
217 | }
218 |
219 | /**
220 | * @param m_AnalyzerRunning the m_AnalyzerRunning to set
221 | */
222 | public synchronized void setM_AnalyzerRunning(Boolean m_AnalyzerRunning) {
223 | this.m_AnalyzerRunning = m_AnalyzerRunning;
224 | }
225 |
226 |
227 | }
228 |
--------------------------------------------------------------------------------
/src/main/java/control/ThreadMongoDBAlerter.java:
--------------------------------------------------------------------------------
1 | package control;
2 |
3 | import java.io.IOException;
4 | import java.util.Date;
5 | //import java.sql.SQLException;
6 | import java.text.ParseException;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | import loader.DataLoadBase;
11 | import loader.DataLoadNightScoutTreatments;
12 |
13 | // Purpose of this class is to alert the application on any updates to the underlying
14 | // MongoDB
15 | // Abstract class since there are two primary intended uses - one on treatments one on sensor results
16 | public abstract class ThreadMongoDBAlerter implements Runnable
17 | {
18 | private static final Logger m_Logger = Logger.getLogger( MyLogger.class.getName() );
19 |
20 | // Separate thread for data loads
21 | private Thread m_LoadThread;
22 |
23 | /**
24 | * @return the m_LoadThread
25 | */
26 | public synchronized Thread getM_LoadThread() {
27 | return m_LoadThread;
28 | }
29 |
30 | /**
31 | * @param m_LoadThread the m_LoadThread to set
32 | */
33 | public synchronized void setM_LoadThread(Thread m_LoadThread) {
34 | this.m_LoadThread = m_LoadThread;
35 | }
36 |
37 | // Data Loader used by thread
38 | protected DataLoadNightScoutTreatments m_DataLoader;
39 | protected Date m_LastResultAt;
40 | protected Date m_CurrentResultAt;
41 | protected String m_CurrentResultBy;
42 |
43 | private Boolean m_LoadRunning;
44 | private Object m_Lock;
45 |
46 | private Boolean m_FirstCheckComplete;
47 |
48 | private int m_SleepInterval;
49 |
50 |
51 | // Abstract mmethod that must be overridden
52 | protected abstract void checkDBForUpdates() throws IOException, ParseException;
53 |
54 | protected abstract String whatIsChecked();
55 |
56 | protected void compareAndNotify()
57 | {
58 | final Date epoch = new Date(0);
59 |
60 | m_Logger.log(Level.FINE, "Thread check on " + whatIsChecked() + " on MongoDB. Most recent date/time "
61 | + m_CurrentResultAt.toString() + " by '" + m_CurrentResultBy + "'");
62 |
63 | if (!m_CurrentResultAt.equals(epoch) && m_CurrentResultAt.after(m_LastResultAt))
64 | {
65 | // Check if this is the first change detected
66 | // Could be start up or a delete
67 | if (m_FirstCheckComplete == true)
68 | {
69 | // Something has changed, generate an info message
70 | m_Logger.log(Level.INFO, "Update detected to " + whatIsChecked() + " on MongoDB. Update at "
71 | + m_CurrentResultAt.toString() + " by '" + m_CurrentResultBy + "'");
72 | }
73 | m_FirstCheckComplete = true;
74 | }
75 | m_LastResultAt = m_CurrentResultAt;
76 | // Reset "by"
77 | m_CurrentResultBy = "";
78 | }
79 |
80 | // Thread Synchronization
81 | public void waitUntilFree()
82 | {
83 | synchronized(m_Lock)
84 | {
85 | while (m_LoadRunning)
86 | {
87 | try
88 | {
89 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - Running & about to try lock: " + this );
90 | m_Lock.wait();
91 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - Running & notified : " + this );
92 | }
93 | catch (InterruptedException e)
94 | {
95 | m_Logger.log(Level.SEVERE, "<"+this.getClass().getName()+">" + "ThreadDataLoad Wait - EXCEPTION CAUGHT.", e);
96 | }
97 | }
98 | m_Logger.log( Level.FINE, "ThreadDataLoad Wait - No longer running: " + this);
99 | }
100 | }
101 | // Handler to notify when load completes
102 | DataLoadCompleteHander m_CompleteHandler;
103 |
104 | // Thread Handler for resynchronization
105 | public static abstract class DataLoadCompleteHander
106 | {
107 | private Object m_Object;
108 | public DataLoadCompleteHander(Object obj)
109 | {
110 | m_Object = obj;
111 | }
112 | public abstract void dataLoadComplete(Object obj);
113 | public abstract void exceptionRaised(String message);
114 |
115 | public Object getM_Object()
116 | {
117 | return m_Object;
118 | }
119 | }
120 |
121 | public ThreadMongoDBAlerter()
122 | {
123 | m_LoadRunning = true; // Initialise the thread in running state
124 | m_LoadThread = new Thread(this);
125 | m_DataLoader = new DataLoadNightScoutTreatments();
126 | m_LastResultAt = new Date(0); // Initialized to epoch time
127 | m_CurrentResultAt = new Date(0); // Initialized to epoch time
128 | m_CurrentResultBy = new String();
129 |
130 | m_CompleteHandler = null;
131 |
132 | // Thread synchronization
133 | m_Lock = new Object();
134 |
135 | m_FirstCheckComplete = false; // Initialize to false until first check
136 |
137 | // Set for 10 minutes by default but now from preferences
138 | // m_SleepInterval = 60 * 10;
139 | m_SleepInterval = PrefsNightScoutLoader.getInstance().getM_MongoDBAlerterCheckInterval() * 60 * 10;
140 | }
141 |
142 | public void interrupThread()
143 | {
144 | m_LoadThread.interrupt();
145 | }
146 |
147 | public void startThread()
148 | {
149 | // m_CompleteHandler = completeHandler;
150 |
151 | m_LoadThread.start();
152 | }
153 |
154 | public void run()
155 | {
156 | m_LoadRunning = true;
157 | synchronized(m_Lock)
158 | {
159 | try
160 | {
161 | // Now if preference is set to 0 in options and then changed, it will have no effect
162 | // the thread is effectively dead and never re-created. THis is fine. Expect user to
163 | // relaunch application to reenable alerting
164 | // Similarly, if value is changed, change only takes effect on next launch
165 | if (m_SleepInterval > 0)
166 | {
167 | // Go into an endless loop, checking for updates then sleeping in between
168 | while (!Thread.interrupted())
169 | {
170 | // Call MongoDB looking for any updates.
171 | // Then block
172 | //
173 | // Looked at below, but it requires particular types of Documents.
174 | // http://tugdualgrall.blogspot.co.uk/2015/01/how-to-create-pubsub-application-with.html?m=1
175 | // Instead, simply get latest date from DataLoader, check against last date then notify
176 |
177 | checkDBForUpdates();
178 |
179 | compareAndNotify();
180 |
181 | // Sleep for a minute before checking again.
182 | Thread.sleep(m_SleepInterval * 1000);
183 | }
184 | }
185 | }
186 |
187 | catch (IOException | InterruptedException | ParseException e)
188 | {
189 | if (m_CompleteHandler != null)
190 | {
191 | m_CompleteHandler.exceptionRaised("Thread Exception: " + e.getLocalizedMessage());
192 | }
193 | }
194 | finally
195 | {
196 | if (m_CompleteHandler != null)
197 | {
198 | m_CompleteHandler.dataLoadComplete(m_CompleteHandler.getM_Object());
199 | }
200 | }
201 | m_LoadRunning = false;
202 | m_Lock.notifyAll();
203 |
204 | // Kill the thread
205 | // m_LoadThread.interrupt();
206 | }
207 | }
208 |
209 | /**
210 | * @return the m_LoadRunning
211 | */
212 | public Boolean getM_LoadRunning() {
213 | return m_LoadRunning;
214 | }
215 |
216 | /**
217 | * @param m_LoadRunning the m_LoadRunning to set
218 | */
219 | public void setM_LoadRunning(Boolean m_LoadRunning) {
220 | this.m_LoadRunning = m_LoadRunning;
221 | }
222 |
223 | /**
224 | * @return the m_DataLoader
225 | */
226 | public synchronized DataLoadBase getM_DataLoader() {
227 | return m_DataLoader;
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/src/main/java/loader/DataLoadMedtronic.java:
--------------------------------------------------------------------------------
1 | package loader;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | import control.MyLogger;
11 | import entity.DBResult;
12 | import entity.DBResultMedtronic;
13 | import entity.DBResultMedtronicNew;
14 | import entity.DBResultMedtronicOld;
15 |
16 | public class DataLoadMedtronic extends DataLoadCSVFile
17 | {
18 | private static final Logger m_Logger = Logger.getLogger(MyLogger.class.getName());
19 | private static final String m_MedtronicSplitBy = "[,;]";
20 |
21 | private static Boolean m_OldFileFormat = false;
22 | private static Boolean m_NewFileFormat = false;
23 |
24 |
25 | @Override
26 | protected DBResult makeDBResult(String[] res)
27 | {
28 | DBResultMedtronic result = null;
29 |
30 | if (m_OldFileFormat == true) result = result == null ? new DBResultMedtronicOld(res) : result;
31 | if (m_NewFileFormat == true) result = result == null ? new DBResultMedtronicNew(res) : result;
32 |
33 | return result;
34 | }
35 |
36 | @Override
37 | protected String loadStringName()
38 | {
39 | return "Medtronic";
40 | }
41 |
42 | @Override
43 | protected String getSplitBy()
44 | {
45 | return m_MedtronicSplitBy;
46 | }
47 |
48 | public static boolean isMedtronic(String fileName)
49 | {
50 | boolean result = false;
51 |
52 | result = (result == true ? result : isMedtronicOld(fileName));
53 | result = (result == true ? result : isMedtronicNew(fileName));
54 |
55 | return result;
56 | }
57 |
58 |
59 | public static boolean isMedtronicOld(String fileName)
60 | {
61 | boolean result = false;
62 | BufferedReader br = null;
63 | String line = "";
64 | String cvsSplitBy = "[,;]";
65 |
66 | // Expected Format
67 | boolean ln2Col1PatientInfo = false;
68 | boolean ln3Col1Name = false;
69 | boolean ln4Col1DateRange = false;
70 | boolean ln5Col1Device = false;
71 | boolean ln11Col1Index = false; // 640
72 | boolean ln13Col1Index = false; // Veo
73 | boolean pump = false;
74 | boolean meter = false;
75 | boolean pump_and_meter = false;
76 |
77 | int ln = 0;
78 | int maxLines = 12;
79 | int index = 10; // for 640 & +2 for Veo
80 | int meterpump1 = 6; // Increment index if both meter and pump seen
81 | int meterpump2 = 7; // Increment for each line that Meter is listed
82 |
83 | try
84 | {
85 | br = new BufferedReader(new FileReader(fileName));
86 | while ((ln <= maxLines) && (line = br.readLine()) != null)
87 | {
88 | ln++;
89 | // use comma as separator
90 | String[] rs = line.split(cvsSplitBy);
91 |
92 | if (ln == 2)
93 | ln2Col1PatientInfo = (rs.length > 0 && rs[0].equals("PATIENT INFO")) ? true : false;
94 | if (ln == 3)
95 | ln3Col1Name = (rs.length > 0 && rs[0].equals("Name")) ? true : false;
96 | if (ln == 4)
97 | ln4Col1DateRange = (rs.length > 0 && rs[0].equals("Report Range")) ? true : false;
98 | if (ln == 5)
99 | ln5Col1Device = (rs.length > 0 && rs[0].equals("DEVICE INFO")) ? true : false;
100 |
101 | if (ln == meterpump1)
102 | {
103 | pump = (pump || (rs.length > 0 && rs[0].equals("Pump:"))) ? true : false;
104 | meter = (meter || (rs.length > 0 && rs[0].equals("Meter:"))) ? true : false;
105 | }
106 |
107 | if (ln == meterpump2)
108 | {
109 | pump = (pump || (rs.length > 0 && rs[0].equals("Pump:"))) ? true : false;
110 | meter = (meter || (rs.length > 0 && rs[0].equals("Meter:"))) ? true : false;
111 | }
112 |
113 |
114 | if (pump && meter && !pump_and_meter)
115 | {
116 | // There could be more than one meter, so allow index to drift forward by one
117 | // each time we see a separate meter line
118 | //
119 | // 19 Feb 2017
120 | // Seen Pump: at line 6 in file from Melanie Mason
121 | index++;
122 | maxLines++;
123 |
124 | pump_and_meter = true;
125 | }
126 |
127 | if (ln == index)
128 | ln11Col1Index = (rs.length > 0 && rs[0].equals("Index")) ? true : false;
129 | if (ln == index + 2)
130 | ln13Col1Index = (rs.length > 0 && rs[0].equals("Index")) ? true : false;
131 | }
132 |
133 | result = (ln2Col1PatientInfo == true && ln3Col1Name == true && ln4Col1DateRange == true &&
134 | ln5Col1Device == true && (ln11Col1Index == true || ln13Col1Index == true) ) ? true : false;
135 |
136 | }
137 | catch (FileNotFoundException e)
138 | {
139 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: FileNotFoundException. File " + fileName + " Error " + e.getMessage());
140 |
141 | e.printStackTrace();
142 | }
143 | catch (IOException e)
144 | {
145 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: IOException. File " + fileName + " Error " + e.getMessage());
146 | e.printStackTrace();
147 | }
148 | finally
149 | {
150 | if (br != null)
151 | {
152 | try
153 | {
154 | br.close();
155 | }
156 | catch (IOException e)
157 | {
158 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: IOException closing file. File " + fileName + " Error " + e.getMessage());
159 | e.printStackTrace();
160 | }
161 | }
162 | }
163 |
164 | m_OldFileFormat = result;
165 | return result;
166 | }
167 |
168 |
169 | public static boolean isMedtronicNew(String fileName)
170 | {
171 | boolean result = false;
172 | BufferedReader br = null;
173 | String line = "";
174 | String cvsSplitBy = "[,;]";
175 |
176 | // Expected Format
177 | boolean ln1Col1PatientInfo = false;
178 | boolean ln6Col1Device = false;
179 | boolean ln7Index = false;
180 |
181 | int ln = 0;
182 | int maxLines = 10;
183 | // int index = 10; // for 640 & +2 for Veo
184 | // int meterpump1 = 6; // Increment index if both meter and pump seen
185 | // int meterpump2 = 7; // Increment for each line that Meter is listed
186 |
187 | try
188 | {
189 | br = new BufferedReader(new FileReader(fileName));
190 | while ((ln <= maxLines) && (line = br.readLine()) != null)
191 | {
192 | ln++;
193 | // use comma as separator
194 | String[] rs = line.split(cvsSplitBy);
195 |
196 | if (ln == 1)
197 | ln1Col1PatientInfo = (rs.length > 0 && rs[0].equals("Last Name")) ? true : false;
198 | if (ln == 6)
199 | ln6Col1Device = (rs.length > 0 && rs[0].equals("-------")) ? true : false;
200 | if (ln == 7)
201 | ln7Index = (rs.length > 0 && rs[0].equals("Index")) ? true : false;
202 |
203 | }
204 |
205 | result = (ln1Col1PatientInfo == true && ln6Col1Device == true && ln7Index == true ) ? true : false;
206 |
207 | }
208 | catch (FileNotFoundException e)
209 | {
210 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: FileNotFoundException. File " + fileName + " Error " + e.getMessage());
211 |
212 | e.printStackTrace();
213 | }
214 | catch (IOException e)
215 | {
216 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: IOException. File " + fileName + " Error " + e.getMessage());
217 | e.printStackTrace();
218 | }
219 | finally
220 | {
221 | if (br != null)
222 | {
223 | try
224 | {
225 | br.close();
226 | }
227 | catch (IOException e)
228 | {
229 | m_Logger.log(Level.SEVERE, "" + "isMedtronic: IOException closing file. File " + fileName + " Error " + e.getMessage());
230 | e.printStackTrace();
231 | }
232 | }
233 | }
234 |
235 | m_NewFileFormat = result;
236 | return result;
237 | }
238 |
239 | }
240 |
241 |
--------------------------------------------------------------------------------