/*
CanZE
Take a closer look at your ZE car
Copyright (C) 2015 - The CanZE Team
http://canze.fisch.lu
This program 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 any
later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package lu.fisch.canze.activities;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TextView;
import java.util.Locale;
import lu.fisch.canze.R;
import lu.fisch.canze.actors.Field;
import lu.fisch.canze.interfaces.DebugListener;
import lu.fisch.canze.interfaces.FieldListener;
// If you want to monitor changes, you must add a FieldListener to the fields.
// For the simple activity, the easiest way is to implement it in the actitviy itself.
public class ChargingTechActivity extends CanzeActivity implements FieldListener, DebugListener {
public static final String SID_MaxCharge = "7bb.6101.336";
public static final String SID_UserSoC = "42e.0"; // user SOC, not raw
// public static final String SID_RealSoC = "654.25"; // real SOC
public static final String SID_AvailableChargingPower = "427.40";
public static final String SID_ACPilot = "42e.38";
public static final String SID_AvEnergy = "427.49";
public static final String SID_TimeToFull = "654.32";
public static final String SID_PlugConnected = "654.2";
public static final String SID_SOH = "7ec.623206.24";
public static final String SID_RangeEstimate = "654.42";
public static final String SID_ChargingStatusDisplay = "65b.41";
public static final String SID_TractionBatteryVoltage = "7ec.623203.24";
public static final String SID_TractionBatteryCurrent = "7ec.623204.24";
public static final String SID_EnergyConsumed = "7ec.6233dc.24";
// public static final String SID_CapacityFluKan = "7bb.6101.348";
// public static final String SID_CapacityZoe = "";
public static final String SID_RealSoC = "7bb.6103.192";
public static final String SID_12V = "7ec.622005.24";
public static final String SID_12A = "7ec.623028.24";
public static final String SID_DcLoad = "1fd.0";
public static final String SID_HvKilometers = "7bb.6161.96";
public static final String SID_Preamble_CompartmentTemperatures = "7bb.6104."; // (LBC)
public static final String SID_Preamble_BalancingBytes = "7bb.6107.";
public static final String DefaultFormatTemperature = "%3.0f";
public static final String DefaultFormatBalancing = "%02X";
//public static final String cha_Status [] = {"No charge", "Waiting (planned)", "Ended", "In progress", "Failure", "Waiting", "Flap open", "Unavailable"};
final String charging_Status [] = MainActivity.getStringList(R.array.list_ChargingStatus);
//public static final String plu_Status [] = {"Not connected", "Connected"};
final String plug_Status [] = MainActivity.getStringList(R.array.list_PlugStatus);
double dcVolt = 0; // holds the DC voltage, so we can calculate the power when the amps come in
double pilot = 0;
int chargingStatus = 7;
double soc = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chargingtech);
}
protected void initListeners() {
MainActivity.getInstance().setDebugListener(this);
addField(SID_MaxCharge);
addField(SID_ACPilot);
addField(SID_TimeToFull);
addField(SID_PlugConnected);
addField(SID_UserSoC);
addField(SID_RealSoC);
if (MainActivity.isZOE()) {
addField(SID_AvailableChargingPower);
//} else {
// addFields(SID_CapacityFluKan);
}
addField(SID_AvEnergy);
addField(SID_SOH); // state of health gives continious timeouts. This frame is send at a very low rate
addField(SID_RangeEstimate);
addField(SID_12V);
addField(SID_12A);
addField(SID_DcLoad);
addField(SID_HvKilometers);
addField(SID_EnergyConsumed);
addField(SID_ChargingStatusDisplay);
addField(SID_TractionBatteryVoltage);
addField(SID_TractionBatteryCurrent);
// Battery compartment temperatures
int lastCell = MainActivity.isZOE() ? 12 : 4;
for (int i = 0; i < lastCell; i++) {
String sid = SID_Preamble_CompartmentTemperatures + (32 + i * 24);
addField(sid);
if (MainActivity.isZOE()) sid = SID_Preamble_BalancingBytes + (16 + i * 8);
addField(sid);
}
}
// This is the event fired as soon as this the registered fields are
// getting updated by the corresponding reader class.
@Override
public void onFieldUpdateEvent(final Field field) {
// the update has to be done in a separate thread
// otherwise the UI will not be repainted
runOnUiThread(new Runnable() {
@Override
public void run() {
String fieldId = field.getSID();
TextView tv = null;
// get the text field
switch (fieldId) {
case SID_MaxCharge:
tv = (TextView) findViewById(R.id.text_max_charge);
break;
case SID_ACPilot:
// save pilot amps
pilot = field.getValue();
if (MainActivity.isFluKan ()) { // for FluKan, aproximate phases (always 1) and AvChPwr (amps * 0.225)
double avChPwr = (double) Math.round(pilot * 2.25) / 10.0;
tv = (TextView) findViewById(R.id.textPhases);
tv.setText("1");
tv = (TextView) findViewById(R.id.textAvChPwr);
tv.setText(String.format(Locale.getDefault(), "%.1f", avChPwr));
}
// continue
tv = (TextView) findViewById(R.id.text_max_pilot);
if (chargingStatus != 3 && MainActivity.isZOE()) {
tv.setText("-");
tv = null;
}
break;
case SID_TimeToFull: // time to full
tv = (TextView) findViewById(R.id.textTTF);
if (field.getValue() >= 1023) {
tv.setText("--:--");
} else {
tv.setText(String.format(Locale.getDefault(), "%.0f", field.getValue()));
}
tv = null;
break;
case SID_UserSoC:
soc = field.getValue() / 100.0;
tv = (TextView) findViewById(R.id.textUserSOC);
break;
case SID_RealSoC:
soc = field.getValue() / 100.0;
tv = (TextView) findViewById(R.id.textRealSOC);
break;
case SID_SOH:
tv = (TextView) findViewById(R.id.textSOH);
tv.setText(String.format(Locale.getDefault(), "%.0f", field.getValue()));
tv = null;
break;
case SID_RangeEstimate:
tv = (TextView) findViewById(R.id.textKMA);
if (field.getValue() >= 1023) {
tv.setText("---");
} else {
tv.setText(String.format(Locale.getDefault(), "%.0f", field.getValue()));
}
tv = null;
break;
case SID_TractionBatteryVoltage: // DC volts
// save DC voltage for DC power purposes
dcVolt = field.getValue();
// continue
tv = (TextView) findViewById(R.id.textVolt);
break;
case SID_TractionBatteryCurrent: // DC amps
// calculate DC power
double dcPwr = (double)Math.round(dcVolt * field.getValue() / 100.0) / 10.0;
tv = (TextView) findViewById(R.id.textDcPwr);
tv.setText(String.format(Locale.getDefault(), "%.1f", dcPwr));
// continue
tv = (TextView) findViewById(R.id.textAmps);
break;
case SID_AvailableChargingPower: // won't be called for FluKan
double avChPwr = field.getValue();
tv = (TextView) findViewById(R.id.textPhases);
if (pilot == 0) {
tv.setText("-");
} else if (avChPwr > (pilot * 0.250)) {
tv.setText("3");
} else {
tv.setText("1");
}
tv = (TextView) findViewById(R.id.textAvChPwr);
break;
case SID_AvEnergy:
if (soc > 0) {
tv = (TextView) findViewById(R.id.textETF);
tv.setText(String.format(Locale.getDefault(), "%.1f", field.getValue() * (1-soc) / soc));
//tv.setText("" + (Math.round((field.getValue() * (1-soc) / soc) * 10.0) / 10.0));
}
tv = (TextView) findViewById(R.id.textAvEner);
break;
case SID_12V:
tv = (TextView) findViewById(R.id.text12V);
break;
case SID_12A:
tv = (TextView) findViewById(R.id.text12A);
break;
case SID_DcLoad:
tv = (TextView) findViewById(R.id.textDcLoad);
break;
case SID_HvKilometers:
tv = (TextView) findViewById(R.id.textHKM);
tv.setText(String.format(Locale.getDefault(), "%.0f", field.getValue()));
tv = null;
break;
case SID_EnergyConsumed:
tv = (TextView) findViewById(R.id.textENC);
break;
//case SID_CapacityFluKan:
//case SID_CapacityZoe:
// tv = (TextView) findViewById(R.id.textCapacity);
// tv.setText("" + field.getValue());
// tv = null;
// break;
case SID_ChargingStatusDisplay:
chargingStatus = (int) field.getValue();
tv = (TextView) findViewById(R.id.textChaStatus);
tv.setText(charging_Status[chargingStatus]);
tv = null;
break;
case SID_PlugConnected:
tv = (TextView) findViewById(R.id.textPlug);
tv.setText(plug_Status[(int) field.getValue()]);
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "32":
tv = (TextView) findViewById(R.id.text_comp_1_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "56":
tv = (TextView) findViewById(R.id.text_comp_2_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "80":
tv = (TextView) findViewById(R.id.text_comp_3_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "104":
tv = (TextView) findViewById(R.id.text_comp_4_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "128":
tv = (TextView) findViewById(R.id.text_comp_5_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "152":
tv = (TextView) findViewById(R.id.text_comp_6_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "176":
tv = (TextView) findViewById(R.id.text_comp_7_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "200":
tv = (TextView) findViewById(R.id.text_comp_8_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "224":
tv = (TextView) findViewById(R.id.text_comp_9_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "248":
tv = (TextView) findViewById(R.id.text_comp_10_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "272":
tv = (TextView) findViewById(R.id.text_comp_11_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_CompartmentTemperatures + "296":
tv = (TextView) findViewById(R.id.text_comp_12_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatTemperature, field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "16":
tv = (TextView) findViewById(R.id.text_bala_1_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "24":
tv = (TextView) findViewById(R.id.text_bala_2_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "32":
tv = (TextView) findViewById(R.id.text_bala_3_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "40":
tv = (TextView) findViewById(R.id.text_bala_4_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "48":
tv = (TextView) findViewById(R.id.text_bala_5_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "56":
tv = (TextView) findViewById(R.id.text_bala_6_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "64":
tv = (TextView) findViewById(R.id.text_bala_7_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "72":
tv = (TextView) findViewById(R.id.text_bala_8_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "80":
tv = (TextView) findViewById(R.id.text_bala_9_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "88":
tv = (TextView) findViewById(R.id.text_bala_10_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "96":
tv = (TextView) findViewById(R.id.text_bala_11_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
case SID_Preamble_BalancingBytes + "104":
tv = (TextView) findViewById(R.id.text_bala_12_temp);
tv.setText(String.format(Locale.getDefault(), DefaultFormatBalancing, (int)field.getValue()));
tv = null;
break;
}
// set regular new content, all exeptions handled above
if (tv != null) {
double val = field.getValue();
tv.setText(Double.isNaN(val) ? "" : String.format(Locale.getDefault(), "%.1f", val));
}
}
});
}
}