package de.jotomo.ruffyscripter.commands; import android.util.Log; import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.BEFORE; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.MAIN; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.BASAL_1_MENU; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.BASAL_OVERVIEW; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.READ_BASAL; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.ERROR; import static de.jotomo.ruffyscripter.commands.GetBasalCommand.State.AFTER; public class GetBasalCommand implements Command { private static final Logger log = LoggerFactory.getLogger(GetBasalCommand.class); private RuffyScripter scripter; public GetBasalCommand() {} @Override public List validateArguments() { List violations = new ArrayList<>(); return violations; } enum State { BEFORE, MAIN, BASAL_1_MENU, BASAL_OVERVIEW, READ_BASAL, ERROR, AFTER, }; private State lastState,state; private long last; private long timeout; private Thread timeoutThread = new Thread() { @Override public void run() { while(state != ERROR && state!=AFTER) { if (timeout + last < System.currentTimeMillis()) { lastState = state; state = ERROR; log.debug("timeout reached -> state:ERROR"); } tick(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } tick(); } }; private void updateState(State newState,long timeoutSec) { lastState = state; state = newState; last = System.currentTimeMillis(); timeout = timeoutSec*1000; } private MenuType lastMenu; private int retries = 0; private double basalTotal = 0; private Map rate = new HashMap<>(); private void tick() { switch (state) { case BEFORE: if(scripter.currentMenu!=null && scripter.currentMenu.getType()==MenuType.MAIN_MENU) { updateState(MAIN,120); lastMenu = MenuType.MAIN_MENU; log.debug("found MAIN_MENU -> state:MAIN"); retries=3; } break; case MAIN: if(retries>0) if(scripter.goToMainMenuScreen(MenuType.BASAL_1_MENU,30000)) { if(scripter.enterMenu(MenuType.BASAL_1_MENU,MenuType.BASAL_TOTAL, RuffyScripter.Key.CHECK,2000)) { updateState(BASAL_OVERVIEW, 30); retries=0; } } else retries--; else updateState(ERROR,30); break; case BASAL_OVERVIEW: if(scripter.currentMenu.getType()==MenuType.BASAL_TOTAL && scripter.currentMenu.getAttribute(MenuAttribute.BASAL_TOTAL)!=null && (Integer)scripter.currentMenu.getAttribute(MenuAttribute.BASAL_SELECTED)==1) { basalTotal = (Double)scripter.currentMenu.getAttribute(MenuAttribute.BASAL_TOTAL); if(scripter.enterMenu(MenuType.BASAL_TOTAL,MenuType.BASAL_SET, RuffyScripter.Key.MENU,3000)) { updateState(READ_BASAL,30); retries = 96; } } break; case READ_BASAL: if(scripter.currentMenu.getType()==MenuType.BASAL_SET && scripter.currentMenu.getAttribute(MenuAttribute.BASAL_START)!=null) { Object rateObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); MenuTime time = (MenuTime) scripter.currentMenu.getAttribute(MenuAttribute.BASAL_START); if (rateObj instanceof Double) { rate.put(time.getHour(), (Double) rateObj); } boolean complete = true; for (int t = 0; t < 24; t++) { if (rate.get(t) == null) complete = false; } if (retries > 0) { if (complete) { scripter.pressBackKey(); updateState(AFTER, 30); } else { retries--; scripter.pressMenuKey(); scripter.waitScreen(250); } } else { updateState(ERROR, 30); } } break; case ERROR: case AFTER: scripter.goToMainMenuScreen(MenuType.MAIN_MENU,2000); synchronized(GetBasalCommand.this) { GetBasalCommand.this.notify(); } break; } } @Override public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { state = BEFORE; this.scripter = scripter; updateState(BEFORE,120); timeoutThread.start(); try { synchronized (this) { this.wait(); } } catch (InterruptedException e) { e.printStackTrace(); return new CommandResult().success(false).message("failed to wait: "+e.getMessage()); } if(state==AFTER) { for(int i = 0; i < 24;i++) { Log.v("BASAL_RATE","BASAL_RATE from "+String.format("%02d",i)+":00 = "+rate.get(i)); } return new CommandResult().success(true).enacted(true).message("Basal Rate was read"); } return new CommandResult().success(false).message("failed with state: "+state+" from: "+lastState); } @Override public String toString() { return "GetTbrCommand{}"; } }