/* * This file is part of Domodroid. * * Domodroid is Copyright (C) 2011 Pierre LAINE, Maxime CHOFARDET * * Domodroid is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * Domodroid is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Domodroid. If not, see <http://www.gnu.org/licenses/>. */ package widgets; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Typeface; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.FrameLayout; import android.widget.TextView; import org.domogik.domodroid13.R; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; import Abstract.calcul; import misc.tracerengine; import rinor.Rest_com; public class Graphical_Info_View extends View implements OnClickListener { private final String parameter; private int width; private int height; private Canvas can; private Canvas can2; private final Vector<Vector<Float>> values; private float gridStartX; private float gridStartY; private float gridStopX; private float gridStopY; private float gridOffset; private float valueOffset; private float minf; private float maxf; private float avgf; public int dev_id; public int id; public String state_key; public Thread thread; //public int period; public int update; private final Handler handler; public boolean activate = false; private boolean loaded = false; private final String mytag = "Graphical_Info_View"; private final FrameLayout container = null; private View myself = null; private Calendar calendar = Calendar.getInstance(); private final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm"); private final Date time_start = new Date(); private final Date time_end = new Date(); public TextView dates = null; private int period_type = 0; // 0 = period defined by settings // 1 = 1 day // 8 = 1 week // 30 = 1 month // 365 = 1 year private int sav_period; private Button Prev = null; private Button Next = null; private Button Year = null; private Button Month = null; private Button Week = null; private Button Day = null; private String step = "hour"; private int limit = 6; // items returned by Rinor on stats arrays when 'hour' average private OnClickListener listener = null; private tracerengine Tracer = null; private final String login; private final String password; private final float size15; private final float size10; private final float size5; private final float size7; private final float api_version; private Boolean SSL; private String unit = ""; private Bitmap buffer; private Bitmap text; final Activity activity; public Graphical_Info_View(final Activity activity, tracerengine Trac, Context context, SharedPreferences params, String parameters) { super(context); this.activity = activity; invalidate(); this.Tracer = Trac; this.parameter = parameters; login = params.getString("http_auth_username", "Anonymous"); password = params.getString("http_auth_password", ""); api_version = params.getFloat("API_VERSION", 0); SSL = params.getBoolean("ssl_activate", false); try { //Basilic add, number feature has a unit parameter JSONObject jparam = new JSONObject(parameter.replaceAll(""", "\"")); unit = jparam.getString("unit"); } catch (JSONException jsonerror) { Tracer.i(mytag, "No unit for this feature"); } if (unit.equals("null")) unit = ""; values = new Vector<>(); activate = true; this.myself = this; period_type = 1; //by default, display 24 hours compute_period(); //To initialize time_start & time_end //correct kitkat problem //DisplayMetrics metrics = getResources().getDisplayMetrics(); //width= metrics.widthPixels; //height= metrics.heightPixels; //fixed 15 float text size = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 15, metrics); DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); //Label Text size according to the screen size size15 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 15, metrics); size10 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, metrics); size7 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 7, metrics); size5 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 5, metrics); handler = new Handler() { @Override public void handleMessage(Message msg) { if (!activate) { Tracer.d(mytag, "Handler receives a request to die "); //That seems to be a zombie myself.setVisibility(GONE); if (container != null) { container.removeView(myself); container.recomputeViewAttributes(myself); } invalidate(); try { finalize(); } catch (Throwable t) { t.printStackTrace(); } //kill the handler thread itself } else { invalidate(); } } }; } public void onClick(View v) { String tag = (String) v.getTag(); sav_period = period_type; //Save the current graph period switch (tag) { case "Prev": Prev = (Button) v; period_type = -1; break; case "Next": Next = (Button) v; period_type = 0; break; case "Year": Year = (Button) v; period_type = 365; break; case "Month": Month = (Button) v; period_type = 31; break; case "Week": Week = (Button) v; period_type = 8; break; case "Day": Day = (Button) v; period_type = 1; break; } force_aspect(period_type); compute_period(); updateTimer(); } private void force_aspect(int which) { if (Prev != null) if (which != -1) Prev.setTypeface(null, Typeface.NORMAL); else Prev.setTypeface(null, Typeface.BOLD); if (Next != null) if (which != 0) Next.setTypeface(null, Typeface.NORMAL); else Next.setTypeface(null, Typeface.BOLD); if (Year != null) if (which != 365) Year.setTypeface(null, Typeface.NORMAL); else Year.setTypeface(null, Typeface.BOLD); if (Month != null) if (which != 31) Month.setTypeface(null, Typeface.NORMAL); else Month.setTypeface(null, Typeface.BOLD); if (Week != null) if (which != 8) Week.setTypeface(null, Typeface.NORMAL); else Week.setTypeface(null, Typeface.BOLD); if (Day != null) if (which != 1) Day.setTypeface(null, Typeface.NORMAL); else Day.setTypeface(null, Typeface.BOLD); } public void onWindowVisibilityChanged(int visibility) { Tracer.i(mytag, "Visibility changed to : " + visibility); if (visibility == View.VISIBLE) { this.activate = true; display_dates(); } else activate = false; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); width = getMeasuredWidth(); height = getMeasuredHeight(); buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); text = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); can = new Canvas(buffer); can2 = new Canvas(text); gridStartY = height - size15; gridStopY = size15; gridOffset = size15; valueOffset = size10; drawMessage(); try { drawGrid(); drawValue(); drawGraph(); } catch (Exception e) { Tracer.e(mytag, e.toString()); } if (loaded) { canvas.drawBitmap(buffer, 0, 0, new Paint()); buffer.recycle(); } else { canvas.drawBitmap(text, 0, 0, new Paint()); text.recycle(); } } private void drawMessage() { Paint paint = new Paint(); paint.setColor(Color.DKGRAY); paint.setAntiAlias(true); paint.setTextSize(size15); can2.drawText(getContext().getString(R.string.loading_data_from_rest), size10, size15, paint); } private void drawGrid() { Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.GRAY); paint.setStyle(Paint.Style.STROKE); can.drawColor(Color.TRANSPARENT); can.drawLine(gridStartX, gridStartY, gridStopX, gridStartY, paint); can.drawLine(gridStartX, gridStartY, gridStartX, gridStopY, paint); } private void drawValue() { //min - max - avg lines float gridSize_values = (gridStartY - gridOffset) - (gridStopY + gridOffset); float scale_values = gridSize_values / (maxf - minf); DashPathEffect dashPath = new DashPathEffect(new float[]{10, 5}, 1); Paint paint = new Paint(); paint.setPathEffect(dashPath); paint.setColor(Color.GRAY); paint.setStrokeWidth(1); can.drawLine(gridStartX, gridStartY - gridOffset, gridStopX, gridStartY - gridOffset, paint); can.drawLine(gridStartX, gridStopY + gridOffset, gridStopX, gridStopY + gridOffset, paint); paint.setColor(Color.parseColor("#993300")); can.drawLine(gridStartX, (gridStartY - gridOffset) - ((avgf - minf) * scale_values), gridStopX, (gridStartY - gridOffset) - ((avgf - minf) * scale_values), paint); //min - max - avg values paint.setPathEffect(null); paint.setAntiAlias(true); paint.setStyle(Paint.Style.FILL_AND_STROKE); paint.setTextSize(size10); paint.setColor(Color.BLACK); can.drawText(String.format("%.2f", minf) + " " + unit, gridStartX - valueOffset - (Float.toString(minf).length() * size5), gridStartY - gridOffset, paint); can.drawText(String.format("%.2f", maxf) + " " + unit, gridStartX - valueOffset - (Float.toString(maxf).length() * size5), gridStopY + gridOffset, paint); can.drawText(String.format("%.2f", avgf) + " " + unit, gridStartX - valueOffset - (Float.toString(avgf).length() * size5), (gridStartY - gridOffset) - ((avgf - minf) * scale_values), paint); //temp values DashPathEffect dashPath2 = new DashPathEffect(new float[]{3, 8}, 1); paint.setStyle(Paint.Style.FILL); float temp_step = (maxf - minf) / 6; for (int i = 1; i < 6; i++) { paint.setPathEffect(dashPath2); paint.setAntiAlias(false); paint.setColor(Color.parseColor("#0B909A")); can.drawLine(gridStartX, (gridStartY - gridOffset) - ((temp_step * i) * scale_values), gridStopX, (gridStartY - gridOffset) - ((temp_step * i) * scale_values), paint); paint.setPathEffect(null); paint.setAntiAlias(true); paint.setColor(Color.BLACK); float right_value = minf + temp_step * i; String s = String.format("%.2f", right_value); can.drawText(s + " " + unit, gridStopX + size5, (gridStartY - gridOffset) - ((temp_step * i) * scale_values), paint); } } private void drawGraph() { float gridSize_values = (gridStartY - gridOffset) - (gridStopY + gridOffset); float scale_values = gridSize_values / (maxf - minf); float step = (gridStopX - gridStartX) / (values.size() - 1); int top = 0; String top_txt = ""; int rythm = 1; int curr = 0; Paint paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.FILL); //Tracer.i(mytag,"drawGraph limit = "+limit+" , step = "+step+"Array size = "+values.size()); for (int i = 0; i < values.size(); i++) { if (limit == 6) { top = values.get(i).get(4).intValue(); //get the hour top_txt = top + "'"; } //top texts on X separators if (step > 24) { paint.setStrokeWidth(1); paint.setColor(Color.LTGRAY); paint.setAntiAlias(false); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStopY, paint); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStartY - 4, paint); paint.setAntiAlias(true); paint.setStrokeWidth(0); paint.setColor(Color.parseColor("#157C9E")); paint.setTextSize(size10); can.drawText(top_txt, gridStartX + (i * step) - size7, gridStopY + gridOffset - size15, paint); } else if (step > 8 && (top == 3 || top == 6 || top == 9 || top == 12 || top == 15 || top == 18 || top == 21 || top == 0)) { paint.setStrokeWidth(1); paint.setColor(Color.LTGRAY); paint.setAntiAlias(false); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStopY, paint); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStartY - 4, paint); paint.setAntiAlias(true); paint.setStrokeWidth(0); paint.setColor(Color.parseColor("#157C9E")); can.drawText(top_txt, gridStartX + (i * step) - 8, gridStopY + gridOffset - 20, paint); } else if (step > 4 && (top == 6 || top == 12 || top == 18 || top == 0)) { paint.setStrokeWidth(1); paint.setColor(Color.LTGRAY); paint.setAntiAlias(false); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStopY, paint); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStartY - 4, paint); paint.setAntiAlias(true); paint.setStrokeWidth(0); paint.setColor(Color.parseColor("#157C9E")); can.drawText(top_txt, gridStartX + (i * step) - 8, gridStopY + gridOffset - 20, paint); } else if (step > 2 && (top == 12 || top == 0)) { paint.setStrokeWidth(1); paint.setColor(Color.LTGRAY); paint.setAntiAlias(false); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStopY, paint); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStartY - 4, paint); paint.setAntiAlias(true); paint.setStrokeWidth(0); paint.setColor(Color.parseColor("#157C9E")); can.drawText(top_txt, gridStartX + (i * step) - 8, gridStopY + gridOffset - 20, paint); } if (top == 0) { paint.setAntiAlias(false); paint.setColor(Color.parseColor("#AEB255")); can.drawLine(gridStartX + (i * step), gridStartY, gridStartX + (i * step), gridStopY, paint); } // bottom texts int bottom_val1 = 0; int bottom_val2 = 0; int hour = values.get(i + 1).get(4).intValue(); String bottom_txt = ""; if (limit == 6) { //day or week rythm = 1; bottom_val1 = values.get(i + 1).get(3).intValue(); //day bottom_val2 = values.get(i).get(1).intValue(); //month bottom_txt = Integer.toString(bottom_val1) + "/" + Integer.toString(bottom_val2); } else if (limit == 5) { //one month rythm = 3; bottom_val1 = values.get(i + 1).get(3).intValue(); //day bottom_val2 = values.get(i).get(1).intValue(); //month bottom_txt = Integer.toString(bottom_val1) + "/" + Integer.toString(bottom_val2); } else { //one year (by weeks ) if (values.size() < 18) //17 weeks rythm = 1; else if (values.size() < 36) //35 weeks rythm = 2; else rythm = 3; //full year bottom_val1 = values.get(i).get(0).intValue(); //year bottom_val2 = values.get(i + 1).get(2).intValue(); // week String tmp = Integer.toString(bottom_val1); tmp = tmp.substring(2); //Only keep last 2 digits bottom_txt = tmp + "/" + Integer.toString(bottom_val2); } // Intermediate points if (values.get(i).get(0).intValue() == 0 || values.get(i + 1).get(0).intValue() == 0) { paint.setColor(Color.RED); } else { paint.setColor(Color.parseColor("#157C9E")); paint.setStrokeWidth(4); can.drawPoint(gridStartX + (step * (i)), (gridStartY - gridOffset) - ((values.get(i).get(5)) - minf) * scale_values, paint); can.drawPoint(gridStartX + (step * (i + 1)), (gridStartY - gridOffset) - ((values.get(i + 1).get(5)) - minf) * scale_values, paint); } paint.setStrokeWidth(2); can.drawLine(gridStartX + (step * (i)), (gridStartY - gridOffset) - ((values.get(i).get(5)) - minf) * scale_values, gridStartX + (step * (i + 1)), (gridStartY - gridOffset) - ((values.get(i + 1).get(5)) - minf) * scale_values, paint); //text on X Axis if ((curr == 0) || (curr == rythm)) { if (hour == 0) { paint.setColor(Color.parseColor("#157C9E")); can.drawText(bottom_txt, gridStartX + ((i + 1) * step), gridStartY + gridOffset, paint); curr = 1; //to skip next draw } } else { curr++; //draw text skipped } } } public void updateTimer() { TimerTask doAsynchronousTask; final Timer timer = new Timer(); doAsynchronousTask = new TimerTask() { @Override public void run() { Runnable myTH = new Runnable() { //handler.post(new Runnable() { //Doume : to avoid Exception on ICS public void run() { try { if (activate) { new UpdateThread().execute(); } else { //Tracer.i(mytag+"("+dev_id+")","update Timer : Destroy runnable"); timer.cancel(); this.finalize(); } } catch (Throwable e) { e.printStackTrace(); } } } //) ; //Tracer.i(mytag,"TimerTask.run : Queuing Runnable for Device : "+dev_id); try { handler.post(myTH); //Doume : to avoid Exception on ICS } catch (Exception e) { e.printStackTrace(); } } //TimerTask Run method }; //TimerTask //timer.schedule(doAsynchronousTask, 0, update*10000); timer.schedule(doAsynchronousTask, 0, update * 1000); // Fix Doume } /* * Graphs are refreshed using a direct request to Domogik server */ private class UpdateThread extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... params) { if (!activate) return null; loaded = false; try { avgf = 0; values.clear(); long currentTimestamp = time_end.getTime() / 1000; long startTimestamp = time_start.getTime() / 1000; JSONObject json_GraphValues = null; try { if (api_version <= 0.6f) { Tracer.i(mytag, "UpdateThread (" + dev_id + ") : " + "stats/" + dev_id + "/" + state_key + "/from/" + startTimestamp + "/to/" + currentTimestamp + "/interval/" + step + "/selector/avg"); json_GraphValues = Rest_com.connect_jsonobject(activity, Tracer, "stats/" + dev_id + "/" + state_key + "/from/" + startTimestamp + "/to/" + currentTimestamp + "/interval/" + step + "/selector/avg", 30000); } else if (api_version >= 0.7f) { Tracer.i(mytag, "UpdateThread (" + id + ") : " + "sensorhistory/id/" + id + "/from/" + startTimestamp + "/to/" + currentTimestamp + "/interval/" + step + "/selector/avg"); //Don't forget old "dev_id"+"state_key" is replaced by "id" json_GraphValues = Rest_com.connect_jsonobject(activity, Tracer, "sensorhistory/id/" + id + "/from/" + startTimestamp + "/to/" + currentTimestamp + "/interval/" + step + "/selector/avg", 30000); } } catch (Exception e) { Tracer.d(mytag, "Could not get sensor history."); Tracer.d(mytag, e.toString()); return null; } //Tracer.d(mytag,"UpdateThread ("+dev_id+") Rinor result: "+json_GraphValues.toString()); //TODO //replace json_GraphValues.getJSONArray("stats") != null by something else as it may crash on a 0.4. //if(! ((json_GraphValues != null) && (json_GraphValues.getJSONArray("stats") != null))) { if (json_GraphValues == null) { //That seems to be a zombie loaded = false; handler.sendEmptyMessage(0); // To force a close of this instance return null; } Tracer.d(mytag, "UpdateThread (" + dev_id + ") Refreshing graph"); JSONArray itemArray = null; JSONArray valueArray = null; if (api_version <= 0.6f) { itemArray = json_GraphValues.getJSONArray("stats"); valueArray = itemArray.getJSONObject(0).getJSONArray("values"); } else if (api_version >= 0.7f) { valueArray = json_GraphValues.getJSONArray("values"); } //minf=(float)valueArray.getJSONArray(0).getDouble(limit-1); maxf = minf = 0; //Tracer.i(mytag,"UpdateThread ("+dev_id+") : array size "+valueArray.length()); for (int i = 0; i < valueArray.length(); i++) { // Create a vector with all entry components Vector<Float> vect = new Vector<>(); Double real_val = valueArray.getJSONArray(i).getDouble(limit - 1); // Get the real 'value' real_val = calcul.Round_double(real_val); if (limit == 6) { // stats per hour return [ year, month, week, day, hour, value] for (int j = 0; j < 6; j++) { vect.addElement((float) valueArray.getJSONArray(i).getDouble(j)); } } else if (limit == 5) { // stats per day return [year, month, week, day, value] for (int j = 0; j < 4; j++) { vect.addElement((float) valueArray.getJSONArray(i).getDouble(j)); } vect.addElement(0f); //null hour vect.addElement(real_val.floatValue()); } else { // stats per week return [ year, week, value ] Calendar date_value = Calendar.getInstance(); date_value.setTimeInMillis(0); date_value.set(Calendar.YEAR, (int) valueArray.getJSONArray(i).getDouble(0)); date_value.set(Calendar.WEEK_OF_YEAR, (int) valueArray.getJSONArray(i).getDouble(1)); Date loc_date = new Date(); loc_date.setTime(date_value.getTimeInMillis()); //Tracer.d(mytag,"Case week : Inserting value at "+sdf.format(loc_date)); vect.addElement((float) valueArray.getJSONArray(i).getDouble(0)); //year vect.addElement((float) loc_date.getMonth()); // month vect.addElement((float) valueArray.getJSONArray(i).getDouble(1)); //week vect.addElement((float) loc_date.getDay()); // day vect.addElement(0f); //null hour vect.addElement(real_val.floatValue()); } // each vector contains 6 floats values.add(vect); if (minf == 0) minf = real_val.floatValue(); avgf += real_val; // Get the real 'value' if (real_val > maxf) { maxf = real_val.floatValue(); } if (real_val < minf) { minf = real_val.floatValue(); } if (i < valueArray.length() - 1) { // It's not the last component int loc_hour, loc_hour_next = 0; int loc_day, loc_day_next = 0; int loc_week, loc_week_next = 0; int loc_year = 0; int loc_month = 0; float loc_value = 0; if (limit == 6) { // range between 1 to 8 days (average per hour) loc_year = (int) valueArray.getJSONArray(i).getDouble(0); loc_month = (int) valueArray.getJSONArray(i).getDouble(1); loc_week = (int) valueArray.getJSONArray(i).getDouble(2); loc_day = (int) valueArray.getJSONArray(i).getDouble(3); loc_hour = (int) valueArray.getJSONArray(i).getDouble(4); loc_hour_next = (int) valueArray.getJSONArray(i + 1).getDouble(4); loc_value = (float) valueArray.getJSONArray(i).getDouble(5); //Tracer.d(mytag,"Case hour : "+loc_year+" - "+loc_month+" - "+loc_week+" - "+loc_day+" - "+loc_hour+" - "+loc_value); if (loc_hour != 23 && (loc_hour < loc_hour_next)) { //no day change //Tracer.d(mytag,"Case hour 1 "); if ((loc_hour + 1) != loc_hour_next) { //ruptur : simulate next missing steps for (int k = 1; k < (loc_hour_next - loc_hour); k++) { Vector<Float> vect2 = new Vector<>(); vect2.addElement(0f); vect2.addElement((float) loc_month); //month vect2.addElement((float) loc_week); //week vect2.addElement((float) loc_day); //day vect2.addElement((float) loc_hour + k); //hour vect2.addElement(loc_value); //value values.add(vect2); //Tracer.e(mytag,"Case 1 : added : 0 - "+loc_month+" - "+loc_week+" - "+loc_day+" - "+(loc_hour+k)+" - "+loc_value); avgf += loc_value; //value } } } else { //Tracer.d(mytag,"Case hour 2 "); //if((loc_hour ==23) && (loc_hour_next != 0) ){ if (loc_hour == 23) { // day change : simulate missing steps //Tracer.d(mytag,"Case hour 2a "); for (int k = 0; k < loc_hour_next; k++) { Vector<Float> vect2 = new Vector<>(); vect2.addElement(0f); vect2.addElement((float) loc_month + 1); //month vect2.addElement((float) loc_week); //week vect2.addElement((float) loc_day + 1); // next day vect2.addElement((float) k); //simulated hour vect2.addElement(loc_value); //value values.add(vect2); //Tracer.e(mytag,"Case 2 : added : 0 - "+loc_month+" - "+loc_week+" - "+(loc_day+1)+" - "+k+" - "+loc_value); avgf += loc_value; //value } } } } else if (limit == 5) { // range between 9 to 32 days (average per day) loc_day_next = (int) valueArray.getJSONArray(i + 1).getDouble(limit - 2); loc_year = (int) valueArray.getJSONArray(i).getDouble(0); loc_month = (int) valueArray.getJSONArray(i).getDouble(1); loc_week = (int) valueArray.getJSONArray(i).getDouble(2); loc_day = (int) valueArray.getJSONArray(i).getDouble(3); loc_day_next = (int) valueArray.getJSONArray(i + 1).getDouble(3); loc_hour = 0; loc_value = (float) valueArray.getJSONArray(i).getDouble(4); //Tracer.d(mytag,"Case day : "+loc_year+" - "+loc_month+" - "+loc_week+" - "+loc_day+" - "+loc_value); //if(loc_day != 31 && (loc_day < loc_day_next) ) { if (loc_day < loc_day_next) { // month continues... //Tracer.d(mytag,"Case day 1 "); if ((loc_day + 1) != loc_day_next) { // but a hole exists : simulate missing days //Tracer.d(mytag,"Case day 1a "); for (int k = 1; k < (loc_day_next - loc_day); k++) { Vector<Float> vect2 = new Vector<>(); vect2.addElement(0f); vect2.addElement((float) loc_month); //month vect2.addElement((float) loc_week); //week vect2.addElement((float) (loc_day + k)); //day vect2.addElement((float) loc_hour); // = 0 vect2.addElement(loc_value); //value values.add(vect2); avgf += loc_value; //value } } } else { // next day being less than current day, month has changed ! //Tracer.d(mytag,"Case day 2 "); //if((loc_day == 31) && (loc_day_next != 0) ){ if (loc_day_next != 0) { //Tracer.d(mytag,"Case day 2a "); for (int k = 0; k < loc_day_next; k++) { Vector<Float> vect2 = new Vector<>(); vect2.addElement(0f); vect2.addElement((float) loc_month); //month vect2.addElement((float) loc_week); //week //vect2.addElement(0f); // no week in scale vect2.addElement((float) k); //day vect2.addElement((float) loc_hour); // = 0 vect2.addElement(loc_value); //value values.add(vect2); //Tracer.d(mytag,"Case day 2a with k="+k); avgf += loc_value; //value } } } } else if (limit == 3) { Calendar date_value = Calendar.getInstance(); date_value.setTimeInMillis(0); date_value.set(Calendar.YEAR, (int) valueArray.getJSONArray(i).getDouble(0)); date_value.set(Calendar.WEEK_OF_YEAR, (int) valueArray.getJSONArray(i).getDouble(1)); Date loc_date = new Date(); loc_date.setTime(date_value.getTimeInMillis()); // range of 1 year (average per week) loc_year = (int) valueArray.getJSONArray(i).getDouble(0); loc_month = loc_date.getMonth(); // month loc_week = (int) valueArray.getJSONArray(i).getDouble(1); loc_week_next = (int) valueArray.getJSONArray(i + 1).getDouble(1); loc_day = loc_date.getDate(); loc_day_next = 0; loc_hour = loc_date.getHours(); loc_value = (float) valueArray.getJSONArray(i).getDouble(2); //Tracer.d(mytag,"Case week : "+loc_year+" - "+loc_week+" - "+loc_value); if (loc_week != 52 && (loc_week < loc_week_next)) { if ((loc_week + 1) != loc_week_next) { // Changing year for (int k = 1; k < (loc_week_next - loc_week); k++) { Vector<Float> vect2 = new Vector<>(); //vect2.addElement((float)loc_year); //year vect2.addElement(0f); vect2.addElement((float) loc_month); //month vect2.addElement((float) (loc_week + k)); //week vect2.addElement((float) loc_day); //day vect2.addElement(0f); //hour vect2.addElement(loc_value); //value values.add(vect2); avgf += loc_value; //value } } } if ((loc_week == 52) && (loc_week_next != 0)) { //last week of the year for (int k = 0; k < loc_week_next; k++) { Vector<Float> vect2 = new Vector<>(); //vect2.addElement((float)loc_year); //year vect2.addElement(0f); vect2.addElement((float) loc_month); //month vect2.addElement((float) k); //week vect2.addElement((float) loc_day); //day vect2.addElement(0f); //hour vect2.addElement(loc_value); //value values.add(vect2); avgf += valueArray.getJSONArray(i).getDouble(limit - 1); //value } } } } } } catch (Exception e) { e.printStackTrace(); } avgf = avgf / values.size(); avgf = calcul.Round_float(avgf, 2); gridStartX = Float.toString(maxf).length() * size7; if (Float.toString(minf).length() * size7 > gridStartX) gridStartX = Float.toString(minf).length() * size7; if (Float.toString(avgf).length() * size7 > gridStartX) gridStartX = Float.toString(avgf).length() * size7; gridStopX = width - gridStartX; loaded = true; handler.sendEmptyMessage(0); return null; } } private void compute_period() { long duration = 0; //Calendar cal = Calendar.getInstance(); // The 'now' time switch (period_type) { case -1: //user requires the 'Prev' period period_type = sav_period; duration = 86400l * 1000l * period_type; if (time_end != null) { long new_end = time_end.getTime(); new_end -= duration; time_end.setTime(new_end); new_end -= duration; time_start.setTime(new_end); } //Tracer.i(mytag,"type prev on "+period_type+" Begin at :"+sdf.format(time_start)+" End at : "+sdf.format(time_end)); break; case 0: //user requires the 'Next' period period_type = sav_period; duration = 86400l * 1000l * period_type; if (time_start != null) { long new_start = time_start.getTime(); new_start += duration; time_start.setTime(new_start); new_start += duration; time_end.setTime(new_start); } long new_start = time_start.getTime(); long new_end = time_end.getTime(); long now = System.currentTimeMillis(); if (new_end > now) { time_end.setTime(now); double new_timestamp = now - duration; new_start = (long) new_timestamp; time_start.setTime(new_start); } //Tracer.i(mytag,"type next on "+period_type+" Begin at :"+sdf.format(time_start)+" End at : "+sdf.format(time_end)); break; default: //period_type indicates the number of days to graph // relative to 'now' date duration = 86400l * 1000l * period_type; long new_end_time = System.currentTimeMillis(); time_end.setTime(new_end_time); //Get actual system time new_end_time -= duration; time_start.setTime(new_end_time); //Tracer.i(mytag,"type = "+period_type+" Begin at :"+sdf.format(time_start)+" End at : "+sdf.format(time_end)); break; } // time_start & time_end are set.... display_dates(); if (period_type < 9) { step = "hour"; limit = 6; } else if (period_type < 32) { step = "day"; limit = 5; } else { step = "week"; limit = 3; } } private void display_dates() { if (dates != null) { dates.setText(getContext().getText(R.string.from) + " " + sdf.format(time_start) + " " + getContext().getText(R.string.to) + " " + sdf.format(time_end)); } } }