diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cmfwatchpro/CmfWatchProSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cmfwatchpro/CmfWatchProSupport.java index 70be70761..85a7b5f2e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cmfwatchpro/CmfWatchProSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/cmfwatchpro/CmfWatchProSupport.java @@ -27,6 +27,10 @@ import android.net.Uri; import android.os.Build; import android.widget.Toast; +import net.e175.klaus.solarpositioning.DeltaT; +import net.e175.klaus.solarpositioning.SPA; +import net.e175.klaus.solarpositioning.SunriseTransitSet; + import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -39,6 +43,7 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.util.ArrayList; import java.util.Calendar; +import java.util.GregorianCalendar; import java.util.TimeZone; import java.util.UUID; @@ -618,8 +623,9 @@ public class CmfWatchProSupport extends AbstractBTLEDeviceSupport implements Cmf // Each weather entry takes up 9 bytes // There are 7 of those weather entries - 7*9 bytes // Then there are 24-hour entries of temp and weather condition (2 bytes each) - // Then finally the location name as bytes - allow for 30 bytes, watch auto-scrolls - final ByteBuffer buf = ByteBuffer.allocate((7 * 9) + (24 * 2) + 30).order(ByteOrder.BIG_ENDIAN); + // Then the location name as bytes - allow for 31 bytes, watch auto-scrolls. Pad it to 32 bytes + // Then finally the sunrise / sunset pairs, for 7 days (7*8) + final ByteBuffer buf = ByteBuffer.allocate((7 * 9) + (24 * 2) + 32 + (7 * 8)).order(ByteOrder.BIG_ENDIAN); // start with the current day's weather buf.put(Weather.mapToCmfCondition(weatherSpec.currentConditionCode)); buf.put((byte) (weatherSpec.currentTemp - 273 + 100)); // convert Kelvin to C, add 100 @@ -669,11 +675,53 @@ public class CmfWatchProSupport extends AbstractBTLEDeviceSupport implements Cmf buf.put((byte) (Weather.mapToCmfCondition(weatherSpec.currentConditionCode))); // current condition } } - // place name - watch scrolls after ~10 chars - buf.put(StringUtils.truncate(weatherSpec.location, 30).getBytes(StandardCharsets.UTF_8)); + // place name - watch scrolls after ~10 chars. Pad up to 32 bytes. + final byte[] locationNameBytes = nodomain.freeyourgadget.gadgetbridge.util.StringUtils.truncateToBytes(weatherSpec.location, 31); + buf.put(locationNameBytes); + buf.put(new byte[32 - locationNameBytes.length]); + + // Sunrise / sunset + buf.order(ByteOrder.LITTLE_ENDIAN); // why... + final Location location = weatherSpec.getLocation() != null ? weatherSpec.getLocation() : new CurrentPosition().getLastKnownLocation(); + final GregorianCalendar sunriseDate = new GregorianCalendar(); + + if (weatherSpec.sunRise != 0 && weatherSpec.sunSet != 0) { + buf.putInt(weatherSpec.sunRise); + buf.putInt(weatherSpec.sunSet); + } else { + putSunriseSunset(buf, location, sunriseDate); + } + + for (int i = 0; i < 6; i++) { + sunriseDate.add(Calendar.DAY_OF_MONTH, 1); + if (i < weatherSpec.forecasts.size() && weatherSpec.forecasts.get(i).sunRise != 0 && weatherSpec.forecasts.get(i).sunSet != 0) { + buf.putInt(weatherSpec.forecasts.get(i).sunRise); + buf.putInt(weatherSpec.forecasts.get(i).sunSet); + } else { + putSunriseSunset(buf, location, sunriseDate); + } + } + sendCommand("send weather", CmfCommand.WEATHER_SET_1, buf.array()); } + private void putSunriseSunset(final ByteBuffer buf, final Location location, final GregorianCalendar date) { + final SunriseTransitSet sunriseTransitSet = SPA.calculateSunriseTransitSet( + date.toZonedDateTime(), + location.getLatitude(), + location.getLongitude(), + DeltaT.estimate(date.toZonedDateTime().toLocalDate()) + ); + + if (sunriseTransitSet.getSunrise() != null && sunriseTransitSet.getSunset() != null) { + buf.putInt((int) sunriseTransitSet.getSunrise().toInstant().getEpochSecond()); + buf.putInt((int) sunriseTransitSet.getSunset().toInstant().getEpochSecond()); + } else { + buf.putInt(0); + buf.putInt(0); + } + } + @Override public void onTestNewFunction() {