diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
index 422dc6afde..90d78a701f 100644
--- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
+++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java
@@ -58,7 +58,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
- final Schema schema = new Schema(112, MAIN_PACKAGE + ".entities");
+ final Schema schema = new Schema(113, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@@ -211,6 +211,7 @@ public class GBDaoGenerator {
addGenericSleepStageSample(schema, user, device);
addGenericTrainingLoadAcuteSample(schema, user, device);
addGenericTrainingLoadChronicSample(schema, user, device);
+ addGenericWeightSample(schema, user, device);
new DaoGenerator().generateAll(schema, "app/src/main/java");
}
@@ -1967,4 +1968,11 @@ public class GBDaoGenerator {
sample.addIntProperty("value").notNull();
return sample;
}
+
+ private static Entity addGenericWeightSample(Schema schema, Entity user, Entity device) {
+ Entity sample = addEntity(schema, "GenericWeightSample");
+ addCommonTimeSampleProperties("AbstractWeightSample", sample, user, device);
+ sample.addFloatProperty(SAMPLE_WEIGHT_KG).notNull().codeBeforeGetter(OVERRIDE);
+ return sample;
+ }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f10ed66e8f..f53136ed61 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -279,6 +279,10 @@
android:name=".devices.ultrahuman.UltrahumanBreathingActivity"
android:label="@string/devicetype_ultrahuma_ring_air"
android:parentActivityName=".activities.ControlCenterv2" />
+ . */
+package nodomain.freeyourgadget.gadgetbridge.devices
+
+import de.greenrobot.dao.AbstractDao
+import de.greenrobot.dao.Property
+import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession
+import nodomain.freeyourgadget.gadgetbridge.entities.GenericWeightSample
+import nodomain.freeyourgadget.gadgetbridge.entities.GenericWeightSampleDao
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice
+
+class GenericWeightSampleProvider(device: GBDevice?, session: DaoSession?) :
+ AbstractTimeSampleProvider(device, session) {
+ override fun getSampleDao(): AbstractDao {
+ return session.genericWeightSampleDao
+ }
+
+ override fun getTimestampSampleProperty(): Property {
+ return GenericWeightSampleDao.Properties.Timestamp
+ }
+
+ override fun getDeviceIdentifierSampleProperty(): Property {
+ return GenericWeightSampleDao.Properties.DeviceId
+ }
+
+ override fun createSample(): GenericWeightSample {
+ return GenericWeightSample()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleAction.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleAction.kt
new file mode 100644
index 0000000000..0ad71241d8
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleAction.kt
@@ -0,0 +1,44 @@
+/* Copyright (C) 2025 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.generic_scale
+
+import android.content.Context
+import android.content.Intent
+import nodomain.freeyourgadget.gadgetbridge.R
+import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCardAction
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice
+import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.weightScale.WeightScaleProfile
+
+class GenericWeightScaleAction : DeviceCardAction {
+ override fun getIcon(device: GBDevice?): Int {
+ return R.drawable.ic_balance
+ }
+
+ override fun getDescription(
+ device: GBDevice?, context: Context?
+ ): String? {
+ return context?.getString(R.string.weight_scale_show_measurement)
+ }
+
+ override fun onClick(
+ device: GBDevice?, context: Context?
+ ) {
+ val intent = Intent(context, GenericWeightScaleMeasurementActivity::class.java)
+ intent.putExtra(WeightScaleProfile.EXTRA_ADDRESS, device?.address)
+ context?.startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleCoordinator.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleCoordinator.kt
new file mode 100644
index 0000000000..ef1021473d
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleCoordinator.kt
@@ -0,0 +1,113 @@
+/* Copyright (C) 2025 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.generic_scale
+
+import de.greenrobot.dao.AbstractDao
+import de.greenrobot.dao.Property
+import nodomain.freeyourgadget.gadgetbridge.R
+import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator
+import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCardAction
+import nodomain.freeyourgadget.gadgetbridge.devices.GenericWeightSampleProvider
+import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider
+import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession
+import nodomain.freeyourgadget.gadgetbridge.entities.GenericWeightSampleDao
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate
+import nodomain.freeyourgadget.gadgetbridge.model.WeightSample
+import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport
+import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService
+import nodomain.freeyourgadget.gadgetbridge.service.devices.generic_scale.GenericWeightScaleSupport
+import java.util.Collections
+
+class GenericWeightScaleCoordinator : AbstractBLEDeviceCoordinator() {
+ override fun getAllDeviceDao(session: DaoSession): MutableMap?, Property?> {
+ return Collections.singletonMap(
+ session.genericWeightSampleDao, GenericWeightSampleDao.Properties.DeviceId
+ )
+ }
+
+ override fun getCustomActions(): MutableList {
+ return Collections.singletonList(GenericWeightScaleAction())
+ }
+
+ override fun getOrderPriority(): Int {
+ return Int.MAX_VALUE
+ }
+
+ override fun getSupportedDeviceSpecificSettings(device: GBDevice?): IntArray? {
+ return intArrayOf(R.xml.devicesettings_weight_scale_unit)
+ }
+
+ override fun getWeightSampleProvider(
+ device: GBDevice?, session: DaoSession?
+ ): TimeSampleProvider? {
+ return GenericWeightSampleProvider(device, session)
+ }
+
+ override fun isExperimental(): Boolean {
+ // needs more testing
+ return true
+ }
+
+ override fun getManufacturer(): String? {
+ return "Generic"
+ }
+
+ override fun getDeviceSupportClass(device: GBDevice?): Class {
+ return GenericWeightScaleSupport::class.java
+ }
+
+ override fun getBondingStyle(): Int {
+ return BONDING_STYLE_ASK
+ }
+
+ override fun getDefaultIconResource(): Int {
+ return R.drawable.ic_device_miscale
+ }
+
+ override fun getDeviceNameResource(): Int {
+ return R.string.devicetype_generic_weight_scale
+ }
+
+ override fun supports(candidate: GBDeviceCandidate): Boolean {
+ return candidate.supportsService(GattService.UUID_SERVICE_WEIGHT_SCALE)
+ }
+
+ override fun supportsWeightMeasurement(device: GBDevice): Boolean {
+ return true
+ }
+
+ override fun supportsActivityTracking(device: GBDevice): Boolean {
+ return true
+ }
+
+ override fun supportsActivityTabs(device: GBDevice): Boolean {
+ return false
+ }
+
+ override fun supportsSleepMeasurement(device: GBDevice): Boolean {
+ return false
+ }
+
+ override fun supportsStepCounter(device: GBDevice): Boolean {
+ return false
+ }
+
+ override fun supportsSpeedzones(device: GBDevice): Boolean {
+ return false
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleMeasurementActivity.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleMeasurementActivity.kt
new file mode 100644
index 0000000000..6eee36c33a
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/generic_scale/GenericWeightScaleMeasurementActivity.kt
@@ -0,0 +1,177 @@
+/* Copyright (C) 2025 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.generic_scale
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Bundle
+import android.view.View
+import android.widget.Button
+import android.widget.TextView
+import androidx.core.content.ContextCompat
+import nodomain.freeyourgadget.gadgetbridge.GBApplication
+import nodomain.freeyourgadget.gadgetbridge.R
+import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity
+import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst
+import nodomain.freeyourgadget.gadgetbridge.database.DBHelper
+import nodomain.freeyourgadget.gadgetbridge.devices.GenericWeightSampleProvider
+import nodomain.freeyourgadget.gadgetbridge.entities.GenericWeightSample
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice
+import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.weightScale.WeightScaleMeasurement
+import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.weightScale.WeightScaleProfile
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import java.time.Instant
+import kotlin.math.roundToInt
+
+class GenericWeightScaleMeasurementActivity : AbstractGBActivity() {
+ private val weightUpdatedReceiver: WeightUpdatedReceiver = WeightUpdatedReceiver()
+ private var actual: TextView? = null
+ private var save: Button? = null
+ private var device: GBDevice? = null
+ private var unit: String? = null
+
+ private var measurement: WeightScaleMeasurement? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val address = intent.getStringExtra(WeightScaleProfile.EXTRA_ADDRESS)
+ ?: throw IllegalArgumentException(WeightScaleProfile.EXTRA_ADDRESS + " must not be null")
+
+ val manager = GBApplication.app().deviceManager
+ device = manager.getDeviceByAddress(address)
+
+ val settings = GBApplication.getDevicePrefs(device)
+ unit = settings.getString(DeviceSettingsPreferenceConst.PREF_WEIGHT_SCALE_UNIT, null)
+
+ if (unit == null) {
+ unit = if (GBApplication.getPrefs().isMetricUnits) "kilogram" else "pound"
+ }
+
+ setContentView(R.layout.activity_weight_scale_measurement)
+
+ save = findViewById(R.id.weight_scale_measurement_save)
+ save?.setOnClickListener(OnSaveClicked())
+
+ actual = findViewById(R.id.weight_scale_measurement_actual)
+
+ val filter = IntentFilter()
+ filter.addAction(WeightScaleProfile.ACTION_WEIGHT_MEASUREMENT)
+ ContextCompat.registerReceiver(
+ applicationContext, weightUpdatedReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED
+ )
+
+ displayWeightInfo()
+ }
+
+ internal fun displayWeightInfo() {
+ val raw: Double? = measurement?.weightKilogram
+ val kg: Double = if (raw == null || raw.isNaN()) 0.0 else raw
+
+ if (unit.equals("jin")) {
+ val jin: Double = kg * 2
+ actual?.text = getString(R.string.weight_scale_jin_format, jin)
+ } else if (unit.equals("pound")) {
+ val pound: Double = kg / 0.45359237
+ actual?.text = getString(R.string.weight_scale_pound_format, pound)
+ } else if (unit.equals("stone")) {
+ val total: Int = (kg / 0.45359237).roundToInt()
+ val stone: Int = total / 14
+ val pound: Int = total % 14
+ actual?.text = getString(R.string.weight_scale_stone_format, stone, pound)
+ } else {
+ actual?.text = getString(R.string.weight_scale_kilogram_format, kg)
+ }
+ }
+
+ internal fun saveWeightInfo(measurement: WeightScaleMeasurement) {
+ LOG.debug("saveWeightInfo - {}", measurement)
+
+ // ignore: missing mandatory information
+ if (measurement.weightKilogram == null) {
+ return
+ }
+
+ // fix time if missing or broken
+ if (measurement.time == null) {
+ measurement.time = Instant.now()
+ } else {
+ // older or newer than 10 minutes - the time on the scale is likely out of sync
+ val tooOld = Instant.now().minusSeconds(60L * 10L)
+ val tooNew = Instant.now().plusSeconds(60L * 10L)
+ if (measurement.time!!.isBefore(tooOld) || measurement.time!!.isAfter(tooNew)) {
+ measurement.time = Instant.now()
+ }
+ }
+
+ try {
+ GBApplication.acquireDB().use { db ->
+ val provider = GenericWeightSampleProvider(device, db.getDaoSession())
+ val userId = DBHelper.getUser(db.getDaoSession()).id
+ val deviceId = DBHelper.getDevice(device, db.getDaoSession()).id
+
+ val sample = GenericWeightSample(
+ measurement.time!!.epochSecond,
+ deviceId,
+ userId,
+ measurement.weightKilogram!!.toFloat()
+ )
+ provider.addSample(sample)
+ }
+ LOG.debug("saveWeightInfo - saved {} kg", measurement.weightKilogram)
+ } catch (e: Exception) {
+ LOG.error("saveWeightInfo - error", e)
+ }
+ }
+
+ private inner class OnSaveClicked : View.OnClickListener {
+ override fun onClick(v: View?) {
+ measurement?.let {
+ save?.setEnabled(false)
+ saveWeightInfo(it)
+ }
+ }
+ }
+
+ public override fun onDestroy() {
+ applicationContext.unregisterReceiver(weightUpdatedReceiver)
+ super.onDestroy()
+ }
+
+ private inner class WeightUpdatedReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent) {
+ LOG.debug("received measurement")
+ val data: WeightScaleMeasurement? =
+ intent.getParcelableExtra(WeightScaleProfile.EXTRA_WEIGHT_MEASUREMENT)
+ val address: String? = intent.getStringExtra(WeightScaleProfile.EXTRA_ADDRESS)
+ if (device?.address?.equals(address) == true) {
+ measurement = data
+ displayWeightInfo()
+ save?.setEnabled(measurement?.weightKilogram != null)
+ }
+ }
+ }
+
+ companion object {
+ private val LOG: Logger =
+ LoggerFactory.getLogger(GenericWeightScaleMeasurementActivity::class.java)
+ }
+}
\ No newline at end of file
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 2a51dd372d..9ce64fce44 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java
@@ -146,6 +146,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.vivosmart.Gar
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.vivosport.GarminVivosportCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.generic_headphones.GenericHeadphonesCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.generic_hr.GenericHeartRateCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.devices.generic_scale.GenericWeightScaleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.gloryfit.watches.DotnP66DCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.gloryfit.watches.OukitelBT103Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.gree.GreeAcCoordinator;
@@ -781,6 +782,7 @@ public enum DeviceType {
COOSPO_H6(CoospoH6Coordinator.class),
COOSPO_HW9(CoospoHW9Coordinator.class),
COOSPO_HW807(CoospoHW807Coordinator.class),
+ GENERIC_WEIGHT_SCALE(GenericWeightScaleCoordinator.class),
TEST(TestDeviceCoordinator.class);
private DeviceCoordinator coordinator;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/weightScale/WeightScaleMeasurement.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/weightScale/WeightScaleMeasurement.kt
new file mode 100644
index 0000000000..5387d96203
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/weightScale/WeightScaleMeasurement.kt
@@ -0,0 +1,40 @@
+/* Copyright (C) 2025 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.btle.profiles.weightScale
+
+import android.os.Parcelable
+import androidx.annotation.FloatRange
+import androidx.annotation.IntRange
+import kotlinx.parcelize.Parcelize
+
+import java.time.Instant
+
+@Parcelize
+class WeightScaleMeasurement(
+ @field:FloatRange(from = 0.0) var weightKilogram: Double?,
+ var time: Instant?,
+ @field:IntRange(from = 0L, to = 255L) var userId: Int?,
+ @field:FloatRange(from = 0.0) var heightMeter: Float?,
+ @field:FloatRange(from = 0.0) var BMI: Float?
+) : Parcelable {
+ constructor() : this(null, null, null, null, null)
+
+ override fun toString(): String {
+ return "$weightKilogram kg, $time, $userId #, $BMI, $heightMeter m"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/weightScale/WeightScaleProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/weightScale/WeightScaleProfile.java
new file mode 100644
index 0000000000..15dcea3deb
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/weightScale/WeightScaleProfile.java
@@ -0,0 +1,184 @@
+/* Copyright (C) 2025 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.btle.profiles.weightScale;
+
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.content.Intent;
+
+import androidx.annotation.NonNull;
+
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.time.Instant;
+import java.util.GregorianCalendar;
+import java.util.UUID;
+
+import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLESingleDeviceSupport;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
+import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
+import nodomain.freeyourgadget.gadgetbridge.util.GB;
+
+/// Supports receiving weights from the standard Bluetooth Weight Scale Service.
+///