mirror of
https://github.com/woheller69/solxpect.git
synced 2025-09-22 00:40:46 +02:00
fix issue:refresh button not rotating
new feature: show sum new feature: clone location update Readme and help
This commit is contained in:
parent
38295c65e1
commit
2ae9a055eb
16 changed files with 274 additions and 82 deletions
|
@ -10,6 +10,10 @@ of the sun and projects the radiation on your solar panel.
|
||||||
It shows the estimated energy production for the next hours and up to 16 days.
|
It shows the estimated energy production for the next hours and up to 16 days.
|
||||||
The hourly values are calculated for the preceding hour. So if there are 150 Wh shown at 11:00 this means you can expect 150 Wh between 10:00 and 11:00.
|
The hourly values are calculated for the preceding hour. So if there are 150 Wh shown at 11:00 this means you can expect 150 Wh between 10:00 and 11:00.
|
||||||
|
|
||||||
|
If you have several modules pointing in different directions you can define them as separate locations and switch on 'show sum' in preferences. Then
|
||||||
|
all locations with same latitude/longitude are summarized. In this case you should define your location names as 'myPV | part1', 'myPV | part2', etc.
|
||||||
|
In 'show sum' mode the location is then shown as 'myPV' and '|' is taken as delimiter in this case.
|
||||||
|
|
||||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/01.png" width="150"/> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/02.png" width="150"/> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/03.png" width="150"/> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/04.png" width="150"/>
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/01.png" width="150"/> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/02.png" width="150"/> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/03.png" width="150"/> <img src="fastlane/metadata/android/en-US/images/phoneScreenshots/04.png" width="150"/>
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,6 +78,7 @@ The app uses:
|
||||||
- Map data from OpenStreetMap, licensed under the Open Data Commons Open Database License (ODbL) by the OpenStreetMap Foundation (OSMF) (https://www.openstreetmap.org/copyright)
|
- Map data from OpenStreetMap, licensed under the Open Data Commons Open Database License (ODbL) by the OpenStreetMap Foundation (OSMF) (https://www.openstreetmap.org/copyright)
|
||||||
- Solar positioning library (https://github.com/klausbrunner/solarpositioning) which is licensed under <a href='https://github.com/klausbrunner/solarpositioning/blob/master/LICENSE.txt'>MIT License</a>
|
- Solar positioning library (https://github.com/klausbrunner/solarpositioning) which is licensed under <a href='https://github.com/klausbrunner/solarpositioning/blob/master/LICENSE.txt'>MIT License</a>
|
||||||
- Zip4j (https://github.com/srikanth-lingala/zip4j) which is licensed under Apache License Version 2.0
|
- Zip4j (https://github.com/srikanth-lingala/zip4j) which is licensed under Apache License Version 2.0
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
If you find a bug, please open an issue in the Github repository, assuming one does not already exist.
|
If you find a bug, please open an issue in the Github repository, assuming one does not already exist.
|
||||||
|
|
|
@ -12,8 +12,8 @@ android {
|
||||||
applicationId "org.woheller69.solxpect"
|
applicationId "org.woheller69.solxpect"
|
||||||
minSdkVersion 26
|
minSdkVersion 26
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 13
|
versionCode 14
|
||||||
versionName "1.3"
|
versionName "1.4"
|
||||||
|
|
||||||
buildConfigField "String", "BASE_URL", "\"https://api.open-meteo.com/v1/\""
|
buildConfigField "String", "BASE_URL", "\"https://api.open-meteo.com/v1/\""
|
||||||
buildConfigField "String", "GITHUB_URL","\"https://github.com/woheller69/solxpect/\""
|
buildConfigField "String", "GITHUB_URL","\"https://github.com/woheller69/solxpect/\""
|
||||||
|
|
|
@ -8,6 +8,11 @@ Es zeigt die geschätzte Energieproduktion für die nächsten Stunden und bis zu
|
||||||
Die Stundenwerte werden für die vorangegangene Stunde berechnet.
|
Die Stundenwerte werden für die vorangegangene Stunde berechnet.
|
||||||
Wenn also um 11:00 Uhr 150 Wh angezeigt werden, bedeutet dies, dass Sie zwischen 10:00 und 11:00 Uhr mit 150 Wh rechnen können.
|
Wenn also um 11:00 Uhr 150 Wh angezeigt werden, bedeutet dies, dass Sie zwischen 10:00 und 11:00 Uhr mit 150 Wh rechnen können.
|
||||||
|
|
||||||
|
<h3>Mehrere Module am gleichen Ort</h3>
|
||||||
|
Wenn Sie mehrere Module haben, die in verschiedene Richtungen zeigen, können Sie sie als separate Standorte definieren und in den Einstellungen 'Summe anzeigen' einschalten.
|
||||||
|
Dann werden alle Orte mit gleichem Breiten-/Längengrad zusammengefasst. In diesem Fall sollten Sie Ihre Standortnamen als 'myPV | Teil1', 'meinPV | Teil2' usw. definieren.
|
||||||
|
Im Modus 'Summe anzeigen' wird der Standort dann als 'myPV' angezeigt und '|' wird in diesem Fall als Trennzeichen verwendet.
|
||||||
|
|
||||||
<h2>Parameter</h2>
|
<h2>Parameter</h2>
|
||||||
|
|
||||||
<h3>Breitengrad [°]</h3>
|
<h3>Breitengrad [°]</h3>
|
||||||
|
|
|
@ -8,6 +8,11 @@ It shows the estimated energy production for the next hours and up to 16 days.
|
||||||
The hourly values are calculated for the preceding hour.
|
The hourly values are calculated for the preceding hour.
|
||||||
So if there are 150 Wh shown at 11:00 this means you can expect 150 Wh between 10:00 and 11:00.
|
So if there are 150 Wh shown at 11:00 this means you can expect 150 Wh between 10:00 and 11:00.
|
||||||
|
|
||||||
|
<h3>Several modules at same location</h3>
|
||||||
|
If you have several modules pointing in different directions you can define them as separate locations and switch on 'show sum' in preferences. Then
|
||||||
|
all locations with same latitude/longitude are summarized. In this case you should define your location names as 'myPV | part1', 'myPV | part2', etc.
|
||||||
|
In 'show sum' mode the location is then shown as 'myPV' and '|' is taken as delimiter in this case.
|
||||||
|
|
||||||
<h2>Parameters</h2>
|
<h2>Parameters</h2>
|
||||||
|
|
||||||
<h3>Latitude [°]</h3>
|
<h3>Latitude [°]</h3>
|
||||||
|
|
|
@ -20,8 +20,8 @@ public class SolarPowerPlant {
|
||||||
double inverterEfficiency;
|
double inverterEfficiency;
|
||||||
double azimuthAngle;
|
double azimuthAngle;
|
||||||
double tiltAngle;
|
double tiltAngle;
|
||||||
private int[] shadingElevation;
|
private final int[] shadingElevation;
|
||||||
private int[] shadingOpacity;
|
private final 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 ) {
|
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.latitude = latitude;
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class ForecastCityActivity extends NavigationActivity implements IUpdatea
|
||||||
private ViewPager2 viewPager2;
|
private ViewPager2 viewPager2;
|
||||||
private TabLayout tabLayout;
|
private TabLayout tabLayout;
|
||||||
private TextView noCityText;
|
private TextView noCityText;
|
||||||
|
private static Boolean isRefreshing = false;
|
||||||
Context context;
|
Context context;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,10 +137,15 @@ public class ForecastCityActivity extends NavigationActivity implements IUpdatea
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initResources() {
|
private void initResources() {
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
viewPager2 = findViewById(R.id.viewPager2);
|
viewPager2 = findViewById(R.id.viewPager2);
|
||||||
reduceViewpager2DragSensitivity(viewPager2,2);
|
reduceViewpager2DragSensitivity(viewPager2,2);
|
||||||
tabLayout = findViewById(R.id.tab_layout);
|
tabLayout = findViewById(R.id.tab_layout);
|
||||||
pagerAdapter = new WeatherPagerAdapter(this, getSupportFragmentManager(),getLifecycle());
|
if (sharedPreferences.getBoolean("pref_summarize",false)){
|
||||||
|
pagerAdapter = new WeatherPagerAdapter(this, getSupportFragmentManager(),getLifecycle(),true);
|
||||||
|
} else {
|
||||||
|
pagerAdapter = new WeatherPagerAdapter(this, getSupportFragmentManager(),getLifecycle(),false);
|
||||||
|
}
|
||||||
noCityText = findViewById(R.id.noCitySelectedText);
|
noCityText = findViewById(R.id.noCitySelectedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +164,7 @@ public class ForecastCityActivity extends NavigationActivity implements IUpdatea
|
||||||
refreshActionButton = menu.findItem(R.id.menu_refresh);
|
refreshActionButton = menu.findItem(R.id.menu_refresh);
|
||||||
refreshActionButton.setActionView(R.layout.menu_refresh_action_view);
|
refreshActionButton.setActionView(R.layout.menu_refresh_action_view);
|
||||||
refreshActionButton.getActionView().setOnClickListener(v -> m.performIdentifierAction(refreshActionButton.getItemId(), 0));
|
refreshActionButton.getActionView().setOnClickListener(v -> m.performIdentifierAction(refreshActionButton.getItemId(), 0));
|
||||||
|
if (isRefreshing) startRefreshAnimation();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -208,28 +215,29 @@ public class ForecastCityActivity extends NavigationActivity implements IUpdatea
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processNewGeneralData(GeneralData data) {
|
public void processNewGeneralData(GeneralData data) {
|
||||||
if (refreshActionButton != null && refreshActionButton.getActionView() != null) {
|
stopRefreshAnimation();
|
||||||
refreshActionButton.getActionView().clearAnimation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processNewWeekForecasts(List<WeekForecast> forecasts) {
|
public void processNewWeekForecasts(List<WeekForecast> forecasts) {
|
||||||
if (refreshActionButton != null && refreshActionButton.getActionView() != null) {
|
stopRefreshAnimation();
|
||||||
refreshActionButton.getActionView().clearAnimation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processNewForecasts(List<HourlyForecast> hourlyForecasts) {
|
public void processNewForecasts(List<HourlyForecast> hourlyForecasts) {
|
||||||
|
stopRefreshAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopRefreshAnimation(){
|
||||||
if (refreshActionButton != null && refreshActionButton.getActionView() != null) {
|
if (refreshActionButton != null && refreshActionButton.getActionView() != null) {
|
||||||
refreshActionButton.getActionView().clearAnimation();
|
refreshActionButton.getActionView().clearAnimation();
|
||||||
}
|
}
|
||||||
|
isRefreshing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startRefreshAnimation(){
|
public static void startRefreshAnimation(){
|
||||||
{
|
isRefreshing = true;
|
||||||
if(refreshActionButton !=null && refreshActionButton.getActionView() != null) {
|
if(refreshActionButton !=null && refreshActionButton.getActionView() != null) {
|
||||||
RotateAnimation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
RotateAnimation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||||
rotate.setDuration(500);
|
rotate.setDuration(500);
|
||||||
rotate.setRepeatCount(5);
|
rotate.setRepeatCount(5);
|
||||||
|
@ -247,6 +255,7 @@ public class ForecastCityActivity extends NavigationActivity implements IUpdatea
|
||||||
refreshActionButton.getActionView().setActivated(true);
|
refreshActionButton.getActionView().setActivated(true);
|
||||||
refreshActionButton.getActionView().setEnabled(true);
|
refreshActionButton.getActionView().setEnabled(true);
|
||||||
refreshActionButton.getActionView().setClickable(true);
|
refreshActionButton.getActionView().setClickable(true);
|
||||||
|
isRefreshing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -254,8 +263,7 @@ public class ForecastCityActivity extends NavigationActivity implements IUpdatea
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
refreshActionButton.getActionView().startAnimation(rotate);
|
refreshActionButton.getActionView().startAnimation(rotate);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://devdreamz.com/question/348298-how-to-modify-sensitivity-of-viewpager
|
//https://devdreamz.com/question/348298-how-to-modify-sensitivity-of-viewpager
|
||||||
|
|
|
@ -251,6 +251,40 @@ public class ManageLocationsActivity extends NavigationActivity {
|
||||||
alert.setNegativeButton(getString(R.string.dialog_add_close_button), (dialog, whichButton) -> {
|
alert.setNegativeButton(getString(R.string.dialog_add_close_button), (dialog, whichButton) -> {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
alert.setNeutralButton(getString(R.string.dialog_add_clone_button), (dialog, whichButton) -> {
|
||||||
|
CityToWatch cloneCity = new CityToWatch(
|
||||||
|
database.getMaxRank() + 1,
|
||||||
|
-1,
|
||||||
|
0, city.getLongitude(),city.getLatitude(),
|
||||||
|
city.getCityName()
|
||||||
|
);
|
||||||
|
long id=database.addCityToWatch(cloneCity);
|
||||||
|
cloneCity.setId((int) id);
|
||||||
|
cloneCity.setCityId((int) id); //use id also instead of city id as unique identifier
|
||||||
|
cities.add(cloneCity);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
for (int i = 0; i < shadingElevation.length ; i++) {
|
||||||
|
shadingElevation[i]= Integer.parseInt(elevationViews[i].getText().toString().isEmpty() ? "0" : elevationViews[i].getText().toString());
|
||||||
|
shadingOpacity[i]= Integer.parseInt(opacityViews[i].getText().toString().isEmpty() ? "0" : opacityViews[i].getText().toString());
|
||||||
|
}
|
||||||
|
adapter.updateCity(cloneCity, String.valueOf(editCity.getText()),
|
||||||
|
Float.parseFloat(editLatitude.getText().toString().isEmpty() ? "0" : editLatitude.getText().toString()),
|
||||||
|
Float.parseFloat(editLongitude.getText().toString().isEmpty() ? "0" : editLongitude.getText().toString()),
|
||||||
|
Float.parseFloat(editAzimuth.getText().toString().isEmpty() ? "0" : editAzimuth.getText().toString()),
|
||||||
|
Float.parseFloat(editTilt.getText().toString().isEmpty() ? "0" : editTilt.getText().toString()),
|
||||||
|
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()),
|
||||||
|
shadingElevation,
|
||||||
|
shadingOpacity
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
alert.show();
|
alert.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +317,7 @@ public class ManageLocationsActivity extends NavigationActivity {
|
||||||
return new CityToWatch(
|
return new CityToWatch(
|
||||||
database.getMaxRank() + 1,
|
database.getMaxRank() + 1,
|
||||||
-1,
|
-1,
|
||||||
selectedCity.getCityId(), selectedCity.getLongitude(),selectedCity.getLatitude(),
|
0, selectedCity.getLongitude(),selectedCity.getLatitude(),
|
||||||
selectedCity.getCityName()
|
selectedCity.getCityName()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import androidx.preference.PreferenceManager;
|
||||||
import androidx.preference.SeekBarPreference;
|
import androidx.preference.SeekBarPreference;
|
||||||
|
|
||||||
import org.woheller69.weather.R;
|
import org.woheller69.weather.R;
|
||||||
|
import org.woheller69.weather.database.SQLiteHelper;
|
||||||
|
|
||||||
public class SettingsActivity extends NavigationActivity implements SharedPreferences.OnSharedPreferenceChangeListener{
|
public class SettingsActivity extends NavigationActivity implements SharedPreferences.OnSharedPreferenceChangeListener{
|
||||||
|
|
||||||
|
@ -80,6 +81,11 @@ public class SettingsActivity extends NavigationActivity implements SharedPrefer
|
||||||
if (key.equals("pref_number_days")){
|
if (key.equals("pref_number_days")){
|
||||||
SeekBarPreference numberDays = findPreference("pref_number_days");
|
SeekBarPreference numberDays = findPreference("pref_number_days");
|
||||||
if (numberDays.getValue()<3) numberDays.setValue(3);
|
if (numberDays.getValue()<3) numberDays.setValue(3);
|
||||||
|
} else if (key.equals("pref_summarize")){
|
||||||
|
if (sharedPreferences.getBoolean("pref_summarize",false)) {
|
||||||
|
SQLiteHelper database = SQLiteHelper.getInstance(getActivity());
|
||||||
|
database.deleteAllForecasts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,6 +403,17 @@ public class SQLiteHelper extends SQLiteOpenHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void deleteAllForecasts(){
|
||||||
|
SQLiteDatabase database = this.getWritableDatabase();
|
||||||
|
database.delete(TABLE_GENERAL_DATA, COLUMN_CITY_ID + " <> ?",
|
||||||
|
new String[]{Integer.toString(-1)});
|
||||||
|
database.delete(TABLE_HOURLY_FORECAST, FORECAST_CITY_ID + " <> ?",
|
||||||
|
new String[]{Integer.toString(-1)});
|
||||||
|
database.delete(TABLE_WEEKFORECAST, WEEKFORECAST_CITY_ID + " <> ?",
|
||||||
|
new String[]{Integer.toString(-1)});
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized List<HourlyForecast> getForecastsByCityId(int cityId) {
|
public synchronized List<HourlyForecast> getForecastsByCityId(int cityId) {
|
||||||
SQLiteDatabase database = this.getWritableDatabase();
|
SQLiteDatabase database = this.getWritableDatabase();
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.db.chart.view.AxisController;
|
||||||
import com.db.chart.view.BarChartView;
|
import com.db.chart.view.BarChartView;
|
||||||
|
|
||||||
import org.woheller69.weather.R;
|
import org.woheller69.weather.R;
|
||||||
|
import org.woheller69.weather.database.CityToWatch;
|
||||||
import org.woheller69.weather.database.GeneralData;
|
import org.woheller69.weather.database.GeneralData;
|
||||||
import org.woheller69.weather.database.HourlyForecast;
|
import org.woheller69.weather.database.HourlyForecast;
|
||||||
import org.woheller69.weather.database.SQLiteHelper;
|
import org.woheller69.weather.database.SQLiteHelper;
|
||||||
|
@ -69,7 +70,34 @@ public class CityWeatherAdapter extends RecyclerView.Adapter<CityWeatherAdapter.
|
||||||
|
|
||||||
// function update 3-hour or 1-hour forecast list
|
// function update 3-hour or 1-hour forecast list
|
||||||
public void updateForecastData(List<HourlyForecast> hourlyForecasts) {
|
public void updateForecastData(List<HourlyForecast> hourlyForecasts) {
|
||||||
|
if (hourlyForecasts.isEmpty()) return;
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
|
if (sp.getBoolean("pref_summarize",false)){
|
||||||
|
int cityId = hourlyForecasts.get(0).getCity_id();
|
||||||
|
ArrayList<Integer> CityIDList = new ArrayList<Integer>();
|
||||||
|
SQLiteHelper dbHelper = SQLiteHelper.getInstance(context.getApplicationContext());
|
||||||
|
hourlyForecasts = dbHelper.getForecastsByCityId(cityId); //get fresh values from database to make sure we do add new values to sum values from last update
|
||||||
|
List<CityToWatch> citiesToWatch = dbHelper.getAllCitiesToWatch();
|
||||||
|
CityToWatch requestedCity = dbHelper.getCityToWatch(cityId);
|
||||||
|
for (int i = 0; i < citiesToWatch.size(); i++) {
|
||||||
|
CityToWatch city = citiesToWatch.get(i);
|
||||||
|
if (city.getCityId()!=requestedCity.getCityId() && city.getLatitude() == requestedCity.getLatitude() && city.getLongitude() == requestedCity.getLongitude()) {
|
||||||
|
CityIDList.add(city.getCityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CityIDList.size()>0){
|
||||||
|
for (int c=0; c<CityIDList.size();c++) {
|
||||||
|
int iteratorCityId = CityIDList.get(c);
|
||||||
|
List<HourlyForecast> hfc = dbHelper.getForecastsByCityId(iteratorCityId);
|
||||||
|
if (hfc.size()!=hourlyForecasts.size()) break; //maybe something went wrong during update or city is not yet updated
|
||||||
|
for (int i=0;i<hfc.size();i++){
|
||||||
|
hourlyForecasts.get(i).setPower(hourlyForecasts.get(i).getPower()+hfc.get(i).getPower());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
courseDayList = new ArrayList<>();
|
courseDayList = new ArrayList<>();
|
||||||
|
|
||||||
for (HourlyForecast f : hourlyForecasts) {
|
for (HourlyForecast f : hourlyForecasts) {
|
||||||
|
@ -87,9 +115,33 @@ public class CityWeatherAdapter extends RecyclerView.Adapter<CityWeatherAdapter.
|
||||||
// function for week forecast list
|
// function for week forecast list
|
||||||
public void updateWeekForecastData(List<WeekForecast> forecasts) {
|
public void updateWeekForecastData(List<WeekForecast> forecasts) {
|
||||||
if (forecasts.isEmpty()) return;
|
if (forecasts.isEmpty()) return;
|
||||||
|
|
||||||
int cityId = forecasts.get(0).getCity_id();
|
int cityId = forecasts.get(0).getCity_id();
|
||||||
|
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
if (sp.getBoolean("pref_summarize",false)){
|
||||||
|
ArrayList<Integer> CityIDList = new ArrayList<Integer>();
|
||||||
|
SQLiteHelper dbHelper = SQLiteHelper.getInstance(context.getApplicationContext());
|
||||||
|
forecasts = dbHelper.getWeekForecastsByCityId(cityId); //get fresh values from database to make sure we do add new values to sum values from last update
|
||||||
|
List<CityToWatch> citiesToWatch = dbHelper.getAllCitiesToWatch();
|
||||||
|
CityToWatch requestedCity = dbHelper.getCityToWatch(cityId);
|
||||||
|
for (int i = 0; i < citiesToWatch.size(); i++) {
|
||||||
|
CityToWatch city = citiesToWatch.get(i);
|
||||||
|
if (city.getCityId()!=requestedCity.getCityId() && city.getLatitude() == requestedCity.getLatitude() && city.getLongitude() == requestedCity.getLongitude()) {
|
||||||
|
CityIDList.add(city.getCityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CityIDList.size()>0){
|
||||||
|
for (int c=0; c<CityIDList.size();c++) {
|
||||||
|
int iteratorCityId = CityIDList.get(c);
|
||||||
|
List<WeekForecast> wfc = dbHelper.getWeekForecastsByCityId(iteratorCityId);
|
||||||
|
if (wfc.size() != forecasts.size()) break; //maybe something went wrong during update or city is not yet updated
|
||||||
|
for (int i=0;i<wfc.size();i++){
|
||||||
|
forecasts.get(i).setEnergyDay(forecasts.get(i).getEnergyDay()+wfc.get(i).getEnergyDay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SQLiteHelper dbHelper = SQLiteHelper.getInstance(context.getApplicationContext());
|
SQLiteHelper dbHelper = SQLiteHelper.getInstance(context.getApplicationContext());
|
||||||
int zonemilliseconds = dbHelper.getGeneralDataByCityId(cityId).getTimeZoneSeconds() * 1000;
|
int zonemilliseconds = dbHelper.getGeneralDataByCityId(cityId).getTimeZoneSeconds() * 1000;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.woheller69.weather.services.UpdateDataService;
|
||||||
import org.woheller69.weather.ui.WeatherCityFragment;
|
import org.woheller69.weather.ui.WeatherCityFragment;
|
||||||
import org.woheller69.weather.ui.updater.IUpdateableCityUI;
|
import org.woheller69.weather.ui.updater.IUpdateableCityUI;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -35,18 +36,41 @@ public class WeatherPagerAdapter extends FragmentStateAdapter implements IUpdate
|
||||||
|
|
||||||
private List<CityToWatch> cities;
|
private List<CityToWatch> cities;
|
||||||
|
|
||||||
|
private boolean showSum;
|
||||||
|
|
||||||
public WeatherPagerAdapter(Context context, @NonNull FragmentManager supportFragmentManager, @NonNull Lifecycle lifecycle) {
|
public WeatherPagerAdapter(Context context, @NonNull FragmentManager supportFragmentManager, @NonNull Lifecycle lifecycle, Boolean showSum) {
|
||||||
super(supportFragmentManager,lifecycle);
|
super(supportFragmentManager,lifecycle);
|
||||||
this.mContext = context;
|
this.mContext = context;
|
||||||
this.database = SQLiteHelper.getInstance(context);
|
this.database = SQLiteHelper.getInstance(context);
|
||||||
|
this.showSum = showSum;
|
||||||
|
|
||||||
loadCities();
|
loadCities();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadCities() {
|
public void loadCities() {
|
||||||
this.cities = database.getAllCitiesToWatch();
|
List<CityToWatch> allCities = database.getAllCitiesToWatch();
|
||||||
Collections.sort(cities, (o1, o2) -> o1.getRank() - o2.getRank());
|
Collections.sort(allCities, (o1, o2) -> o1.getRank() - o2.getRank());
|
||||||
|
|
||||||
|
if (showSum && !allCities.isEmpty()) {
|
||||||
|
List<CityToWatch> citiesFiltered = new ArrayList<>();
|
||||||
|
citiesFiltered.add(allCities.get(0)); //always add first element
|
||||||
|
if (allCities.size() > 0) { //if there is more than one element
|
||||||
|
for (int i = 1; i < allCities.size(); i++) {
|
||||||
|
boolean alreadyHasLatLon = false;
|
||||||
|
for (int j = 0; j < citiesFiltered.size(); j++) {
|
||||||
|
if (citiesFiltered.get(j).getLatitude() == allCities.get(i).getLatitude() && citiesFiltered.get(j).getLongitude() == allCities.get(i).getLongitude()) {
|
||||||
|
alreadyHasLatLon = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!alreadyHasLatLon) {
|
||||||
|
citiesFiltered.add(allCities.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cities = citiesFiltered;
|
||||||
|
} else {
|
||||||
|
this.cities = allCities;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -64,7 +88,19 @@ public class WeatherPagerAdapter extends FragmentStateAdapter implements IUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getPageTitle(int position) {
|
public CharSequence getPageTitle(int position) {
|
||||||
return cities.get(position).getCityName();
|
String title;
|
||||||
|
if (showSum){
|
||||||
|
String name = cities.get(position).getCityName();
|
||||||
|
if (name.contains("|")){
|
||||||
|
String[] name2 = name.split("\\|");
|
||||||
|
title = name2[0];
|
||||||
|
} else {
|
||||||
|
title = cities.get(position).getCityName();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title = cities.get(position).getCityName();
|
||||||
|
}
|
||||||
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refreshSingleData(Context context, Boolean asap, int cityId) {
|
public static void refreshSingleData(Context context, Boolean asap, int cityId) {
|
||||||
|
@ -106,14 +142,4 @@ public class WeatherPagerAdapter extends FragmentStateAdapter implements IUpdate
|
||||||
return -1; //item not found
|
return -1; //item not found
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getLatForPos(int pos) {
|
|
||||||
CityToWatch city = cities.get(pos);
|
|
||||||
return city.getLatitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getLonForPos(int pos) {
|
|
||||||
CityToWatch city = cities.get(pos);
|
|
||||||
return city.getLongitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,15 +1,18 @@
|
||||||
package org.woheller69.weather.weather_api.open_meteo;
|
package org.woheller69.weather.weather_api.open_meteo;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import com.android.volley.VolleyError;
|
import com.android.volley.VolleyError;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.woheller69.weather.R;
|
import org.woheller69.weather.R;
|
||||||
import org.woheller69.weather.activities.NavigationActivity;
|
import org.woheller69.weather.activities.NavigationActivity;
|
||||||
|
import org.woheller69.weather.database.CityToWatch;
|
||||||
import org.woheller69.weather.database.GeneralData;
|
import org.woheller69.weather.database.GeneralData;
|
||||||
import org.woheller69.weather.database.HourlyForecast;
|
import org.woheller69.weather.database.HourlyForecast;
|
||||||
import org.woheller69.weather.database.WeekForecast;
|
import org.woheller69.weather.database.WeekForecast;
|
||||||
|
@ -62,66 +65,88 @@ public class ProcessOMweatherAPIRequest implements IProcessHttpRequest {
|
||||||
public void processSuccessScenario(String response, int cityId) {
|
public void processSuccessScenario(String response, int cityId) {
|
||||||
|
|
||||||
IDataExtractor extractor = new OMDataExtractor(context);
|
IDataExtractor extractor = new OMDataExtractor(context);
|
||||||
try {
|
|
||||||
JSONObject json = new JSONObject(response);
|
|
||||||
|
|
||||||
//Extract daily weather
|
|
||||||
dbHelper.deleteWeekForecastsByCityId(cityId);
|
|
||||||
List<WeekForecast> weekforecasts = new ArrayList<>();
|
|
||||||
weekforecasts = extractor.extractWeekForecast(json.getString("daily"));
|
|
||||||
|
|
||||||
if (weekforecasts!=null && !weekforecasts.isEmpty()){
|
ArrayList<Integer> CityIDList = new ArrayList<Integer>();
|
||||||
for (WeekForecast weekForecast: weekforecasts){
|
|
||||||
weekForecast.setCity_id(cityId);
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
if (sharedPreferences.getBoolean("pref_summarize",false)){
|
||||||
|
List<CityToWatch> citiesToWatch = dbHelper.getAllCitiesToWatch();
|
||||||
|
CityToWatch requestedCity = dbHelper.getCityToWatch(cityId);
|
||||||
|
for (int i = 0; i < citiesToWatch.size(); i++) {
|
||||||
|
CityToWatch city = citiesToWatch.get(i);
|
||||||
|
if (city.getCityId()!=requestedCity.getCityId() && city.getLatitude() == requestedCity.getLatitude() && city.getLongitude() == requestedCity.getLongitude()) {
|
||||||
|
CityIDList.add(city.getCityId());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
final String ERROR_MSG = context.getResources().getString(R.string.error_convert_to_json);
|
|
||||||
if (NavigationActivity.isVisible)
|
|
||||||
Toast.makeText(context, ERROR_MSG, Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Extract current weather
|
CityIDList.add(cityId); //add requested city at end of list. Call Viewupdater if last (requested) city is updated
|
||||||
GeneralData generalData = new GeneralData();
|
|
||||||
generalData.setTimestamp(System.currentTimeMillis() / 1000);
|
|
||||||
generalData.setCity_id(cityId);
|
|
||||||
generalData.setTimeSunrise(weekforecasts.get(0).getTimeSunrise());
|
|
||||||
generalData.setTimeSunset(weekforecasts.get(0).getTimeSunset());
|
|
||||||
generalData.setTimeZoneSeconds(json.getInt("utc_offset_seconds"));
|
|
||||||
GeneralData current = dbHelper.getGeneralDataByCityId(cityId);
|
|
||||||
if (current != null && current.getCity_id() == cityId) {
|
|
||||||
dbHelper.updateGeneralData(generalData);
|
|
||||||
} else {
|
|
||||||
dbHelper.addGeneralData(generalData);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Extract hourly weather
|
for (int c=0; c<CityIDList.size();c++) {
|
||||||
dbHelper.deleteForecastsByCityId(cityId);
|
cityId = CityIDList.get(c);
|
||||||
List<HourlyForecast> hourlyforecasts = new ArrayList<>();
|
|
||||||
hourlyforecasts = extractor.extractHourlyForecast(json.getString("hourly"), cityId);
|
|
||||||
|
|
||||||
if (hourlyforecasts!=null && !hourlyforecasts.isEmpty()){
|
try {
|
||||||
for (HourlyForecast hourlyForecast: hourlyforecasts){
|
JSONObject json = new JSONObject(response);
|
||||||
hourlyForecast.setCity_id(cityId);
|
|
||||||
|
//Extract daily weather
|
||||||
|
dbHelper.deleteWeekForecastsByCityId(cityId);
|
||||||
|
List<WeekForecast> weekforecasts = new ArrayList<>();
|
||||||
|
weekforecasts = extractor.extractWeekForecast(json.getString("daily"));
|
||||||
|
|
||||||
|
if (weekforecasts != null && !weekforecasts.isEmpty()) {
|
||||||
|
for (WeekForecast weekForecast : weekforecasts) {
|
||||||
|
weekForecast.setCity_id(cityId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String ERROR_MSG = context.getResources().getString(R.string.error_convert_to_json);
|
||||||
|
if (NavigationActivity.isVisible)
|
||||||
|
Toast.makeText(context, ERROR_MSG, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
final String ERROR_MSG = context.getResources().getString(R.string.error_convert_to_json);
|
//Extract current weather
|
||||||
if (NavigationActivity.isVisible)
|
GeneralData generalData = new GeneralData();
|
||||||
Toast.makeText(context, ERROR_MSG, Toast.LENGTH_LONG).show();
|
generalData.setTimestamp(System.currentTimeMillis() / 1000);
|
||||||
return;
|
generalData.setCity_id(cityId);
|
||||||
|
generalData.setTimeSunrise(weekforecasts.get(0).getTimeSunrise());
|
||||||
|
generalData.setTimeSunset(weekforecasts.get(0).getTimeSunset());
|
||||||
|
generalData.setTimeZoneSeconds(json.getInt("utc_offset_seconds"));
|
||||||
|
GeneralData current = dbHelper.getGeneralDataByCityId(cityId);
|
||||||
|
if (current != null && current.getCity_id() == cityId) {
|
||||||
|
dbHelper.updateGeneralData(generalData);
|
||||||
|
} else {
|
||||||
|
dbHelper.addGeneralData(generalData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Extract hourly weather
|
||||||
|
dbHelper.deleteForecastsByCityId(cityId);
|
||||||
|
List<HourlyForecast> hourlyforecasts = new ArrayList<>();
|
||||||
|
hourlyforecasts = extractor.extractHourlyForecast(json.getString("hourly"), cityId);
|
||||||
|
|
||||||
|
if (hourlyforecasts != null && !hourlyforecasts.isEmpty()) {
|
||||||
|
for (HourlyForecast hourlyForecast : hourlyforecasts) {
|
||||||
|
hourlyForecast.setCity_id(cityId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String ERROR_MSG = context.getResources().getString(R.string.error_convert_to_json);
|
||||||
|
if (NavigationActivity.isVisible)
|
||||||
|
Toast.makeText(context, ERROR_MSG, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dbHelper.addForecasts(hourlyforecasts);
|
||||||
|
|
||||||
|
weekforecasts = reanalyzeWeekIDs(weekforecasts, hourlyforecasts);
|
||||||
|
|
||||||
|
dbHelper.addWeekForecasts(weekforecasts);
|
||||||
|
|
||||||
|
if (c == CityIDList.size()-1) ViewUpdater.updateGeneralDataData(generalData); // Call Viewupdater if last (requested) city is updated
|
||||||
|
if (c == CityIDList.size()-1) ViewUpdater.updateWeekForecasts(weekforecasts);
|
||||||
|
if (c == CityIDList.size()-1) ViewUpdater.updateForecasts(hourlyforecasts);
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
dbHelper.addForecasts(hourlyforecasts);
|
|
||||||
|
|
||||||
weekforecasts = reanalyzeWeekIDs(weekforecasts, hourlyforecasts);
|
|
||||||
|
|
||||||
dbHelper.addWeekForecasts(weekforecasts);
|
|
||||||
|
|
||||||
ViewUpdater.updateGeneralDataData(generalData);
|
|
||||||
ViewUpdater.updateWeekForecasts(weekforecasts);
|
|
||||||
ViewUpdater.updateForecasts(hourlyforecasts);
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,9 @@
|
||||||
<string name="permission_message">%s benötigt Zugriff auf den externen Speicher. Bitte die Berechtigung erteilen und erneut versuchen.</string>
|
<string name="permission_message">%s benötigt Zugriff auf den externen Speicher. Bitte die Berechtigung erteilen und erneut versuchen.</string>
|
||||||
<string name="toast_delete">Bitte die Datei zuerst löschen und erneut versuchen.</string>
|
<string name="toast_delete">Bitte die Datei zuerst löschen und erneut versuchen.</string>
|
||||||
<string name="restore_database_message">Daten aus dem Dokumentenordner wiederherstellen. Falls nötig, Ordner \'Documents\' öffnen und solXpect.zip auswählen!</string>
|
<string name="restore_database_message">Daten aus dem Dokumentenordner wiederherstellen. Falls nötig, Ordner \'Documents\' öffnen und solXpect.zip auswählen!</string>
|
||||||
|
<string name="settings_summarize">Summe anzeigen</string>
|
||||||
|
<string name="summary_summarize">Summiere die Werte aller Module mit gleichem Längen- und Breitengrad.</string>
|
||||||
|
<string name="dialog_add_clone_button">Klonen</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -105,4 +105,7 @@
|
||||||
<string name="permission_message">%s needs access to external storage. Please accept permission and try again.</string>
|
<string name="permission_message">%s needs access to external storage. Please accept permission and try again.</string>
|
||||||
<string name="toast_delete">Please delete file and try again</string>
|
<string name="toast_delete">Please delete file and try again</string>
|
||||||
<string name="restore_database_message">Restore Data from Documents folder. Open folder \'Documents\' and select solXpect.zip if needed!</string>
|
<string name="restore_database_message">Restore Data from Documents folder. Open folder \'Documents\' and select solXpect.zip if needed!</string>
|
||||||
|
<string name="settings_summarize">Show sum</string>
|
||||||
|
<string name="summary_summarize">Summarize values of modules at the same latitude and longitude.</string>
|
||||||
|
<string name="dialog_add_clone_button">Clone</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -11,6 +11,13 @@
|
||||||
app:showSeekBarValue="true"
|
app:showSeekBarValue="true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="pref_summarize"
|
||||||
|
android:title="@string/settings_summarize"
|
||||||
|
android:summary="@string/summary_summarize"
|
||||||
|
android:defaultValue="false"
|
||||||
|
/>
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="pref_TimeFormat"
|
android:key="pref_TimeFormat"
|
||||||
android:title="@string/settings_time24h"
|
android:title="@string/settings_time24h"
|
||||||
|
|
2
fastlane/metadata/android/en-US/changelogs/14.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/14.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Add option to show sum of all modules with same latitude/longitude
|
||||||
|
Add option to clone location
|
Loading…
Add table
Add a link
Reference in a new issue