From 014b180a300f0bcfe9044d4c9a7dd366c78c7139 Mon Sep 17 00:00:00 2001 From: Thomas Kuehne Date: Mon, 28 Jul 2025 14:30:59 +0200 Subject: [PATCH] igsport: rebase device code to master ad34fec706418e21acc5078c9ebb351be70238b2 --- .../igpsport/IGPSportAbstractCoordinator.java | 22 ++++++- .../igpsport/IGPSportRouteInstallHandler.java | 26 ++++++++ .../igpsport/IGPSportiGS630Coordinator.java | 19 +++++- .../gadgetbridge/model/DeviceType.java | 4 ++ .../igpsport/IGPSportDeviceSupport.java | 63 ++++++++++--------- .../igpsport/IGPSportDownloadManager.java | 18 +++++- .../igpsport/IGPSportRoutesManager.java | 32 +++++++--- .../devices/igpsport/IGPSportWeather.java | 54 ++++++++++------ app/src/main/res/values/strings.xml | 5 ++ 9 files changed, 183 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportAbstractCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportAbstractCoordinator.java index be1f6601eb..2a4d7c38a5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportAbstractCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportAbstractCoordinator.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.devices.igpsport; import android.app.Activity; @@ -49,7 +65,7 @@ public abstract class IGPSportAbstractCoordinator extends AbstractBLEDeviceCoord } @Override - public boolean supportsActivityTracks() { + public boolean supportsActivityTracks(final GBDevice device) { return true; } @@ -59,12 +75,12 @@ public abstract class IGPSportAbstractCoordinator extends AbstractBLEDeviceCoord } @Override - public boolean supportsAppListFetching() { + public boolean supportsAppListFetching(final GBDevice device) { return true; } @Override - public Class getAppsManagementActivity() { + public Class getAppsManagementActivity(final GBDevice device) { return AppManagerActivity.class; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportRouteInstallHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportRouteInstallHandler.java index eabb4b8d01..14e4b8ecbc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportRouteInstallHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportRouteInstallHandler.java @@ -1,8 +1,27 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.devices.igpsport; +import android.app.Activity; import android.content.Context; import android.net.Uri; +import androidx.annotation.NonNull; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +33,7 @@ import java.util.Arrays; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.FwAppInstallerActivity; import nodomain.freeyourgadget.gadgetbridge.activities.InstallActivity; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; @@ -62,6 +82,12 @@ public class IGPSportRouteInstallHandler implements InstallHandler { } } + @NonNull + @Override + public Class getInstallActivity() { + return FwAppInstallerActivity.class; + } + @Override public boolean isValid() { if (routeExtensions.contains(extension)) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportiGS630Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportiGS630Coordinator.java index c6cdbb39d3..678c51b786 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportiGS630Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/igpsport/IGPSportiGS630Coordinator.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.devices.igpsport; import org.slf4j.Logger; @@ -6,6 +22,7 @@ import org.slf4j.LoggerFactory; import java.util.regex.Pattern; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; public class IGPSportiGS630Coordinator extends IGPSportAbstractCoordinator { private static final Logger LOG = LoggerFactory.getLogger(IGPSportiGS630Coordinator.class); @@ -21,7 +38,7 @@ public class IGPSportiGS630Coordinator extends IGPSportAbstractCoordinator { } @Override - public boolean supportsWeather() { + public boolean supportsWeather(final GBDevice device) { return true; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java index 4cc38ad56f..ef71468e10 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -316,6 +316,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchultimate.H import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchultimate2.HuaweiWatchUltimate2Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.id115.ID115Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.idasen.IdasenCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.igpsport.IGPSportBSC200Coordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.igpsport.IGPSportiGS630Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.itag.ITagCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.jyou.BFH16DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.jyou.TeclastH30.TeclastH30Coordinator; @@ -941,6 +943,8 @@ public enum DeviceType { SANITAS_SBM_67(SanitasSBM67Coordinator.class), SILVERCREST_SBM_67(SilverCrestSBM67Coordinator.class), BRAUN_BPW4500(BraunBPW4500DeviceCoordinator.class), + IGPSPORT_BSC200(IGPSportBSC200Coordinator.class), + IGPSPORT_IGS630(IGPSportiGS630Coordinator.class), TEST(TestDeviceCoordinator.class); private DeviceCoordinator coordinator; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDeviceSupport.java index e6142f92f5..cef1ce29c5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDeviceSupport.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.igpsport; @@ -8,8 +24,11 @@ import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.content.Intent; import android.net.Uri; +import android.os.Bundle; import android.widget.Toast; +import androidx.annotation.NonNull; + import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -47,11 +66,9 @@ import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Firmware; import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Ins; import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.PeripheralCommon; import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.RoutePlan; -import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLESingleDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; -import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; -import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.IntentListener; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfo; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfoProfile; @@ -63,7 +80,7 @@ import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Common; import nodomain.freeyourgadget.gadgetbridge.proto.igpsport.Factory; -public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { +public class IGPSportDeviceSupport extends AbstractBTLESingleDeviceSupport { private static final Logger LOG = LoggerFactory.getLogger(IGPSportDeviceSupport.class); public BluetoothGattCharacteristic readCharacteristic; @@ -147,7 +164,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { @Override protected TransactionBuilder initializeDevice(TransactionBuilder builder) { // mark the device as initializing - builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); + builder.setDeviceState(GBDevice.State.INITIALIZING); readCharacteristic = getCharacteristic(IGPSportConstants.UUID_IGPSPORT_CHARACTERISTIC_FIRST_RX); writeCharacteristic = getCharacteristic(IGPSportConstants.UUID_IGPSPORT_CHARACTERISTIC_FIRST_TX); writeCharacteristicThird = getCharacteristic(IGPSportConstants.UUID_IGPSPORT_CHARACTERISTIC_THIRD_TX); @@ -201,7 +218,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { getDevice().setFirmwareVersion2("N/A"); // mark the device as initialized - builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext())); + builder.setDeviceState(GBDevice.State.INITIALIZED); return builder; } @@ -323,25 +340,15 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { if (mainOperation == Common.SERVICE_OPERATE_TYPE.enum_SERVICE_OPERATE_TYPE_ADD_VALUE) { gbDevice.unsetBusyTask(); gbDevice.sendDeviceUpdateIntent(getContext()); - TransactionBuilder builder = new TransactionBuilder("Route upload finished"); + TransactionBuilder builder = createTransactionBuilder("Route upload finished"); if (result == 0) { - builder.add(new SetProgressAction( - "Route upload completed", - false, - 100, - getContext() - )); + builder.setProgress(R.string.route_upload_completed, false, 100); handleGBDeviceEvent(new GBDeviceEventDisplayMessage("Route upload completed", Toast.LENGTH_LONG, GB.INFO)); } else { - builder.add(new SetProgressAction( - "Route upload failed", - false, - 0, - getContext() - )); + builder.setProgress(R.string.route_upload_failed, false, 0); handleGBDeviceEvent(new GBDeviceEventDisplayMessage("Failed to upload route", Toast.LENGTH_LONG, GB.ERROR)); } - builder.queue(getQueue()); + builder.queue(); } break; @@ -476,7 +483,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onNotification(NotificationSpec notificationSpec) { LOG.debug("iGPSport notification: " + notificationSpec.type); - TransactionBuilder builder = new TransactionBuilder("notification"); + TransactionBuilder builder = createTransactionBuilder("notification"); Ins.ins_msg.Builder insMsgBuilder = Ins.ins_msg.newBuilder(); insMsgBuilder.setServiceType(Common.service_type_index.enum_SERVICE_TYPE_INDEX_INS); @@ -501,13 +508,13 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { insMsgBuilder.setInsDataMsg(insDataMsgBuilder); byte[] callData = craftData(insMsgBuilder.getServiceType().getNumber(), insMsgBuilder.getInsServiceType().getNumber(), insMsgBuilder.getInsOperateType().getNumber(), insMsgBuilder.build().toByteArray()); builder.write(writeCharacteristic, callData); - builder.queue(getQueue()); + builder.queue(); } @Override public void onSetCallState(CallSpec callSpec) { LOG.debug("iGPSport send call notification"); - TransactionBuilder builder = new TransactionBuilder("CALL"); + TransactionBuilder builder = createTransactionBuilder("CALL"); Ins.ins_msg.Builder insMsgBuilder = Ins.ins_msg.newBuilder(); insMsgBuilder.setServiceType(Common.service_type_index.enum_SERVICE_TYPE_INDEX_INS); insMsgBuilder.setInsServiceType(Ins.INS_SERVICE_TYPE.enum_INS_SERVICE_TYPE_CALL); @@ -529,7 +536,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { insMsgBuilder.setInsDataMsg(insDataMsgBuilder); byte[] callData = craftData(insMsgBuilder.getServiceType().getNumber(), insMsgBuilder.getInsServiceType().getNumber(), insMsgBuilder.getInsOperateType().getNumber(), insMsgBuilder.build().toByteArray()); builder.write(writeCharacteristic, callData); - builder.queue(getQueue()); + builder.queue(); } @Override @@ -545,7 +552,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { byte[] cycleDataMsgBytes = craftData(cycleDataMsg.getServiceType().getNumber(), 0xff, cycleDataMsg.getCyclingDataOperateType().getNumber(), cycleDataMsg.build().toByteArray(), true); builder.write(writeCharacteristicThird, cycleDataMsgBytes); - builder.queue(getQueue()); + builder.queue(); } @@ -566,7 +573,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { setMeasurementSystem(builder); break; } - builder.queue(getQueue()); + builder.queue(); } catch (IOException e) { GB.toast(getContext(), "Error sending configuration: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } @@ -627,7 +634,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { } @Override - public void onInstallApp(Uri uri) { + public void onInstallApp(Uri uri, @NonNull final Bundle options) { //final IGPSportGpxRouteInstallHandler gpxRouteHandler = new IGPSportGpxRouteInstallHandler(uri, getContext()); final IGPSportRouteInstallHandler routeHandler = new IGPSportRouteInstallHandler(uri, getContext()); if (routeHandler.isValid()) { @@ -665,7 +672,7 @@ public class IGPSportDeviceSupport extends AbstractBTLEDeviceSupport { private void handleWeather() { // Send weather - final ArrayList specs = new ArrayList<>(nodomain.freeyourgadget.gadgetbridge.model.Weather.getInstance().getWeatherSpecs()); + final ArrayList specs = new ArrayList<>(nodomain.freeyourgadget.gadgetbridge.model.weather.Weather.getWeatherSpecs()); if (!specs.isEmpty()) { weatherManager.handleWeather(specs.get(0)); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDownloadManager.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDownloadManager.java index b55a9590f0..786301eb4c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDownloadManager.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportDownloadManager.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.igpsport; import com.google.protobuf.InvalidProtocolBufferException; @@ -68,7 +84,7 @@ public class IGPSportDownloadManager { byte[] cycleDataMsgBytes = IGPSportDeviceSupport.craftData(cycleDataMsg.getServiceType().getNumber(), 0xff, cycleDataMsg.getCyclingDataOperateType().getNumber(), cycleDataMsg.build().toByteArray(), true); builder.write(support.writeCharacteristicThird, cycleDataMsgBytes); - builder.queue(support.getQueue()); + builder.queue(); // } else { // syncNextFile(); // } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportRoutesManager.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportRoutesManager.java index eff426064b..ba330da49b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportRoutesManager.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportRoutesManager.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.igpsport; import android.widget.Toast; @@ -14,6 +30,7 @@ import java.util.List; import java.util.Random; import java.util.UUID; +import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo; import nodomain.freeyourgadget.gadgetbridge.devices.igpsport.IGPSportRouteInstallHandler; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp; @@ -109,9 +126,8 @@ public class IGPSportRoutesManager { fileOperationbuilder.build().toByteArray(), handler.getBytes()); builder.writeChunkedData(support.writeCharacteristicFourth, fileOperationBytes, support.getMTU()); - support.getDevice().setBusyTask("Installing route"); - support.getDevice().sendDeviceUpdateIntent(support.getContext()); - builder.queue(support.getQueue()); + builder.setBusyTask(R.string.task_installing_route); + builder.queue(); } catch (final Exception e) { GB.toast(support.getContext(), "Gpx install error: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); @@ -129,7 +145,7 @@ public class IGPSportRoutesManager { byte[] routePlanBytes = support.craftData(routePlanBuilder.getServiceType().getNumber(), 0xff, routePlanBuilder.getRoutePlanOperateType().getNumber(), routePlanBuilder.build().toByteArray()); builder.write(support.writeCharacteristicFourth, routePlanBytes); - builder.queue(support.getQueue()); + builder.queue(); } catch (IOException e) { GB.toast(support.getContext(), "Gpx get list error: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); @@ -191,7 +207,7 @@ public class IGPSportRoutesManager { private void requestFiles() { int endFile = (fileNumber > fileListSupportNumMax ? fileListSupportNumMax - 1 : fileNumber)+startFile; - TransactionBuilder builder = new TransactionBuilder("get files list"); + TransactionBuilder builder = support.createTransactionBuilder("get files list"); RoutePlan.route_plan_data_msg.Builder routePlan2ndBuilder = RoutePlan.route_plan_data_msg.newBuilder(); @@ -205,7 +221,7 @@ public class IGPSportRoutesManager { fileNumber -= fileListSupportNumMax; builder.write(support.writeCharacteristicFourth, routePlan2ndBytes); - builder.queue(support.getQueue()); + builder.queue(); } public void handleRouteNumber(byte[] pbData) throws InvalidProtocolBufferException { @@ -235,7 +251,7 @@ public class IGPSportRoutesManager { routePlanBuilder.addRoutePlanInfoMsg(installedRouteHash.get(uuid).toMessage()); byte[] routePlanBytes = support.craftData(routePlanBuilder.getServiceType().getNumber(), 0xff, routePlanBuilder.getRoutePlanOperateType().getNumber(), routePlanBuilder.build().toByteArray()); builder.write(support.writeCharacteristicFourth, routePlanBytes); - builder.queue(support.getQueue()); + builder.queue(); } catch (IOException e) { GB.toast(support.getContext(), "Failed to start gpx navigation: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); } @@ -250,7 +266,7 @@ public class IGPSportRoutesManager { routePlanBuilder.addRoutePlanInfoMsg(installedRouteHash.get(uuid).toMessage()); byte[] routePlanBytes = support.craftData(routePlanBuilder.getServiceType().getNumber(), 0xff, routePlanBuilder.getRoutePlanOperateType().getNumber(), routePlanBuilder.build().toByteArray()); builder.write(support.writeCharacteristicFourth, routePlanBytes); - builder.queue(support.getQueue()); + builder.queue(); } catch (IOException e) { GB.toast(support.getContext(), "Failed to delete gpx navigation: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportWeather.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportWeather.java index 60c653ac34..4eb7656b6e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportWeather.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/igpsport/IGPSportWeather.java @@ -1,3 +1,19 @@ +/* Copyright (C) 2025 Vitaliy Tomin, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.igpsport; import java.io.IOException; @@ -119,27 +135,27 @@ public class IGPSportWeather { TransactionBuilder builder = support.performInitialized("set weather"); Back.back_msg.Builder weatherMsg = Back.back_msg.newBuilder(); Back.weather_current_data_message.Builder currentWeatherMsg =Back.weather_current_data_message.newBuilder(); - currentWeatherMsg.setCurDayMinTemp(weatherSpec.todayMinTemp-273); - currentWeatherMsg.setCurDayMaxTemp(weatherSpec.todayMaxTemp-273); - currentWeatherMsg.setCurTemperature(weatherSpec.currentTemp-273); - currentWeatherMsg.setCurWeather(IGPSportWeather.convertOWMtoQWeather(weatherSpec.currentConditionCode)); - currentWeatherMsg.setWindDeg(String.valueOf(weatherSpec.windDirection)); - currentWeatherMsg.setWindSpd(String.valueOf(Math.round(weatherSpec.windSpeed))); + currentWeatherMsg.setCurDayMinTemp(weatherSpec.getTodayMinTemp()-273); + currentWeatherMsg.setCurDayMaxTemp(weatherSpec.getTodayMaxTemp()-273); + currentWeatherMsg.setCurTemperature(weatherSpec.getCurrentTemp()-273); + currentWeatherMsg.setCurWeather(IGPSportWeather.convertOWMtoQWeather(weatherSpec.getCurrentConditionCode())); + currentWeatherMsg.setWindDeg(String.valueOf(weatherSpec.getWindDirection())); + currentWeatherMsg.setWindSpd(String.valueOf(Math.round(weatherSpec.getWindSpeed()))); currentWeatherMsg.setTime(formatterHourly.format(currentTime)); int currentDay=0; - for (final WeatherSpec.Daily forecast : weatherSpec.forecasts) { + for (final WeatherSpec.Daily forecast : weatherSpec.getForecasts()) { LocalDateTime now = LocalDateTime.now(); currentDay++; LocalDateTime tomorrow = now.plusDays(currentDay); DateTimeFormatter formatterDaily = DateTimeFormatter.ISO_LOCAL_DATE; //"yyyy-MM-dd" weatherMsg.addThreeDaysMsg(Back.weather_three_days_data_message.newBuilder() - .setWeatherIndex(IGPSportWeather.convertOWMtoQWeather(forecast.conditionCode)) - .setRainProb(forecast.precipProbability) - .setMaxTemp(forecast.maxTemp-273) - .setMinTemp(forecast.minTemp-273) + .setWeatherIndex(IGPSportWeather.convertOWMtoQWeather(forecast.getConditionCode())) + .setRainProb(forecast.getPrecipProbability()) + .setMaxTemp(forecast.getMaxTemp()-273) + .setMinTemp(forecast.getMinTemp()-273) .setDate(tomorrow.format(formatterDaily)).build()); if (currentDay > 2) //we only need 3 days @@ -147,14 +163,14 @@ public class IGPSportWeather { } int currentHour=0; - for (final WeatherSpec.Hourly hourly : weatherSpec.hourly) { + for (final WeatherSpec.Hourly hourly : weatherSpec.getHourly()) { weatherMsg.addThreeHoursMsg(Back.weather_three_hour_data_memsage.newBuilder() - .setWatherIndex(IGPSportWeather.convertOWMtoQWeather(hourly.conditionCode)) - .setRainProb(hourly.precipProbability) - .setTemp(hourly.temp-273) - .setTime(formatterHourly.format(Instant.ofEpochMilli(hourly.timestamp * 1000L))) - .setWindDeg(String.valueOf(hourly.windDirection)) - .setWindSpd(String.valueOf(Math.round(hourly.windSpeed))).build()); + .setWatherIndex(IGPSportWeather.convertOWMtoQWeather(hourly.getConditionCode())) + .setRainProb(hourly.getPrecipProbability()) + .setTemp(hourly.getTemp()-273) + .setTime(formatterHourly.format(Instant.ofEpochMilli(hourly.getTimestamp() * 1000L))) + .setWindDeg(String.valueOf(hourly.getWindDirection())) + .setWindSpd(String.valueOf(Math.round(hourly.getWindSpeed()))).build()); currentHour++; if (currentHour > 3 ) // its called three hour weather but shows actually 4 entries @@ -174,7 +190,7 @@ public class IGPSportWeather { weatherMsg.getBackOperateType().getNumber(), weatherMsg.build().toByteArray()); builder.writeChunkedData(support.writeCharacteristicFourth, weatherBytes, support.getMTU()); - builder.queue(support.getQueue()); + builder.queue(); } catch (IOException e) { throw new RuntimeException(e); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c057802467..8a947668cb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2250,6 +2250,11 @@ EarFun Air S EarFun Air Pro 4 ATC_BLE_OEPL + IGPSPORT BSC200 + IGPSPORT iGS630 + Installing route + Route upload completed + Route upload failed Choose export location General High-priority