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