diff --git a/app/build.gradle b/app/build.gradle
index eca612e..5a0a807 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -12,8 +12,8 @@ android {
applicationId "org.woheller69.solxpect"
minSdkVersion 26
targetSdkVersion 31
- versionCode 11
- versionName "1.1"
+ versionCode 12
+ versionName "1.2"
buildConfigField "String", "BASE_URL", "\"https://api.open-meteo.com/v1/\""
buildConfigField "String", "GITHUB_URL","\"https://github.com/woheller69/solxpect/\""
diff --git a/app/src/main/assets/help/help-de.html b/app/src/main/assets/help/help-de.html
index fd26d8e..d615019 100644
--- a/app/src/main/assets/help/help-de.html
+++ b/app/src/main/assets/help/help-de.html
@@ -28,8 +28,11 @@
Zellen max. Leistung [W]
Zelleneffizienz [%]
Energieanteil in Form von Sonnenlicht, der von der Solarzelle in Strom umgewandelt werden kann.
+Temperaturkoeffizient [%/K]
+Abhängigkeit der Leistung der Solarmodule von der Temperatur (normalerweise im Bereich von -0.4%/K).
+
Zellenfläche [m2]
-Größe der aktiven Fläche Ihres Solarpanels.
+Fläche Ihres Solarpanels.
Diffuse Strahlungseffizienz [%]
Wirkungsgrad Ihres Solarkraftwerks bei diffuser Strahlung. Bei der Ausrichtung nach oben sollte er etwa 100 % betragen, bei der Ausrichtung zum Horizont etwa 50 %.
diff --git a/app/src/main/assets/help/help-en.html b/app/src/main/assets/help/help-en.html
index a7437a4..9c54d80 100644
--- a/app/src/main/assets/help/help-en.html
+++ b/app/src/main/assets/help/help-en.html
@@ -28,8 +28,11 @@ Cells max power [W]
Cells efficiency [%]
Portion of energy in the form of sunlight that can be converted into electricity by the solar cell.
+Temperature coefficient [%/K]
+Dependence of the cell power on temperature (usually in the range of -0.4%/K).
+
Cell area [m2]
-Size of the active area your solar panel.
+Size of your solar panel.
Diffuse radiation efficiency [%]
Efficiency of your solar power plant for diffuse radiation. When pointing up it should be around 100%, when pointing to the horizon it may be around 50%.
diff --git a/app/src/main/java/org/woheller69/weather/SolarPowerPlant.java b/app/src/main/java/org/woheller69/weather/SolarPowerPlant.java
index d4a0d55..d893bc1 100644
--- a/app/src/main/java/org/woheller69/weather/SolarPowerPlant.java
+++ b/app/src/main/java/org/woheller69/weather/SolarPowerPlant.java
@@ -14,6 +14,7 @@ public class SolarPowerPlant {
double cellsMaxPower;
double cellsArea;
double cellsEfficiency;
+ double cellsTempCoeff;
double diffuseEfficiency;
double inverterPowerLimit;
double inverterEfficiency;
@@ -22,7 +23,7 @@ public class SolarPowerPlant {
private int[] shadingElevation;
private int[] shadingOpacity;
- public SolarPowerPlant(double latitude, double longitude, double cellsMaxPower, double cellsArea, double cellsEfficiency, double diffuseEfficiency, double inverterPowerLimit, double inverterEfficiency, double azimuthAngle, double tiltAngle, int[] shadingElevation, int[] shadingOpacity ) {
+ public SolarPowerPlant(double latitude, double longitude, double cellsMaxPower, double cellsArea, double cellsEfficiency, double cellsTempCoeff, double diffuseEfficiency, double inverterPowerLimit, double inverterEfficiency, double azimuthAngle, double tiltAngle, int[] shadingElevation, int[] shadingOpacity ) {
this.latitude = latitude;
this.longitude = longitude;
this.cellsMaxPower = cellsMaxPower;
@@ -35,10 +36,11 @@ public SolarPowerPlant(double latitude, double longitude, double cellsMaxPower,
this.tiltAngle = tiltAngle;
this.shadingElevation = shadingElevation;
this.shadingOpacity = shadingOpacity;
+ this.cellsTempCoeff = cellsTempCoeff / 100;
}
- public float getPower(double solarPowerNormal, double solarPowerDiffuse, long epochTimeSeconds) {
+ public float getPower(double solarPowerNormal, double solarPowerDiffuse, long epochTimeSeconds, float ambientTemperature) {
Instant i = Instant.ofEpochSecond(epochTimeSeconds); //currentTimeMillis is in GMT
ZonedDateTime dateTime = ZonedDateTime.ofInstant(i, ZoneId.of("GMT"));
@@ -70,10 +72,23 @@ public float getPower(double solarPowerNormal, double solarPowerDiffuse, long ep
}
}
}
- double dcPower = (solarPowerNormal * efficiency + solarPowerDiffuse * diffuseEfficiency )* cellsEfficiency * cellsArea;
+
+ float totalRadiationOnCell = (float) (solarPowerNormal * efficiency + solarPowerDiffuse * diffuseEfficiency); //flat plate equivalent of the solar irradiance
+ float cellTemperature = calcCellTemperature(ambientTemperature,totalRadiationOnCell);
+
+ double dcPower = totalRadiationOnCell * cellsEfficiency * (1+(cellTemperature - 25)*cellsTempCoeff) * cellsArea;
double acPower = Math.min(dcPower * inverterEfficiency, inverterPowerLimit);
return (float) acPower;
}
+
+ public static float calcCellTemperature(float ambientTemperature, float totalIrradiance){
+ //models from here: https://www.scielo.br/j/babt/a/FBq5Pmm4gSFqsfh3V8MxfGN/ Photovoltaic Cell Temperature Estimation for a Grid-Connect Photovoltaic Systems in Curitiba
+ //float cellTemperature = 30.006f + 0.0175f*(totalIrradiance-300f)+1.14f*(ambientTemperature-25f); //Lasnier and Ang Lasnier, F.; Ang, T. G. Photovoltaic engineering handbook, 1st ed.; IOP Publishing LTD: Lasnier, France, 1990; pp. 258.
+ //float cellTemperature = ambientTemperature + 0.028f*totalIrradiance-1f; //Schott Schott, T. Operation temperatures of PV modules. Photovoltaic solar energy conference 1985, pp. 392-396.
+ float cellTemperature = ambientTemperature + 0.0342f*totalIrradiance; //Ross model: https://www.researchgate.net/publication/275438802_Thermal_effects_of_the_extended_holographic_regions_for_holographic_planar_concentrator
+ //assuming "not so well cooled" : 0.0342
+ return cellTemperature;
+ }
}
diff --git a/app/src/main/java/org/woheller69/weather/activities/ManageLocationsActivity.java b/app/src/main/java/org/woheller69/weather/activities/ManageLocationsActivity.java
index 333df47..8bfaa41 100644
--- a/app/src/main/java/org/woheller69/weather/activities/ManageLocationsActivity.java
+++ b/app/src/main/java/org/woheller69/weather/activities/ManageLocationsActivity.java
@@ -187,6 +187,7 @@ private void editCityToWatch(CityToWatch city) {
EditText editCellsMaxPower = (EditText) dialogView.findViewById(R.id.EditLocation_Cell_Max_Power);
EditText editCellsArea = (EditText) dialogView.findViewById(R.id.EditLocation_Cells_Area);
EditText editCellsEfficiency = (EditText) dialogView.findViewById(R.id.EditLocation_Cell_Efficiency);
+ EditText editCellsTempCoeff = (EditText) dialogView.findViewById(R.id.EditLocation_Cell_Temp_Coeff);
EditText editDiffuseEfficiency = (EditText) dialogView.findViewById(R.id.EditLocation_Diffuse_Efficiency);
EditText editInverterPowerLimit = (EditText) dialogView.findViewById(R.id.EditLocation_Inverter_Power_Limit);
EditText editInverterEfficiency = (EditText) dialogView.findViewById(R.id.EditLocation_Inverter_Efficiency);
@@ -204,6 +205,8 @@ private void editCityToWatch(CityToWatch city) {
editCellsArea.setText(Float.toString(city.getCellsArea()));
editCellsEfficiency.setText(Float.toString(city.getCellsEfficiency()));
editCellsEfficiency.setFilters(new InputFilter[]{ new InputFilterMinMax(0, 100)});
+ editCellsTempCoeff.setText(Float.toString(city.getCellsTempCoeff()));
+ editCellsTempCoeff.setFilters(new InputFilter[]{ new InputFilterMinMax(-100, 100)});
editDiffuseEfficiency.setText(Float.toString(city.getDiffuseEfficiency()));
editDiffuseEfficiency.setFilters(new InputFilter[]{ new InputFilterMinMax(0, 100)});
editInverterPowerLimit.setText(Float.toString(city.getInverterPowerLimit()));
@@ -237,6 +240,7 @@ public void afterTextChanged(Editable editable) {
Float.parseFloat(editCellsMaxPower.getText().toString().isEmpty() ? "0" : editCellsMaxPower.getText().toString()),
Float.parseFloat(editCellsArea.getText().toString().isEmpty() ? "0" : editCellsArea.getText().toString()),
Float.parseFloat(editCellsEfficiency.getText().toString().isEmpty() ? "0" : editCellsEfficiency.getText().toString()),
+ Float.parseFloat(editCellsTempCoeff.getText().toString().isEmpty() ? "0" : editCellsTempCoeff.getText().toString()),
Float.parseFloat(editDiffuseEfficiency.getText().toString().isEmpty() ? "0" : editDiffuseEfficiency.getText().toString()),
Float.parseFloat(editInverterPowerLimit.getText().toString().isEmpty() ? "0" : editInverterPowerLimit.getText().toString()),
Float.parseFloat(editInverterEfficiency.getText().toString().isEmpty() ? "0" : editInverterEfficiency.getText().toString()),
diff --git a/app/src/main/java/org/woheller69/weather/database/CityToWatch.java b/app/src/main/java/org/woheller69/weather/database/CityToWatch.java
index 081e2b1..bc68368 100644
--- a/app/src/main/java/org/woheller69/weather/database/CityToWatch.java
+++ b/app/src/main/java/org/woheller69/weather/database/CityToWatch.java
@@ -17,6 +17,7 @@ public class CityToWatch {
private float cellsMaxPower;
private float cellsArea;
private float cellsEfficiency;
+ private float cellsTempCoeff;
private float diffuseEfficiency;
private float inverterPowerLimit;
private float inverterEfficiency;
@@ -36,14 +37,15 @@ public CityToWatch(int rank, int id, int cityId, float lon, float lat, String ci
this.id = id;
this.cityId = cityId;
this.cityName = cityName;
- this.cellsMaxPower=650;
- this.cellsArea=3.18f;
- this.cellsEfficiency=19.3f;
- this.diffuseEfficiency=40;
- this.inverterPowerLimit =600;
- this.inverterEfficiency =95;
- this.azimuthAngle=170;
- this.tiltAngle =90;
+ this.cellsMaxPower = 650;
+ this.cellsArea = 3.18f;
+ this.cellsEfficiency = 19.3f;
+ this.cellsTempCoeff = -0.4f;
+ this.diffuseEfficiency = 40;
+ this.inverterPowerLimit = 600;
+ this.inverterEfficiency = 95;
+ this.azimuthAngle = 170;
+ this.tiltAngle = 90;
}
@@ -182,4 +184,12 @@ public String getShadingElevationString() {
public String getShadingOpacityString() {
return Arrays.toString(shadingOpacity).replaceAll("\\[|\\]|\\s", "");
}
+
+ public float getCellsTempCoeff() {
+ return cellsTempCoeff;
+ }
+
+ public void setCellsTempCoeff(float cellsTempCoeff) {
+ this.cellsTempCoeff = cellsTempCoeff;
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/woheller69/weather/database/SQLiteHelper.java b/app/src/main/java/org/woheller69/weather/database/SQLiteHelper.java
index 863f3a8..29a4f83 100644
--- a/app/src/main/java/org/woheller69/weather/database/SQLiteHelper.java
+++ b/app/src/main/java/org/woheller69/weather/database/SQLiteHelper.java
@@ -20,7 +20,7 @@
*/
public class SQLiteHelper extends SQLiteOpenHelper {
- private static final int DATABASE_VERSION = 1;
+ private static final int DATABASE_VERSION = 2;
private Context context;
private List allCities = new ArrayList<>();
@@ -53,6 +53,7 @@ public class SQLiteHelper extends SQLiteOpenHelper {
private static final String CITIES_TO_WATCH_TILT_ANGLE = "tilt_angle";
private static final String CITIES_TO_WATCH_SHADING_ELEVATION = "shading_elevation";
private static final String CITIES_TO_WATCH_SHADING_OPACITY = "shading_opacity";
+ private static final String CITIES_TO_WATCH_CELLS_TEMP_COEFF = "cells_temp_coeff";
//Names of columns in TABLE_FORECAST
private static final String FORECAST_ID = "forecast_id";
@@ -135,7 +136,8 @@ public class SQLiteHelper extends SQLiteOpenHelper {
CITIES_TO_WATCH_AZIMUTH_ANGLE + " REAL NOT NULL," +
CITIES_TO_WATCH_TILT_ANGLE + " REAL NOT NULL," +
CITIES_TO_WATCH_SHADING_ELEVATION + " VARCHAR(255) NOT NULL," +
- CITIES_TO_WATCH_SHADING_OPACITY + " VARCHAR(255) NOT NULL)";
+ CITIES_TO_WATCH_SHADING_OPACITY + " VARCHAR(255) NOT NULL," +
+ CITIES_TO_WATCH_CELLS_TEMP_COEFF + " REAL NOT NULL)";
public static SQLiteHelper getInstance(Context context) {
if (instance == null && context != null) {
@@ -160,6 +162,12 @@ public void onCreate(SQLiteDatabase db) {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ switch(oldVersion) {
+ case 1:
+ db.execSQL("ALTER TABLE "+TABLE_CITIES_TO_WATCH+" ADD COLUMN "+CITIES_TO_WATCH_CELLS_TEMP_COEFF+" REAL DEFAULT 0");
+ // we want both updates, so no break statement here...
+ }
+
}
@@ -185,6 +193,7 @@ public synchronized long addCityToWatch(CityToWatch city) {
values.put(CITIES_TO_WATCH_TILT_ANGLE,city.getTiltAngle());
values.put(CITIES_TO_WATCH_SHADING_ELEVATION,city.getShadingElevationString());
values.put(CITIES_TO_WATCH_SHADING_OPACITY,city.getShadingOpacityString());
+ values.put(CITIES_TO_WATCH_CELLS_TEMP_COEFF,city.getCellsTempCoeff());
long id=database.insert(TABLE_CITIES_TO_WATCH, null, values);
@@ -218,6 +227,7 @@ public synchronized CityToWatch getCityToWatch(int id) {
", " + CITIES_TO_WATCH_TILT_ANGLE +
", " + CITIES_TO_WATCH_SHADING_ELEVATION +
", " + CITIES_TO_WATCH_SHADING_OPACITY +
+ ", " + CITIES_TO_WATCH_CELLS_TEMP_COEFF +
", " + CITIES_TO_WATCH_COLUMN_RANK +
" FROM " + TABLE_CITIES_TO_WATCH +
" WHERE " + CITIES_TO_WATCH_CITY_ID + " = ?", arguments);
@@ -240,7 +250,8 @@ public synchronized CityToWatch getCityToWatch(int id) {
cityToWatch.setTiltAngle(Float.parseFloat(cursor.getString(12)));
cityToWatch.setShadingElevation(cursor.getString(13));
cityToWatch.setShadingOpacity(cursor.getString(14));
- cityToWatch.setRank(Integer.parseInt(cursor.getString(15)));
+ cityToWatch.setCellsTempCoeff(Float.parseFloat(cursor.getString(15)));
+ cityToWatch.setRank(Integer.parseInt(cursor.getString(16)));
cursor.close();
}
@@ -271,6 +282,7 @@ public synchronized List getAllCitiesToWatch() {
", " + CITIES_TO_WATCH_TILT_ANGLE +
", " + CITIES_TO_WATCH_SHADING_ELEVATION +
", " + CITIES_TO_WATCH_SHADING_OPACITY +
+ ", " + CITIES_TO_WATCH_CELLS_TEMP_COEFF +
", " + CITIES_TO_WATCH_COLUMN_RANK +
" FROM " + TABLE_CITIES_TO_WATCH
, new String[]{});
@@ -295,7 +307,8 @@ public synchronized List getAllCitiesToWatch() {
cityToWatch.setTiltAngle(Float.parseFloat(cursor.getString(12)));
cityToWatch.setShadingElevation(cursor.getString(13));
cityToWatch.setShadingOpacity(cursor.getString(14));
- cityToWatch.setRank(Integer.parseInt(cursor.getString(15)));
+ cityToWatch.setCellsTempCoeff(Float.parseFloat(cursor.getString(15)));
+ cityToWatch.setRank(Integer.parseInt(cursor.getString(16)));
cityToWatchList.add(cityToWatch);
} while (cursor.moveToNext());
@@ -325,6 +338,7 @@ public synchronized void updateCityToWatch(CityToWatch cityToWatch) {
values.put(CITIES_TO_WATCH_TILT_ANGLE,cityToWatch.getTiltAngle());
values.put(CITIES_TO_WATCH_SHADING_ELEVATION,cityToWatch.getShadingElevationString());
values.put(CITIES_TO_WATCH_SHADING_OPACITY,cityToWatch.getShadingOpacityString());
+ values.put(CITIES_TO_WATCH_CELLS_TEMP_COEFF,cityToWatch.getCellsTempCoeff());
database.update(TABLE_CITIES_TO_WATCH, values, CITIES_TO_WATCH_ID + " = ?",
new String[]{String.valueOf(cityToWatch.getId())});
diff --git a/app/src/main/java/org/woheller69/weather/ui/Help/InputFilterMinMax.java b/app/src/main/java/org/woheller69/weather/ui/Help/InputFilterMinMax.java
index 029afa8..b371e34 100644
--- a/app/src/main/java/org/woheller69/weather/ui/Help/InputFilterMinMax.java
+++ b/app/src/main/java/org/woheller69/weather/ui/Help/InputFilterMinMax.java
@@ -5,9 +5,9 @@
public class InputFilterMinMax implements InputFilter {
- private int min, max;
+ private float min, max;
- public InputFilterMinMax(int min, int max) {
+ public InputFilterMinMax(float min, float max) {
this.min = min;
this.max = max;
}
@@ -15,17 +15,30 @@ public InputFilterMinMax(int min, int max) {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
- String oldString = dest.toString();
- String insertString = source.toString();
- String newString = new StringBuilder(oldString).insert(dstart,insertString).toString();
- float input = Float.parseFloat(newString);
- if (isInRange(min, max, input))
- return null;
- else
- return "";
+ try {
+ String oldString = dest.toString();
+ String insertString = source.toString();
+ String newString = oldString.substring(0, dstart) + oldString.substring(dend);
+ newString = newString.substring(0, dstart) + insertString + newString.substring(dstart);
+ float input = Float.parseFloat(newString);
+
+ if (isInRange(min, max, input)) {
+ return null;
+ } else {
+ if (source.equals("") && dest.toString().length() != 1) {
+ //backspace was clicked, do not accept that change, unless user is deleting the last char
+ return dest.subSequence(dstart, dend);
+ } else {
+ return "";
+ }
+ }
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+ return "";
}
- private boolean isInRange(int a, int b, float c) {
+ private boolean isInRange(float a, float b, float c) {
return b > a ? c >= a && c <= b : c >= b && c <= a;
}
diff --git a/app/src/main/java/org/woheller69/weather/ui/RecycleList/ItemViewHolder.java b/app/src/main/java/org/woheller69/weather/ui/RecycleList/ItemViewHolder.java
index c92586d..52b5a61 100644
--- a/app/src/main/java/org/woheller69/weather/ui/RecycleList/ItemViewHolder.java
+++ b/app/src/main/java/org/woheller69/weather/ui/RecycleList/ItemViewHolder.java
@@ -23,6 +23,7 @@ public class ItemViewHolder extends RecyclerView.ViewHolder {
public TextView cellsMaxPower;
public TextView cellsArea;
public TextView cellsEfficiency;
+ public TextView cellsTempCoeff;
public TextView diffuseEfficiency;
public TextView inverterPowerLimit;
public TextView inverterEfficiency;
@@ -41,6 +42,7 @@ public ItemViewHolder(View itemView) {
this.cellsMaxPower = (TextView) itemView.findViewById(R.id.city_cells_max_power);
this.cellsArea = (TextView) itemView.findViewById(R.id.city_cells_area);
this.cellsEfficiency = (TextView) itemView.findViewById(R.id.city_cells_efficiency);
+ this.cellsTempCoeff = (TextView) itemView.findViewById(R.id.city_cells_temp_coeff);
this.diffuseEfficiency = (TextView) itemView.findViewById(R.id.city_diffuse_efficiency);
this.inverterPowerLimit = (TextView) itemView.findViewById(R.id.city_inverter_power_limit);
this.inverterEfficiency = (TextView) itemView.findViewById(R.id.city_inverter_efficiency);
diff --git a/app/src/main/java/org/woheller69/weather/ui/RecycleList/RecyclerOverviewListAdapter.java b/app/src/main/java/org/woheller69/weather/ui/RecycleList/RecyclerOverviewListAdapter.java
index 0c5e032..e7bfd60 100644
--- a/app/src/main/java/org/woheller69/weather/ui/RecycleList/RecyclerOverviewListAdapter.java
+++ b/app/src/main/java/org/woheller69/weather/ui/RecycleList/RecyclerOverviewListAdapter.java
@@ -63,6 +63,7 @@ public void onBindViewHolder(ItemViewHolder holder, int position) {
holder.tiltAngle.setText(context.getString(R.string.edit_location_hint_tilt) +": "+ cities.get(position).getTiltAngle());
holder.cellsMaxPower.setText(context.getString(R.string.edit_location_hint_cells_max_power) +": "+ cities.get(position).getCellsMaxPower());
holder.cellsEfficiency.setText(context.getString(R.string.edit_location_hint_cells_efficiency) +": "+ cities.get(position).getCellsEfficiency());
+ holder.cellsTempCoeff.setText(context.getString(R.string.edit_location_hint_cells_temp_coeff) +": "+ cities.get(position).getCellsTempCoeff());
holder.cellsArea.setText(context.getString(R.string.edit_location_hint_cells_area) +": "+ cities.get(position).getCellsArea());
holder.diffuseEfficiency.setText(context.getString(R.string.edit_location_hint_diffuse_efficiency) +": "+ cities.get(position).getDiffuseEfficiency());
holder.inverterPowerLimit.setText(context.getString(R.string.edit_location_hint_inverter_power_limit) +": "+ cities.get(position).getInverterPowerLimit());
@@ -114,7 +115,7 @@ public void onItemMove(int fromPosition, int toPosition) {
public CityToWatch getCitytoWatch(int position){
return cities.get(position);
}
- public void updateCity(CityToWatch cityToWatch, String cityName, float latitude, float longitude, float azimuth, float tilt, float cellsMaxPower, float cellsArea, float cellsEfficiency, float diffuseEfficiency, float inverterPowerLimit, float inverterEfficiency, int[] shadingElevation, int[] shadingOpacity) {
+ public void updateCity(CityToWatch cityToWatch, String cityName, float latitude, float longitude, float azimuth, float tilt, float cellsMaxPower, float cellsArea, float cellsEfficiency, float cellsTempCoeff, float diffuseEfficiency, float inverterPowerLimit, float inverterEfficiency, int[] shadingElevation, int[] shadingOpacity) {
cityToWatch.setCityName(cityName);
cityToWatch.setLatitude(latitude);
cityToWatch.setLongitude(longitude);
@@ -123,6 +124,7 @@ public void updateCity(CityToWatch cityToWatch, String cityName, float latitude,
cityToWatch.setCellsMaxPower(cellsMaxPower);
cityToWatch.setCellsArea(cellsArea);
cityToWatch.setCellsEfficiency(cellsEfficiency);
+ cityToWatch.setCellsTempCoeff(cellsTempCoeff);
cityToWatch.setDiffuseEfficiency(diffuseEfficiency);
cityToWatch.setInverterPowerLimit(inverterPowerLimit);
cityToWatch.setInverterEfficiency(inverterEfficiency);
diff --git a/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMDataExtractor.java b/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMDataExtractor.java
index 45acc2b..e04856b 100644
--- a/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMDataExtractor.java
+++ b/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMDataExtractor.java
@@ -66,6 +66,7 @@ public List extractHourlyForecast(String data, int cityID) {
JSONObject jsonData = new JSONObject(data);
JSONArray timeArray = jsonData.getJSONArray("time");
JSONArray weathercodeArray = jsonData.has("weathercode") ? jsonData.getJSONArray("weathercode") : null;
+ JSONArray tempArray = jsonData.has("temperature_2m") ? jsonData.getJSONArray("temperature_2m") : null;
JSONArray directRadiationArray = jsonData.has("direct_normal_irradiance") ? jsonData.getJSONArray("direct_normal_irradiance") : null;
JSONArray diffuseRadiationArray = jsonData.has("diffuse_radiation") ? jsonData.getJSONArray("diffuse_radiation") : null;
@@ -73,18 +74,20 @@ public List extractHourlyForecast(String data, int cityID) {
SQLiteHelper dbhelper = SQLiteHelper.getInstance(context);
CityToWatch city = dbhelper.getCityToWatch(cityID);
- SolarPowerPlant spp = new SolarPowerPlant(city.getLatitude(), city.getLongitude(), city.getCellsMaxPower(), city.getCellsArea(), city.getCellsEfficiency(),city.getDiffuseEfficiency(), city.getInverterPowerLimit(), city.getInverterEfficiency(), city.getAzimuthAngle(), city.getTiltAngle(), city.getShadingElevation(), city.getShadingOpacity());
+ SolarPowerPlant spp = new SolarPowerPlant(city.getLatitude(), city.getLongitude(), city.getCellsMaxPower(), city.getCellsArea(), city.getCellsEfficiency(), city.getCellsTempCoeff(), city.getDiffuseEfficiency(), city.getInverterPowerLimit(), city.getInverterEfficiency(), city.getAzimuthAngle(), city.getTiltAngle(), city.getShadingElevation(), city.getShadingOpacity());
IApiToDatabaseConversion conversion = new OMToDatabaseConversion();
+ float ambientTemperature = 25;
for (int i = 0; i < timeArray.length(); i++) {
HourlyForecast hourlyForecast = new HourlyForecast();
hourlyForecast.setTimestamp(System.currentTimeMillis() / 1000);
if (timeArray!=null && !timeArray.isNull(i)) hourlyForecast.setForecastTime(timeArray.getLong(i)*1000L);
+ if (tempArray != null && !tempArray.isNull(i)) ambientTemperature = (float) tempArray.getDouble(i);
if (weathercodeArray!=null && !weathercodeArray.isNull(i)) hourlyForecast.setWeatherID(conversion.convertWeatherCategory(weathercodeArray.getString(i)));
if (directRadiationArray!=null && !directRadiationArray.isNull(i)) hourlyForecast.setDirectRadiationNormal((float) directRadiationArray.getDouble(i));
if (diffuseRadiationArray!=null && !diffuseRadiationArray.isNull(i)) hourlyForecast.setDiffuseRadiation((float) diffuseRadiationArray.getDouble(i));
- hourlyForecast.setPower(spp.getPower(hourlyForecast.getDirectRadiationNormal(),hourlyForecast.getDiffuseRadiation(), timeArray.getLong(i)-1800)); //use solar position 1/2h earlier for calculation of average power in preceding hour
+ hourlyForecast.setPower(spp.getPower(hourlyForecast.getDirectRadiationNormal(),hourlyForecast.getDiffuseRadiation(), timeArray.getLong(i)-1800 , ambientTemperature)); //use solar position 1/2h earlier for calculation of average power in preceding hour
hourlyForecasts.add(hourlyForecast);
}
return hourlyForecasts;
diff --git a/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMHttpRequest.java b/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMHttpRequest.java
index 64db92e..5a36ec2 100644
--- a/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMHttpRequest.java
+++ b/app/src/main/java/org/woheller69/weather/weather_api/open_meteo/OMHttpRequest.java
@@ -24,7 +24,7 @@ protected String getUrlForQueryingOMweatherAPI(Context context, float lat, float
SharedPreferences sharedPreferences=PreferenceManager.getDefaultSharedPreferences(context);
return String.format(
- "%sforecast?latitude=%s&longitude=%s&forecast_days=%s&hourly=diffuse_radiation,direct_normal_irradiance,weathercode&daily=weathercode,sunrise,sunset,&timeformat=unixtime&timezone=auto",
+ "%sforecast?latitude=%s&longitude=%s&forecast_days=%s&hourly=temperature_2m,diffuse_radiation,direct_normal_irradiance,weathercode&daily=weathercode,sunrise,sunset,&timeformat=unixtime&timezone=auto",
BuildConfig.BASE_URL,
lat,
lon,
diff --git a/app/src/main/res/drawable/ic_sunny_24px.xml b/app/src/main/res/drawable/ic_sunny_24px.xml
new file mode 100644
index 0000000..ac5026f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_sunny_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_wb_sunny_24px.xml b/app/src/main/res/drawable/ic_wb_sunny_24px.xml
deleted file mode 100644
index 36167d1..0000000
--- a/app/src/main/res/drawable/ic_wb_sunny_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/app/src/main/res/layout/card_day.xml b/app/src/main/res/layout/card_day.xml
index 9da02db..c78fd19 100644
--- a/app/src/main/res/layout/card_day.xml
+++ b/app/src/main/res/layout/card_day.xml
@@ -17,7 +17,6 @@
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center"
- android:text="@string/card_day_heading"
android:textAllCaps="true"
android:textColor="@color/colorPrimaryDark"
android:textStyle="bold" />
diff --git a/app/src/main/res/layout/card_details.xml b/app/src/main/res/layout/card_details.xml
index e633bf5..e6dc147 100644
--- a/app/src/main/res/layout/card_details.xml
+++ b/app/src/main/res/layout/card_details.xml
@@ -20,7 +20,6 @@
android:textAllCaps="true"
android:textColor="@color/colorPrimaryDark"
android:textStyle="bold"
- android:text="@string/card_details_heading"
android:id="@+id/card_details_title"/>
@@ -79,7 +77,6 @@
android:layout_column="0"
android:layout_marginBottom="5dp"
android:layout_row="2"
- android:text="@string/card_details_humidity"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/colorPrimaryDark" />
@@ -101,7 +98,6 @@
android:layout_column="0"
android:layout_marginBottom="5dp"
android:layout_row="3"
- android:text="@string/card_details_pressure"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/colorPrimaryDark" />
@@ -123,7 +119,6 @@
android:layout_column="0"
android:layout_marginBottom="5dp"
android:layout_row="4"
- android:text="@string/card_details_wind_speed"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/colorPrimaryDark" />
diff --git a/app/src/main/res/layout/dialog_edit_location.xml b/app/src/main/res/layout/dialog_edit_location.xml
index 77b7807..8dab3a0 100644
--- a/app/src/main/res/layout/dialog_edit_location.xml
+++ b/app/src/main/res/layout/dialog_edit_location.xml
@@ -91,6 +91,16 @@
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:hint="@string/edit_location_hint_cells_efficiency"/>
+
+
+
- Einstellungen
Aktualisieren
Einstellungen
- Jetzt
- Luftfeuchte:
- Luftdruck:
- Wind:
- Tagesverlauf
Woche
Die erhaltenen Wetterdaten entsprachen nicht dem erwarteten Format.
Das Gerät ist nicht mit dem Internet verbunden!
@@ -30,20 +25,10 @@
Ort, der hinzugefügt werden soll:
Es wurde kein Ort gefunden, der der Eingabe entspricht. Es wird empfohlen, einen Eintrag aus dem Dropdown-Menu zu wählen.
Navigationsleiste schließen
- Maßeinheiten
- Temperaturen
- Entfernungen
- Celsius
- Fahrenheit
- Kilometer
- Meilen
- Die Einheit, die zur Anzeige von Entfernungen verwendet wird.
- Die Einheit, die zur Anzeige von Temperaturen verwendet wird.
Setzen Sie das Interval der automatischen Updates
Intervalle
Update Intervall
Anzeigeoptionen
-
Navigationsleiste öffnen
Fr.
Mo.
@@ -62,7 +47,6 @@
Halten und ziehen Sie, um die Orte zu sortieren.
Wischen Sie zum Löschen
Die Wetterinformationen stammen von Open-Meteo.com
-
Montag
Dienstag
Mittwoch
@@ -71,34 +55,17 @@
Samstag
Sonntag
Diagramm
- % rh
kWh
- km
- hPa
- Bft
- mm/h
- km/h
- mph
- ☔ 60 min:
- keine Daten
Ändern
Name
Suche
- Temperatur mit einer Dezimalstelle anzeigen
Android 10+ Dark Mode
- Position
- Erlaubt die Nutzung der aktuellen GPS Position im ersten TAB und im Widget für das aktuelle Wetter. Das Update der Position wird automatisch vom Widget ausgelöst.
- GPS Nutzung erlauben
- Keine Position verfügbar
24-Stunden-Format
Systemeinstellung überschreiben
- Beaufort-Skala benutzen
OK
Nein
Vielleicht später
Mögen Sie diese App? Bitte vergeben Sie einen Stern auf GitHub und spendieren Sie dem Entwickler einen Kaffee über PayPal.
- Luftdruck anzeigen
- Nur manuell aktualisieren
15 min
30 min
1 h
@@ -106,13 +73,7 @@
6 h
12 h
24 h
- Bitte erlauben Sie auch die GPS Nutzung im Hintergrund für die Verwendung im Widget
- Bitte GPS einschalten
Open-Meteo
- Verbessern der Wochensymbole durch Analyse der stündlichen Vorhersagen zwischen Sonnenaufgang und Sonnenuntergang (experimentell).
- Wochensymbole
- Niederschlag
- Schneemenge anstelle der entsprechenden Wassermenge verwenden.
Anzahl der prognostizierten Tage
Breitengrad [°]
Längengrad [°]
@@ -133,5 +94,6 @@
Anleitung
Sonnenposition
Elevation [°]
+ Temperaturkoeffizient [%/K]
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 881b7ed..05639fd 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -1,24 +1,6 @@
-
-
- @string/settings_celsius
- - @string/settings_fahrenheit
-
-
- - 1
- - 2
-
-
-
- - @string/settings_kilometers
- - @string/settings_miles
-
-
- - 1
- - 2
-
-
- @string/settings_interval_quarter
- @string/settings_interval_half
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 15f1ffc..3d31510 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -13,12 +13,7 @@
solXpect forecasts the output of your solar power plant
Github
The sourcecode of this app is available at GitHub. For further explanations have a look at the About Page.
- Now
- Humidity:
- Pressure:
- Wind:
Week
- Course of the day
Error fetching weather data
Please try to update!
Privacy Info
@@ -30,15 +25,6 @@
Github-Repo
Open-Meteo \n(Attribution 4.0 International CC BY 4.0)
Settings
- Units
- Set the unit to use for displaying temperatures
- Temperatures
- Celsius
- Fahrenheit
- Set the unit to use for displaying distances
- Distances
- Kilometers
- Miles
Mo.
Tu.
We.
@@ -79,42 +65,18 @@
Saturday
Sunday
Chart
- % rh
kWh
- km
- hPa
- Bft
- mm/h
- km/h
- mph
- ☔ 60 min:
- no data
Modify
Name
Search
- Show temperature with one decimal
Android 10+ Dark Mode
- Position
- Allow usage of current GPS position in first TAB and in current weather widget. Position update is triggered automatically by widget.
- Allow GPS usage
- No position available
24-hour format
Override system setting
- Use Beaufort scale
OK
No
Maybe later
Do you like this app? Please give a star on GitHub and buy the developer a coffee via PayPal.
- Show air pressure
- Update Location
- Manual update only
- Please also allow GPS usage in the background for use in the widget
- Please turn on GPS
Open-Meteo
- Improve week icons by analyzing hourly forecasts between sunrise and sunset (experimental).
- Week Icons
- Precipitation
- Use snow amount instead of the equivalent amount of water.
Number of forecast days
Latitude [°]
Longitude [°]
@@ -135,4 +97,5 @@
Instructions
Sun position
Elevation [°]
+ Temperature coefficient [%/K]
diff --git a/fastlane/metadata/android/en-US/changelogs/12.txt b/fastlane/metadata/android/en-US/changelogs/12.txt
new file mode 100644
index 0000000..fea5a13
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/12.txt
@@ -0,0 +1,6 @@
+Estimate panel temperature from ambient temperature and radiation
+Additional parameter: temperature coefficient
+Adapt efficiency according to these values
+Bugfix input filter
+
+!!! Please enter temperature coeffient of your panels !!!
\ No newline at end of file