feat(train): a ride reads the bike's speed and cadence sensor and power meter (ADR 0030, D49)
11d, its sensors: a ride's Record sheet offers the CSC sensor (0x1816) and the power meter (0x1818), found nearby and remembered as the strap is; the person's devices are now one map of DeviceKind to DeviceStore. The service parses CSC and Cycling Power measurements (JVM-tested, counters' rollover, coasting), writes the wheel's revolutions, the crank's cadence and the watts to the file and to series of their own. The recording screen shows cadence and watts; the page the power's chart, average, highest and normalised power and the cadence's chart and average; GPX, TCX and FIT carry them. A plan's watts target reads the power meter too. The wheel's speed and distance follow. Not tried with a real sensor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
57cbd97fd1
commit
5c13e6f3c5
5 changed files with 1209 additions and 62 deletions
|
|
@ -519,5 +519,26 @@
|
|||
"workoutExportTitle": "Training exportieren",
|
||||
"workoutExportGpxHint": "Die Strecke, für Karten und andere Apps",
|
||||
"workoutExportTcxHint": "Runden, Puls und Kadenz, für die meisten Trainingsseiten",
|
||||
"workoutExportFitHint": "Was Strava, Garmin und intervals.icu am besten lesen"
|
||||
"workoutExportFitHint": "Was Strava, Garmin und intervals.icu am besten lesen",
|
||||
"recordSpeedSensor": "Geschwindigkeits- und Trittfrequenzsensor",
|
||||
"recordNoSpeedSensor": "Keiner gewählt",
|
||||
"recordPowerMeter": "Leistungsmesser",
|
||||
"recordNoPowerMeter": "Keiner gewählt",
|
||||
"speedSensorSheetTitle": "Geschwindigkeits- und Trittfrequenzsensor",
|
||||
"speedSensorSearching": "Suche Sensoren in der Nähe …",
|
||||
"speedSensorSearchingHint": "Dreh das Rad oder die Kurbel, um ihn zu wecken. Einer, den eine andere App hält, ist nicht zu finden: Schließ diese App zuerst.",
|
||||
"speedSensorUnnamed": "Sensor ohne Namen",
|
||||
"speedSensorForget": "Sensor vergessen",
|
||||
"speedSensorRefused": "Train braucht Geräte in der Nähe, um deinen Sensor zu finden. Du kannst das in den Systemeinstellungen erlauben.",
|
||||
"powerMeterSheetTitle": "Leistungsmesser",
|
||||
"powerMeterSearching": "Suche Leistungsmesser in der Nähe …",
|
||||
"powerMeterSearchingHint": "Dreh die Kurbel, um ihn zu wecken. Einer, den eine andere App hält, ist nicht zu finden: Schließ diese App zuerst.",
|
||||
"powerMeterUnnamed": "Leistungsmesser ohne Namen",
|
||||
"powerMeterForget": "Leistungsmesser vergessen",
|
||||
"powerMeterRefused": "Train braucht Geräte in der Nähe, um deinen Leistungsmesser zu finden. Du kannst das in den Systemeinstellungen erlauben.",
|
||||
"recordingCadence": "Umdrehungen pro Minute",
|
||||
"workoutPedalling": "Trittfrequenz",
|
||||
"workoutAverageCadence": "durchschnittliche Trittfrequenz",
|
||||
"workoutNormalisedPower": "normalisierte Leistung",
|
||||
"workoutRpmValue": "{rpm} U/min"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -658,5 +658,27 @@
|
|||
"workoutExportTitle": "Export the workout",
|
||||
"workoutExportGpxHint": "The track, for maps and other apps",
|
||||
"workoutExportTcxHint": "Laps, heart rate and cadence, for most training sites",
|
||||
"workoutExportFitHint": "What Strava, Garmin and intervals.icu read best"
|
||||
"workoutExportFitHint": "What Strava, Garmin and intervals.icu read best",
|
||||
"recordSpeedSensor": "Speed and cadence sensor",
|
||||
"recordNoSpeedSensor": "None chosen",
|
||||
"recordPowerMeter": "Power meter",
|
||||
"recordNoPowerMeter": "None chosen",
|
||||
"speedSensorSheetTitle": "Speed and cadence sensor",
|
||||
"speedSensorSearching": "Looking for speed and cadence sensors nearby…",
|
||||
"speedSensorSearchingHint": "Turn the wheel or the crank to wake it. One another app holds can't be found: close that app first.",
|
||||
"speedSensorUnnamed": "Unnamed sensor",
|
||||
"speedSensorForget": "Forget sensor",
|
||||
"speedSensorRefused": "Train needs nearby devices to find your sensor. You can allow it in the system's settings.",
|
||||
"powerMeterSheetTitle": "Power meter",
|
||||
"powerMeterSearching": "Looking for power meters nearby…",
|
||||
"powerMeterSearchingHint": "Turn the crank to wake it. One another app holds can't be found: close that app first.",
|
||||
"powerMeterUnnamed": "Unnamed power meter",
|
||||
"powerMeterForget": "Forget power meter",
|
||||
"powerMeterRefused": "Train needs nearby devices to find your power meter. You can allow it in the system's settings.",
|
||||
"recordingCadence": "turns a minute",
|
||||
"workoutPedalling": "Cadence",
|
||||
"workoutAverageCadence": "average cadence",
|
||||
"workoutNormalisedPower": "normalised power",
|
||||
"workoutRpmValue": "{rpm} rpm",
|
||||
"@workoutRpmValue": {"placeholders": {"rpm": {"type": "int"}}}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3141,6 +3141,132 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'What Strava, Garmin and intervals.icu read best'**
|
||||
String get workoutExportFitHint;
|
||||
|
||||
/// No description provided for @recordSpeedSensor.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Speed and cadence sensor'**
|
||||
String get recordSpeedSensor;
|
||||
|
||||
/// No description provided for @recordNoSpeedSensor.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'None chosen'**
|
||||
String get recordNoSpeedSensor;
|
||||
|
||||
/// No description provided for @recordPowerMeter.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Power meter'**
|
||||
String get recordPowerMeter;
|
||||
|
||||
/// No description provided for @recordNoPowerMeter.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'None chosen'**
|
||||
String get recordNoPowerMeter;
|
||||
|
||||
/// No description provided for @speedSensorSheetTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Speed and cadence sensor'**
|
||||
String get speedSensorSheetTitle;
|
||||
|
||||
/// No description provided for @speedSensorSearching.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Looking for speed and cadence sensors nearby…'**
|
||||
String get speedSensorSearching;
|
||||
|
||||
/// No description provided for @speedSensorSearchingHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Turn the wheel or the crank to wake it. One another app holds can\'t be found: close that app first.'**
|
||||
String get speedSensorSearchingHint;
|
||||
|
||||
/// No description provided for @speedSensorUnnamed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Unnamed sensor'**
|
||||
String get speedSensorUnnamed;
|
||||
|
||||
/// No description provided for @speedSensorForget.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Forget sensor'**
|
||||
String get speedSensorForget;
|
||||
|
||||
/// No description provided for @speedSensorRefused.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Train needs nearby devices to find your sensor. You can allow it in the system\'s settings.'**
|
||||
String get speedSensorRefused;
|
||||
|
||||
/// No description provided for @powerMeterSheetTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Power meter'**
|
||||
String get powerMeterSheetTitle;
|
||||
|
||||
/// No description provided for @powerMeterSearching.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Looking for power meters nearby…'**
|
||||
String get powerMeterSearching;
|
||||
|
||||
/// No description provided for @powerMeterSearchingHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Turn the crank to wake it. One another app holds can\'t be found: close that app first.'**
|
||||
String get powerMeterSearchingHint;
|
||||
|
||||
/// No description provided for @powerMeterUnnamed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Unnamed power meter'**
|
||||
String get powerMeterUnnamed;
|
||||
|
||||
/// No description provided for @powerMeterForget.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Forget power meter'**
|
||||
String get powerMeterForget;
|
||||
|
||||
/// No description provided for @powerMeterRefused.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Train needs nearby devices to find your power meter. You can allow it in the system\'s settings.'**
|
||||
String get powerMeterRefused;
|
||||
|
||||
/// No description provided for @recordingCadence.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'turns a minute'**
|
||||
String get recordingCadence;
|
||||
|
||||
/// No description provided for @workoutPedalling.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cadence'**
|
||||
String get workoutPedalling;
|
||||
|
||||
/// No description provided for @workoutAverageCadence.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'average cadence'**
|
||||
String get workoutAverageCadence;
|
||||
|
||||
/// No description provided for @workoutNormalisedPower.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'normalised power'**
|
||||
String get workoutNormalisedPower;
|
||||
|
||||
/// No description provided for @workoutRpmValue.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{rpm} rpm'**
|
||||
String workoutRpmValue(int rpm);
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -1889,4 +1889,74 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get workoutExportFitHint =>
|
||||
'Was Strava, Garmin und intervals.icu am besten lesen';
|
||||
|
||||
@override
|
||||
String get recordSpeedSensor => 'Geschwindigkeits- und Trittfrequenzsensor';
|
||||
|
||||
@override
|
||||
String get recordNoSpeedSensor => 'Keiner gewählt';
|
||||
|
||||
@override
|
||||
String get recordPowerMeter => 'Leistungsmesser';
|
||||
|
||||
@override
|
||||
String get recordNoPowerMeter => 'Keiner gewählt';
|
||||
|
||||
@override
|
||||
String get speedSensorSheetTitle =>
|
||||
'Geschwindigkeits- und Trittfrequenzsensor';
|
||||
|
||||
@override
|
||||
String get speedSensorSearching => 'Suche Sensoren in der Nähe …';
|
||||
|
||||
@override
|
||||
String get speedSensorSearchingHint =>
|
||||
'Dreh das Rad oder die Kurbel, um ihn zu wecken. Einer, den eine andere App hält, ist nicht zu finden: Schließ diese App zuerst.';
|
||||
|
||||
@override
|
||||
String get speedSensorUnnamed => 'Sensor ohne Namen';
|
||||
|
||||
@override
|
||||
String get speedSensorForget => 'Sensor vergessen';
|
||||
|
||||
@override
|
||||
String get speedSensorRefused =>
|
||||
'Train braucht Geräte in der Nähe, um deinen Sensor zu finden. Du kannst das in den Systemeinstellungen erlauben.';
|
||||
|
||||
@override
|
||||
String get powerMeterSheetTitle => 'Leistungsmesser';
|
||||
|
||||
@override
|
||||
String get powerMeterSearching => 'Suche Leistungsmesser in der Nähe …';
|
||||
|
||||
@override
|
||||
String get powerMeterSearchingHint =>
|
||||
'Dreh die Kurbel, um ihn zu wecken. Einer, den eine andere App hält, ist nicht zu finden: Schließ diese App zuerst.';
|
||||
|
||||
@override
|
||||
String get powerMeterUnnamed => 'Leistungsmesser ohne Namen';
|
||||
|
||||
@override
|
||||
String get powerMeterForget => 'Leistungsmesser vergessen';
|
||||
|
||||
@override
|
||||
String get powerMeterRefused =>
|
||||
'Train braucht Geräte in der Nähe, um deinen Leistungsmesser zu finden. Du kannst das in den Systemeinstellungen erlauben.';
|
||||
|
||||
@override
|
||||
String get recordingCadence => 'Umdrehungen pro Minute';
|
||||
|
||||
@override
|
||||
String get workoutPedalling => 'Trittfrequenz';
|
||||
|
||||
@override
|
||||
String get workoutAverageCadence => 'durchschnittliche Trittfrequenz';
|
||||
|
||||
@override
|
||||
String get workoutNormalisedPower => 'normalisierte Leistung';
|
||||
|
||||
@override
|
||||
String workoutRpmValue(int rpm) {
|
||||
return '$rpm U/min';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1877,6 +1877,76 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get workoutExportFitHint =>
|
||||
'What Strava, Garmin and intervals.icu read best';
|
||||
|
||||
@override
|
||||
String get recordSpeedSensor => 'Speed and cadence sensor';
|
||||
|
||||
@override
|
||||
String get recordNoSpeedSensor => 'None chosen';
|
||||
|
||||
@override
|
||||
String get recordPowerMeter => 'Power meter';
|
||||
|
||||
@override
|
||||
String get recordNoPowerMeter => 'None chosen';
|
||||
|
||||
@override
|
||||
String get speedSensorSheetTitle => 'Speed and cadence sensor';
|
||||
|
||||
@override
|
||||
String get speedSensorSearching =>
|
||||
'Looking for speed and cadence sensors nearby…';
|
||||
|
||||
@override
|
||||
String get speedSensorSearchingHint =>
|
||||
'Turn the wheel or the crank to wake it. One another app holds can\'t be found: close that app first.';
|
||||
|
||||
@override
|
||||
String get speedSensorUnnamed => 'Unnamed sensor';
|
||||
|
||||
@override
|
||||
String get speedSensorForget => 'Forget sensor';
|
||||
|
||||
@override
|
||||
String get speedSensorRefused =>
|
||||
'Train needs nearby devices to find your sensor. You can allow it in the system\'s settings.';
|
||||
|
||||
@override
|
||||
String get powerMeterSheetTitle => 'Power meter';
|
||||
|
||||
@override
|
||||
String get powerMeterSearching => 'Looking for power meters nearby…';
|
||||
|
||||
@override
|
||||
String get powerMeterSearchingHint =>
|
||||
'Turn the crank to wake it. One another app holds can\'t be found: close that app first.';
|
||||
|
||||
@override
|
||||
String get powerMeterUnnamed => 'Unnamed power meter';
|
||||
|
||||
@override
|
||||
String get powerMeterForget => 'Forget power meter';
|
||||
|
||||
@override
|
||||
String get powerMeterRefused =>
|
||||
'Train needs nearby devices to find your power meter. You can allow it in the system\'s settings.';
|
||||
|
||||
@override
|
||||
String get recordingCadence => 'turns a minute';
|
||||
|
||||
@override
|
||||
String get workoutPedalling => 'Cadence';
|
||||
|
||||
@override
|
||||
String get workoutAverageCadence => 'average cadence';
|
||||
|
||||
@override
|
||||
String get workoutNormalisedPower => 'normalised power';
|
||||
|
||||
@override
|
||||
String workoutRpmValue(int rpm) {
|
||||
return '$rpm rpm';
|
||||
}
|
||||
}
|
||||
|
||||
/// The translations for English, as used in the United Kingdom (`en_GB`).
|
||||
|
|
|
|||
Loading…
Reference in a new issue