Marstek B2500: decode more unknown values, display temperature values in activity

This commit is contained in:
Andreas Shimokawa 2025-01-02 00:15:07 +01:00
parent 559ccda676
commit e661a4661a
4 changed files with 63 additions and 18 deletions

View File

@ -599,7 +599,7 @@ public class DeviceSettingsPreferenceConst {
public static final String PREF_BATTERY_DISCHARGE_INTERVAL4_WATT = "battery_discharge_interval4_watt";
public static final String PREF_BATTERY_DISCHARGE_INTERVAL5_WATT = "battery_discharge_interval5_watt";
public static final String PREF_BATTERY_DISCHARGE_INTERVALS_SET = "battery_discharge_intervals_set";
public static final String PREF_BATTERY_DISCHARGE_MANAUAL = "battery_discharge_manual";
public static final String PREF_BATTERY_DISCHARGE_MANUAL = "battery_discharge_manual";
public static final String PREF_BATTERY_MINIMUM_CHARGE = "battery_minimum_charge";
public static final String PREF_BATTERY_ALLOW_PASS_THOUGH = "battery_allow_pass_though";
public static final String PREF_BATTERY_ALLOW_PASS_THROUGH = "battery_allow_pass_though";
}

View File

@ -42,7 +42,6 @@ import android.media.AudioManager;
import android.os.Bundle;
import android.text.InputType;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
@ -884,7 +883,7 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
addPreferenceHandlerFor("lock");
addPreferenceHandlerFor(PREF_BATTERY_MINIMUM_CHARGE);
addPreferenceHandlerFor(PREF_BATTERY_ALLOW_PASS_THOUGH);
addPreferenceHandlerFor(PREF_BATTERY_ALLOW_PASS_THROUGH);
final Preference dischargeIntervalsSet = findPreference(PREF_BATTERY_DISCHARGE_INTERVALS_SET);
if (dischargeIntervalsSet != null) {

View File

@ -53,6 +53,8 @@ public class SolarEquipmentStatusActivity extends AbstractGBActivity {
public static String EXTRA_PANEL2_WATT = "panel2_watt";
public static String EXTRA_OUTPUT1_WATT = "output1_watt";
public static String EXTRA_OUTPUT2_WATT = "output2_watt";
public static String EXTRA_TEMP1 = "temp1";
public static String EXTRA_TEMP2 = "temp2";
private final Map<String, View> widgetMap = new HashMap<>();
private GridLayout gridLayout;
@ -68,11 +70,15 @@ public class SolarEquipmentStatusActivity extends AbstractGBActivity {
int battery_wh = extras.getInt(EXTRA_BATTERY_WH);
int panel1_watt = extras.getInt(EXTRA_PANEL1_WATT);
int panel2_watt = extras.getInt(EXTRA_PANEL2_WATT);
int temp1 = extras.getInt(EXTRA_TEMP1);
int temp2 = extras.getInt(EXTRA_TEMP2);
int output1_watt = extras.getInt(EXTRA_OUTPUT1_WATT);
int output2_watt = extras.getInt(EXTRA_OUTPUT2_WATT);
updateWidget("battery", battery_pct + "%\n" + battery_wh + "Wh", (float) (battery_pct / 100.0));
updateWidget("panel1", panel1_watt + "W", (float) (panel1_watt / 380.0));
updateWidget("panel2", panel2_watt + "W", (float) (panel2_watt / 380.0));
updateWidget("temp1", temp1 + "°C", (float) ((temp1 + 20) / 100.0));
updateWidget("temp2", temp2 + "°C", (float) ((temp2 + 20) / 100.0));
updateWidget("output1", output1_watt + "W", (float) (output1_watt / 400.0));
updateWidget("output2", output2_watt + "W", (float) (output2_watt / 400.0));
@ -92,6 +98,16 @@ public class SolarEquipmentStatusActivity extends AbstractGBActivity {
};
}
public static int[] getColorsTemp() {
return new int[]{
ContextCompat.getColor(GBApplication.getContext(), R.color.calories_resting_color),
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_excellent_color),
ContextCompat.getColor(GBApplication.getContext(), R.color.body_energy_level_color),
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_fair_color),
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_poor_color),
};
}
public static int[] getColorsOutput() {
return new int[]{
ContextCompat.getColor(GBApplication.getContext(), R.color.chart_stress_unknown),
@ -110,6 +126,16 @@ public class SolarEquipmentStatusActivity extends AbstractGBActivity {
};
}
public static float[] getSegmentsTemp() {
return new float[]{
0.2f,
0.1f,
0.2f,
0.3f,
0.2f,
};
}
public static float[] getSegmentsOutput() {
return new float[]{
0.01f,
@ -126,7 +152,13 @@ public class SolarEquipmentStatusActivity extends AbstractGBActivity {
gaugeValue.setText(value);
GaugeDrawer gaugeDrawer = new GaugeDrawer();
ImageView gaugeBar = view.findViewById(R.id.gauge_bar);
gaugeDrawer.drawSegmentedGauge(gaugeBar, name.startsWith("output") ? getColorsOutput() : getColors(), name.startsWith("output") ? getSegmentsOutput() : getSegments(), gaugeFill, true, false);
if (name.startsWith("output")) {
gaugeDrawer.drawSegmentedGauge(gaugeBar, getColorsOutput(), getSegmentsOutput(), gaugeFill, true, false);
} else if (name.startsWith("temp")) {
gaugeDrawer.drawSegmentedGauge(gaugeBar, getColorsTemp(), getSegmentsTemp(), gaugeFill, true, false);
} else {
gaugeDrawer.drawSegmentedGauge(gaugeBar, getColors(), getSegments(), gaugeFill, true, false);
}
}
}
@ -142,6 +174,8 @@ public class SolarEquipmentStatusActivity extends AbstractGBActivity {
createWidget("panel1", "Panel 1", 1);
createWidget("panel2", "Panel 2", 1);
createWidget("battery", "Battery", 2);
createWidget("temp1", "Temp 1", 1);
createWidget("temp2", "Temp 2", 1);
createWidget("output1", "Output 1", 1);
createWidget("output2", "Output 2", 1);

View File

@ -16,9 +16,9 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.marstek;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BATTERY_ALLOW_PASS_THOUGH;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BATTERY_ALLOW_PASS_THROUGH;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BATTERY_DISCHARGE_INTERVALS_SET;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BATTERY_DISCHARGE_MANAUAL;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BATTERY_DISCHARGE_MANUAL;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BATTERY_MINIMUM_CHARGE;
import android.bluetooth.BluetoothGatt;
@ -157,7 +157,7 @@ public class MarstekB2500DeviceSupport extends AbstractBTLEDeviceSupport {
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()));
switch (config) {
case PREF_BATTERY_DISCHARGE_INTERVALS_SET:
if (devicePrefs.getBoolean(PREF_BATTERY_DISCHARGE_MANAUAL, true)) {
if (devicePrefs.getBoolean(PREF_BATTERY_DISCHARGE_MANUAL, true)) {
sendCommand("set discharge intervals", encodeDischargeIntervalsFromPreferences());
} else {
sendCommand("set dynamic discharge", COMMAND_SET_AUTO_DISCHARGE);
@ -167,8 +167,8 @@ public class MarstekB2500DeviceSupport extends AbstractBTLEDeviceSupport {
case PREF_BATTERY_MINIMUM_CHARGE:
sendCommand("set minimum charge", encodeMinimumChargeFromPreferences());
return;
case PREF_BATTERY_ALLOW_PASS_THOUGH:
if (devicePrefs.getBoolean(PREF_BATTERY_ALLOW_PASS_THOUGH, true)) {
case PREF_BATTERY_ALLOW_PASS_THROUGH:
if (devicePrefs.getBoolean(PREF_BATTERY_ALLOW_PASS_THROUGH, true)) {
sendCommand("set allow pass-though", COMMAND_SET_BATTERY_ALLOW_PASS_THOUGH);
} else {
sendCommand("set disallow pass-though", COMMAND_SET_BATTERY_DISALLOW_PASS_THOUGH);
@ -189,18 +189,29 @@ public class MarstekB2500DeviceSupport extends AbstractBTLEDeviceSupport {
boolean p2_active = buf.get() != 0x00;
int p1_watt = buf.getShort();
int p2_watt = buf.getShort();
buf.position(buf.position() + 2); // unknown;
int battery_pct = buf.getShort() / 10;
firmwareVersion = buf.get() & 0xff;
boolean battery_allow_passthrough = buf.get() != 0x01;
boolean battery_manual_discharge_intervals = buf.get() != 0x01;
buf.position(buf.position() + 3); // skip unknown
buf.position(buf.position() + 1); // skip unknown
boolean output1_active = buf.get() != 0x00;
boolean output2_active = buf.get() != 0x00;
byte battery_max_use_pct = buf.get();
int output_to_inverter_target = buf.getShort();
buf.position(buf.position() + 1); // skip unknown
int light_condition = buf.get(); // 1 = low light or none, 2 = some light, 0 = good light condition (?)
int battery_wh = buf.getShort();
int output_to_inverter_1_watt = buf.getShort();
int output_to_inverter_2_watt = buf.getShort();
buf.position(buf.position() + 3); // skip unknown
int hour_utc = buf.get();
int minute_utc = buf.get();
int temperature_sensor_1 = buf.getShort();
int temperature_sensor_2 = buf.getShort();
buf.position(buf.position() + 3); // skip unknown
int battery_charging_wh_24h = buf.getInt();
int battery_discharging_wh_24h = buf.getInt();
int input_wh_last_24h = buf.getInt();
int output_wh_last_24h = buf.getInt();
int battery_minimum_charge_pct = 100 - battery_max_use_pct;
int output_to_inverter_sum_watt = output_to_inverter_1_watt + output_to_inverter_2_watt;
@ -212,12 +223,11 @@ public class MarstekB2500DeviceSupport extends AbstractBTLEDeviceSupport {
getDevice().sendDeviceUpdateIntent(getContext());
devicePrefsEdit.putString(PREF_BATTERY_MINIMUM_CHARGE, String.valueOf(battery_minimum_charge_pct));
devicePrefsEdit.putBoolean(PREF_BATTERY_DISCHARGE_MANAUAL, battery_manual_discharge_intervals);
devicePrefsEdit.putBoolean(PREF_BATTERY_ALLOW_PASS_THOUGH, battery_allow_passthrough);
devicePrefsEdit.putBoolean(PREF_BATTERY_DISCHARGE_MANUAL, battery_manual_discharge_intervals);
devicePrefsEdit.putBoolean(PREF_BATTERY_ALLOW_PASS_THROUGH, battery_allow_passthrough);
devicePrefsEdit.apply();
devicePrefsEdit.commit();
int battery_pct = (int) Math.ceil((battery_wh / 2240.0f) * 100);
getDevice().setBatteryLevel(battery_pct);
getDevice().sendDeviceUpdateIntent(getContext());
@ -226,6 +236,8 @@ public class MarstekB2500DeviceSupport extends AbstractBTLEDeviceSupport {
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_BATTERY_PCT, battery_pct);
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_PANEL1_WATT, p1_watt);
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_PANEL2_WATT, p2_watt);
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_TEMP1, temperature_sensor_1);
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_TEMP2, temperature_sensor_2);
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_OUTPUT1_WATT, output_to_inverter_1_watt);
intent.putExtra(SolarEquipmentStatusActivity.EXTRA_OUTPUT2_WATT, output_to_inverter_2_watt);
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
@ -307,7 +319,7 @@ public class MarstekB2500DeviceSupport extends AbstractBTLEDeviceSupport {
private byte[] encodeDischargeIntervalsFromPreferences() {
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()));
if (devicePrefs.getBoolean(PREF_BATTERY_DISCHARGE_MANAUAL, true)) {
if (devicePrefs.getBoolean(PREF_BATTERY_DISCHARGE_MANUAL, true)) {
int nr_invervals = (firmwareVersion >= 220) ? 5 : 3; // old firmware V210 only had 3 intervals it seems, so set only 3
int length = 5 + nr_invervals * 7;