/* * Class GoToPowerDown * * This software is developed for Choral devices with Java. * Copyright Choral srl. All Rights reserved. */ package general; import java.util.EmptyStackException; import javax.microedition.rms.RecordStore; import javax.microedition.rms.RecordStoreException; import javax.microedition.rms.RecordStoreFullException; import javax.microedition.rms.RecordStoreNotOpenException; /** * Sets the application to put the module in Power Down, * setting date and time of awakening of the module and * writing to FILE all data and system settings to recover * at next start of the application. * * @version 1.02 <BR> <i>Last update</i>: 25-10-2007 * @author alessioza * */ public class GoToPowerDown extends ThreadCustom implements GlobCost { /* * local variables */ protected Object objGPRMC; protected String GPRMCorig, GPRMCmod; protected String dataGPRMC = "00/00/00"; protected String oraGPRMC = "00:00:00"; protected String timeSveglia; protected int virgIndex; protected boolean fixFlag = false; // Array for GPS position strings private String[] arrayGPS; /* * INHERITED RESOURCES from ThreadCustom and passed to AppMain * * semaphore 'semAT', for the exclusive use of the AT resource * flag 'ATexec', indicates if AT resource is busy * flag 'validFIXgprs', indicates if it has been completed sending * of GPS strings through GPRS * flag 'FIXtimeoutExpired', indicates if FIXtimeout expires * flag 'isFirstRun', indication for first application execution * Mailbox 'mboxMAIN', to send msg to AppMain * Mailbox 'mbox2', to send msg to th2 (ATsender) * Mailbox 'mbox4', to receive msg with this thread * DataStore 'dsData', to deposit GPS strings * FlashFile 'file', to save settings * FlashRecordStore 'flash', to save settings */ /* * constructors */ public GoToPowerDown() { if(debug){ System.out.println("Th*GoToPowerDown: CREATED"); } // Final GPS string has 19 chars (without checksum, added after) arrayGPS = new String[19]; } /* * methods */ public void run() { if(debug){ System.out.println("Th*GoToPowerDown: STARTED"); } /* * Two possibilities: * 1) valid FIX * 2) not valid FIX or 'FIXtimeout' expired, timeout within which * it must be done the first FIX * * In any case, I have to put the module in Power Down, if the * timeout has expired I keep good the current Real Time Clock to * calculate current date and time of awakening. * (Please note: possible problem if at the first start of the * application is not made a FIX) */ try { /* * [1] EXTRACT CURRENT DATE/TIME */ /* * CASE n.1: valid FIX correctly sent through GPRS and timeout not expired: * a) if actual string is valid, I use it * b) if actual string is not valid, I use the last valid */ if (infoS.getValidFIX()==true){ if(debug){ System.out.println("Th*GoToPowerDown: CASE n.1"); } Posusr msg = new Posusr(); msg.addInfoStato(infoS); String tempRMC = (String)dsDataRMC.readOnlyIfObjectIsValid(); String tempGGA = (String)dsDataGGA.readOnlyIfObjectIsValid(); if(tempRMC!=null) objGPRMC = msg.set_posusr(tempRMC, tempGGA); else objGPRMC = null; // check validity if (objGPRMC != null) { // if current string is valid --> OK GPRMCorig = (String)objGPRMC; } else { /* if current string is not valid * then get the last valid */ tempRMC = (String)dsDataRMC.getLastValid(); tempGGA = (String)dsDataGGA.getLastValid(); if((tempRMC != null) && (!(tempRMC.equals("")))) GPRMCorig = msg.set_posusr(tempRMC, tempGGA); else GPRMCorig = ""; // GPRMCorig = (String)choralQueue.LastValidElement(); } // I create a local copy for subsequent processing GPRMCmod = GPRMCorig; if(debug){ System.out.println("Th*GoToPowerDown: Letta la stringa: " + GPRMCorig); } /* * Convert GPS string in a array of strings * */ virgIndex = 0; for (int i=0; i<arrayGPS.length-2; i++) { virgIndex = GPRMCmod.indexOf(","); /* =6 */ //System.out.println("virgIndex: "+virgIndex); if (virgIndex>0) { arrayGPS[i] = GPRMCmod.substring(0,virgIndex); /* from 0 to 5 */ } else arrayGPS[i] = null; // null if field is empty //System.out.println("Item inserted into array: "+arrayGPRMC[i]); GPRMCmod = GPRMCmod.substring(virgIndex+1); /* from 7 to FINE_STRINGA */ //System.out.println("letturaStringa: "+letturaStringa); } // pay attention to checksum, is preceded by * virgIndex = GPRMCmod.indexOf("*"); // identify * if (virgIndex>0) { arrayGPS[arrayGPS.length-2] = GPRMCmod.substring(0,virgIndex); } else arrayGPS[arrayGPS.length-2] = null; arrayGPS[arrayGPS.length-1] = GPRMCmod.substring(virgIndex+1); /* * Data of interest are into arrayGPS at indexes: * 5 -> time in format hhmmss * 4 -> date in format yymmdd */ // extract time in format hh:mm:ss and date in format yy/mm/dd oraGPRMC = arrayGPS[5].substring(0,2)+":"+arrayGPS[5].substring(2,4)+":"+arrayGPS[5].substring(4,6); dataGPRMC = arrayGPS[4].substring(0,2)+"/"+arrayGPS[4].substring(2,4)+"/"+arrayGPS[4].substring(4,6); /* Please note: use satellite time */ // SET RTC semAT.getCoin(5); if(debug){ System.out.println("Th*GoToPowerDown: Set RTC in progress..."); } // send 'at+cclk' infoS.setATexec(true); if(debug){ System.out.println("Th*GoToPowerDown: ATexec = " + infoS.getATexec()); } mbox2.write("at+cclk=\"" + dataGPRMC + "," + oraGPRMC + "\"\r"); if(debug){ System.out.println("Th*GoToPowerDown: sent message: at+cclk.."); System.out.println("Th*GoToPowerDown,at+cclk: wait for AT resource is free..."); } while(infoS.getATexec()) { Thread.sleep(whileSleep); } semAT.putCoin(); } //case 1 /* * CASE n.2: timeout expired, put module in Power Down * recovering current time and date from RTC */ else if (infoS.getValidFIX()==false) { if(debug){ System.out.println("Th*GoToPowerDown: CASE n.2"); } // recover time and date from RTC through read command 'AT+CCLK?' semAT.getCoin(5); if(debug){ System.out.println("Th*GoToPowerDown: read RTC in progress..."); } // send 'at+cclk?' infoS.setATexec(true); mbox2.write("at+cclk?\r"); while(infoS.getATexec()) { Thread.sleep(whileSleep); } semAT.putCoin(); // wait for answer while(infoS.getDataGPRMC() == null || infoS.getOraGPRMC() == null) { Thread.sleep(whileSleep); } dataGPRMC = infoS.getDataGPRMC(); oraGPRMC = infoS.getOraGPRMC(); infoS.setDataOraGPRMC(null, null); GPRMCorig = ""; if(debug){ System.out.println("date GPRMC: " + dataGPRMC); System.out.println("time GPRMC: " + oraGPRMC); } } //case 2 /* * CASE n.3: other */ else { if(debug){ System.out.println("Case n.3"); System.out.println("Valid FIX GPRS: "+infoS.getValidFIXgprs()); System.out.println("FIX timeout EXPIRED: "+infoS.isFIXtimeoutExpired()); } GPRMCorig = ""; } //case 3 /* * [2] SET TIME/DATE OF AWAKENING * * not to do incase of closure for battery low */ if (infoS.getSTATOexecApp().equalsIgnoreCase(execBATTSCARICA)) { /* * Don't set time of awakening */ if(debug){ System.out.println("Th*GoToPowerDown: not set time of awakening!"); } } else { // Calculate new time of awakening CalcolaSveglia cs = new CalcolaSveglia(); if(debug){ System.out.println("Th*GoToPowerDown: calculation of new time of awakening..."); } cs.putTime(dataGPRMC,oraGPRMC); timeSveglia = cs.setSveglia(); if(!timeSveglia.equals("error")){ semAT.getCoin(5); if(debug){ System.out.println("Th*GoToPowerDown: Set alarm time in progress..."); } // send 'at+cala' infoS.setATexec(true); //System.out.println("Th*GoToPowerDown: ATexec = " + infoS.getATexec()); mbox2.write("at+cala=\"" + timeSveglia + "\"\r"); if(debug){ System.out.println("Th*GoToPowerDown: sent message 'at+cala'..."); } //System.out.println("Th*GoToPowerDown: wait for AT resource is free..."); while(infoS.getATexec()) { Thread.sleep(whileSleep); } semAT.putCoin(); } } /* * [3] SAVE SYSTEM SETTINGS to file */ if(debug){ System.out.println("Th*GoToPowerDown: saving system settings to FILE in progress..."); } /* Save last valid GPS position string: * - if FIX done in this session --> replace it with the last valid * - if FIX not done --> maintain original one */ Posusr msg = new Posusr(); msg.addInfoStato(infoS); String tempRMC = (String)dsDataRMC.getLastValid(); String tempGGA = (String)dsDataGGA.getLastValid(); if((tempRMC != null) && (!(tempRMC.equals("")))) file.setImpostazione(LastGPSValid, msg.set_posusr(tempRMC, tempGGA)); else file.setImpostazione(LastGPSValid, ""); /* * Saving application closure mode */ /* * FIRST EXECUTION * (only if I find KEY not active at the first time that I observe it) */ if (infoS.getSTATOexecApp().equalsIgnoreCase(execFIRST)) { if(debug){ System.out.println("Th*GoToPowerDown, closure from status :" + execFIRST); } // Key deactivation FIRST file.setImpostazione(CloseMode, closeAppDisattivChiaveFIRST); // pay attention, MODIFY FOR DEBUG //file.setImpostazione(CloseMode, closeAppFactory); } // NORMAL EXECUTION else if (infoS.getSTATOexecApp().equalsIgnoreCase(execNORMALE)) { if(debug){ System.out.println("Th*GoToPowerDown, closure from status :" + execNORMALE); } // Normal OK if (infoS.getValidFIXgprs()==true) { file.setImpostazione(CloseMode, closeAppNormaleOK); } // Normal Timeout EXPIRED else if (infoS.getValidFIXgprs()==false) { file.setImpostazione(CloseMode, closeAppNormaleTimeout); } } // KEY DEACTIVATED else if (infoS.getSTATOexecApp().equalsIgnoreCase(execCHIAVEdisattivata)) { if(debug){ System.out.println("Th*GoToPowerDown, closure from status :" + execCHIAVEdisattivata); } // Key deactivation OK if (infoS.getValidFIXgprs()==true) { file.setImpostazione(CloseMode, closeAppDisattivChiaveOK); } // Key deactivation Timeout EXPIRED else if (infoS.getValidFIXgprs()==false) { file.setImpostazione(CloseMode, closeAppDisattivChiaveTimeout); } } // MOVEMENT else if (infoS.getSTATOexecApp().equalsIgnoreCase(execMOVIMENTO)) { if(debug){ System.out.println("Th*GoToPowerDown, closure from status :" + execMOVIMENTO); } // Movement OK file.setImpostazione(CloseMode, closeAppMovimentoOK); } // AFTER RESET else if (infoS.getSTATOexecApp().equalsIgnoreCase(execPOSTRESET)) { if(debug){ System.out.println("Th*GoToPowerDown, closure from status :" + execPOSTRESET); } // Key deactivation after RESET file.setImpostazione(CloseMode, closeAppPostReset); } // BATTERY LOW else if (infoS.getSTATOexecApp().equalsIgnoreCase(execBATTSCARICA)) { if(debug){ System.out.println("Th*GoToPowerDown, closure from status :" + execBATTSCARICA); } // Battery Low file.setImpostazione(CloseMode, closeAppBatteriaScarica ); } // Write on file InfoStato.getFile(); file.writeSettings(); InfoStato.freeFile(); /* * [4] SAVING DATA on RecordStore */ if(debug){ System.out.println("Th*GoToPowerDown: Saving data on RecordStore in progress..."); } try { // Open RecordStore RecordStore rs = RecordStore.openRecordStore(recordStoreName, true); // Modify record try { String appt = (String)dsDataRMC.getLastValid(); //System.out.println("FlashRecordStore: get: "+appt); byte data[] = appt.getBytes(); //System.out.println("FlashRecordStore: converted in bytes: "+appt); rs.setRecord(1, data, 0, data.length); //System.out.println("FlashRecordStore: saved: "+appt); } catch (RecordStoreException rse) { //System.out.println("FlashRecordStore: RecordStoreException"); // add record because not exists String newappt = (String)dsDataRMC.getLastValid(); byte newdata[] = newappt.getBytes(); rs.addRecord(newdata,0,newdata.length); //System.out.println("FlashRecordStore: saved: "+newappt); } // Close RecordStore rs.closeRecordStore(); } catch (RecordStoreNotOpenException rsnoe) { //System.out.println("FlashRecordStore: RecordStoreNotOpenException"); new LogError("FlashRecordStore: RecordStoreNotOpenException"); } catch (RecordStoreFullException rsfe) { //System.out.println("FlashRecordStore: RecordStoreFullException"); new LogError("FlashRecordStore: RecordStoreFullException"); } catch (RecordStoreException rse) { //System.out.println("FlashRecordStore: RecordStoreException"); new LogError("FlashRecordStore: RecordStoreException"); } catch (NullPointerException npe) { //System.out.println("NullPointerException in RecordStore"); new LogError("FlashRecordStore: NullPointerException in RecordStore"); } /* * Notify to AppMain to close application */ mboxMAIN.write(msgClose); if(debug){ System.out.println("Th*GoToPowerDown: sent message: "+msgClose); } } catch (EmptyStackException e) { //System.out.println("exception: " + e.getMessage()); new LogError("ERROR"); //e.printStackTrace(); } catch (InterruptedException ie) { new LogError("Th*GoToPowerDown: InterruptedException ie"); } catch (NullPointerException npe) { //System.out.println("NullPointerException in GoToPowerDown"); new LogError("NullPointerException in GoToPowerDown"); }//catch } //run /** * Private class to calculate date and time to use to set * awakening of the module * * @version * @author alessioza * */ private class CalcolaSveglia implements GlobCost { /* * local variables */ private int hh,mm,ss,YY,MM,DD; private String hhS,mmS,ssS,YYs,MMs,DDs,ris; private int addH,changeMM,bisest; /* * constructors */ public CalcolaSveglia() { } /* * methods */ /** * Insert current date and time, to use for calculation * of awakening time and date * * @param data date with format YY/MM/DD * @param ora time with format hh:mm:ss * */ public void putTime(String data, String ora) { try{ /* time -> hh:mm:ss */ hh = Integer.parseInt(ora.substring(0,2)); mm = Integer.parseInt(ora.substring(3,5)); ss = Integer.parseInt(ora.substring(6)); /* date -> YY/MM/DD */ YY = Integer.parseInt(data.substring(0,2)); MM = Integer.parseInt(data.substring(3,5)); DD = Integer.parseInt(data.substring(6)); if(debug){ System.out.println("putTime\r\nhh:"+hh+" mm:"+mm+" ss:"+ss+"\r\nYY:"+YY+" MM:"+MM+" DD: "+DD); } }catch (NumberFormatException e){ new LogError("putTime waking up error"); } } //putTime /** * Calculate date and time of awakening of the module * * @return string with format 'YY/MM/DD,hh:mm:ss' * */ public String setSveglia() { try{ /* UPDATE MINUTES AND HOURS */ /* Update minutes * Please note: mSleep must be between 0 and 59 minutes */ if(debug){ System.out.println("CalcolaSveglia: set time of awakening in progress..."); } addH = 0; mm = mm + infoS.getInfoFileInt(MinPowerDownOK); if (mm>59) { addH = 1; /* go to next hour */ mm = mm-60; /* update minutes */ } //if /* update total numer of hours, hSleep >= 0 */ if (addH==0) { hh = hh + infoS.getInfoFileInt(OrePowerDownOK); } else { /* addH=1 */ hh = hh + infoS.getInfoFileInt(OrePowerDownOK) + 1; } //if /* UPDATE TIME and ev. DATE */ /* Check leap year: * are leap all years divisible by an integer multiple of 4, * (as long as it is not secular years) */ if (YY%4==0) {bisest=1;} else bisest=0; changeMM = 0; while (hh>23) { hh = hh - 24; /* if I have to change date, depends on month */ switch (MM) { case 1: { /*january*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; case 2: { /*february*/ if (bisest==0) { if (DD>0 && DD<28) DD++; if (DD==28) changeMM=1; } else if (bisest==1) { if (DD>0 && DD<29) DD++; if (DD==29) changeMM=1; } } break; case 3: { /*march*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; case 4: { /*april*/ if (DD>0 && DD<30) DD++; if (DD==30) changeMM=1; } break; case 5: { /*may*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; case 6: { /*june*/ if (DD>0 && DD<30) DD++; if (DD==30) changeMM=1; } break; case 7: { /*july*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; case 8: { /*august*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; case 9: { /*september*/ if (DD>0 && DD<30) DD++; if (DD==30) changeMM=1; } break; case 10: { /*october*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; case 11: { /*november*/ if (DD>0 && DD<30) DD++; if (DD==30) changeMM=1; } break; case 12: { /*december*/ if (DD>0 && DD<31) DD++; if (DD==31) changeMM=1; } break; } //switch(MM) /* change month */ if (changeMM==1) { if (MM>0 & MM<12) { /* month between january and november */ MM++; } else { /* if decxember, go to january and change year */ MM=1; YY++; } //if } //changeMM } //while // verify correct alarm setting if(debug){ System.out.println("set alarm:\r\nhh:"+hh+" mm:"+mm+" ss:"+ss+"\r\nYY:"+YY+" MM:"+MM+" DD:"+DD); } /* Convert from number to strings, * if number has 1 digit rather than 2, add zero where there isn't */ hhS = Integer.toString(hh); if (hhS.length()==1) hhS = "0"+hhS; mmS = Integer.toString(mm); if (mmS.length()==1) mmS = "0"+mmS; ssS = Integer.toString(ss); if (ssS.length()==1) ssS = "0"+ssS; YYs = Integer.toString(YY); if (YYs.length()==1) YYs = "0"+YYs; MMs = Integer.toString(MM); if (MMs.length()==1) MMs = "0"+MMs; DDs = Integer.toString(DD); if (DDs.length()==1) DDs = "0"+DDs; /* create string */ ris = YYs+"/"+MMs+"/"+DDs+","+hhS+":"+mmS+":"+ssS; if(debug){ System.out.println("Result in string: "+ris); } return ris; } catch (NumberFormatException e){ new LogError("Th*GoToPowerDown: NumberFormatException"); return "error"; } } //setSveglia } //class CalcolaSveglia } //GoToPowerDown