homebridge-peloton 0.1.0-beta.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  All notable changes to homebridge-peloton are listed here. The format follows Keep a Changelog, and the project follows semantic versioning from 0.1.0-beta.1. The release notes of a version are its section here and nothing else.
4
4
 
5
+ ## 1.0.0 (2026-09-17)
6
+
7
+ The first general release, to the npm latest tag. Every device the test membership can produce is named, the Device filter covers the apps, the plugin records the device codes it sees so a Row or Android report is a copy and paste, and a second workout after the first is caught quickly whether or not the fast polling switch is on.
8
+
9
+ ### Added
10
+
11
+ - Apple TV and Phone or tablet app as Device options on Workout triggers: `appletv` matches the workout platform `apple_tv` (device_type `apple_tv`), `app` matches platform `iOS_app` or `android_app` when the workout is Peloton originated (device_type `iPhone` or `iPad`; Android as expected, not yet observed). The page, `config.schema.json` and `src/config.ts` offer Any device, Bike, Tread, Guide, Apple TV and Phone or tablet app with the caption "Bike and Tread cover every model of each. Guide is a class on the Peloton Guide. Apple TV and Phone or tablet app are classes taken in the Peloton app."
12
+ - `src/devices.ts`, the one table from device_type to display name: home_bike_v1 Bike, home_bike_plus Bike+, prism Tread, t21n8m2 Guide, apple_tv Apple TV, iPhone iPhone, iPad iPad, apple_health Apple Health import. An unmapped code displays as the raw code.
13
+ - Devices seen: the poller records every device_type and platform pair it observes, with the workout type it was first seen on, on the owner's account file (no workout ids, titles, dates or account details). The first time a pair whose device_type has no display name appears, one info line: "New Peloton device seen: device_type={x}, platform={y}. Open the settings page, Advanced, Devices seen, to report it." The UI server answers `/devices-seen`. The settings page shows a read-only Devices seen block under Advanced after Daily check-in time, each pair as "{display name} ({device_type}, {platform})" with a Known or Unknown tag, a Copy report button on Unknown rows and the privacy caption with a Report it on GitHub link to the new Device report issue form (`.github/ISSUE_TEMPLATE/device-report.yml`, one textarea for the pasted report). The report is the two codes, the discipline and the plugin version, nothing else.
14
+ - `advanced.keepFastAfterEndMinutes`, default 5, minimum 0, under Advanced after Fast polling switch turns off after: "Keep fast polling after a workout ends (minutes)". After any workout ends the poller keeps the fast interval that long, even with the switch off, so a second workout is caught within one fast interval, then follows the switch state.
15
+ - README: the Devices section with the display names and codes, the How I use it section after Setup, and the new Advanced fields.
16
+ - Tests: rules, config, schema and poller tests for the new filters; a devices table suite; poller, UI server, page model and page tests for the devices seen and the copy text; fake clock poller tests for the kept fast interval; a poller test for the log title fallback.
17
+
18
+ ### Changed
19
+
20
+ - Version 1.0.0 in package.json and the version literals in the tests and the bug report form; the settings page footer reads it from package.json. A GitHub release marked Latest publishes to the npm latest tag through the existing release workflow; a pre-release still goes to the beta tag.
21
+ - README: status line "stable. 1.0.0 is the first general release.", the npm version badge on the latest tag, and install without the beta tag.
22
+ - The strength fixture carries the iPhone app codes as observed (device_type `iPhone`, platform `iOS_app`) in place of the synthesised `iOS` and `ios`.
23
+ - SPEC: the version line, sections 2, 4.2 (the full device table), 5, 6, 7, 8, 10, 11, 13 and 14, section 15 down to Row and Android codes, verification-required accounts and the Heart-rate zone offering, and the 1.0.0 notes in section 16. design/README.md records the Device options, the two new Advanced fields and the Devices seen block.
24
+
25
+ ### Fixed
26
+
27
+ - The "workout started" log line uses the ride title when there is one, else the workout's title or name, and the discipline alone otherwise, so an app class no longer logs "(strength, )".
28
+
5
29
  ## 0.1.0-beta.2 (2026-09-14)
6
30
 
7
31
  Beta.2 in two PRs. PR 1: the settings page aligned with the Homebridge Plugin Shell as homebridge-notify-switch v1.3.2 ships it. PR 2: the Guide device option, the Heart-rate zone triggers withdrawn from the settings page for this release, the provenance note on the auth module, the README badges and credits, the CodeQL configuration, and the version.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Do not claim it. Once the plugin is verified, replace this comment with the badg
6
6
  [![verified-by-homebridge](https://badgen.net/badge/homebridge/verified/purple)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
7
7
  -->
8
8
 
9
- [![npm version](https://img.shields.io/npm/v/homebridge-peloton/beta)](https://www.npmjs.com/package/homebridge-peloton)
9
+ [![npm version](https://img.shields.io/npm/v/homebridge-peloton)](https://www.npmjs.com/package/homebridge-peloton)
10
10
  [![npm downloads](https://img.shields.io/npm/dt/homebridge-peloton)](https://www.npmjs.com/package/homebridge-peloton)
11
11
  [![License](https://img.shields.io/github/license/arodbuilds/homebridge-peloton)](LICENSE)
12
12
  [![Build, lint, and test](https://github.com/arodbuilds/homebridge-peloton/actions/workflows/build.yml/badge.svg)](https://github.com/arodbuilds/homebridge-peloton/actions/workflows/build.yml)
@@ -15,7 +15,7 @@ A [Homebridge](https://homebridge.io) plugin that turns Peloton workouts into Ho
15
15
 
16
16
  Not affiliated with or endorsed by Peloton Interactive. Uses Peloton's undocumented member API, which can change without notice.
17
17
 
18
- > **Status:** Beta. Please report what works and what does not in the [issue tracker](https://github.com/arodbuilds/homebridge-peloton/issues).
18
+ > **Status:** stable. 1.0.0 is the first general release.
19
19
 
20
20
  ## Contents
21
21
 
@@ -26,8 +26,10 @@ Not affiliated with or endorsed by Peloton Interactive. Uses Peloton's undocumen
26
26
  - [2. Add a Workout trigger](#2-add-a-workout-trigger)
27
27
  - [3. Set up the fast polling automation](#3-set-up-the-fast-polling-automation)
28
28
  - [4. Settings and Advanced](#4-settings-and-advanced)
29
+ - [How I use it](#how-i-use-it)
29
30
  - [Browser sign-in](#browser-sign-in)
30
31
  - [How it works](#how-it-works)
32
+ - [Devices](#devices)
31
33
  - [Privacy and what is stored where](#privacy-and-what-is-stored-where)
32
34
  - [Troubleshooting](#troubleshooting)
33
35
  - [Development](#development)
@@ -42,10 +44,10 @@ Not affiliated with or endorsed by Peloton Interactive. Uses Peloton's undocumen
42
44
 
43
45
  ## Install
44
46
 
45
- Search for "Peloton" under Plugins in the Homebridge UI and install the beta, or from a shell on the Homebridge host:
47
+ Search for "Peloton" under Plugins in the Homebridge UI and install it, or from a shell on the Homebridge host:
46
48
 
47
49
  ```shell
48
- npm install -g homebridge-peloton@beta
50
+ npm install -g homebridge-peloton
49
51
  ```
50
52
 
51
53
  Then open the plugin's settings from the Plugins page. Everything in the setup below happens on that page. The host's Save button writes config.json and Homebridge restarts the plugin.
@@ -66,7 +68,7 @@ The password is stored in your Homebridge config so the plugin can sign in again
66
68
 
67
69
  ![A Workout trigger card: name, Occupancy sensor or Switch, who, device, the activity chips, and the keep-on time](assets/screenshots/trigger-workout.png)
68
70
 
69
- Under Triggers, click Add trigger. The sensor is on while a matching workout is in progress. Pick who it watches (anyone on the membership, or one member), the device (any, Bike, Tread, or Guide), and the activities that count; all twelve are selected to start with. Keep on after the workout ends holds the sensor on for a while after the class finishes, 90 seconds by default, so stacked classes do not turn your scene off between them.
71
+ Under Triggers, click Add trigger. The sensor is on while a matching workout is in progress. Pick who it watches (anyone on the membership, or one member), the device (Any device, Bike, Tread, Guide, Apple TV, or Phone or tablet app; see [Devices](#devices)), and the activities that count; all twelve are selected to start with. Keep on after the workout ends holds the sensor on for a while after the class finishes, 90 seconds by default, so stacked classes do not turn your scene off between them.
70
72
 
71
73
  Give the trigger a name (it starts as "Workout"), choose Occupancy sensor or Switch as its HomeKit kind, and click Done. Save, restart Homebridge, and the sensor appears in the Home app under the bridge. In Automations, choose the sensor as the trigger and pick what should happen when it turns on and when it turns off.
72
74
 
@@ -76,7 +78,7 @@ Heart-rate zone triggers are being refined and are not offered in this release.
76
78
 
77
79
  ![The Polling section: the Fast polling switch, the fast and standby intervals, and the automation callout](assets/screenshots/polling.png)
78
80
 
79
- The plugin creates a switch called Peloton fast polling. While it is on, the plugin checks every account every 10 seconds, locks onto the first workout it sees, and follows it to the end. While it is off, it polls at the standby interval, 120 seconds by default; 0 turns standby polling off entirely. The switch turns itself off after 120 minutes, counted from the later of turning on and the last workout ending.
81
+ The plugin creates a switch called Peloton fast polling. While it is on, the plugin checks every account every 10 seconds, locks onto the first workout it sees, and follows it to the end. While it is off, it polls at the standby interval, 120 seconds by default; 0 turns standby polling off entirely. The switch turns itself off after 120 minutes, counted from the later of turning on and the last workout ending. After any workout ends the plugin keeps checking every 10 seconds for 5 minutes, whether the switch is on or off, so a second workout is caught quickly; both periods are set under Advanced.
80
82
 
81
83
  Add two Home app automations:
82
84
 
@@ -94,10 +96,22 @@ Settings holds one Advanced disclosure, collapsed until something inside it is c
94
96
  - Name: the plugin name, shown in Homebridge logs and as the bridge name in the Home app.
95
97
  - Debug logging: logs every poll and the workout data it returns; sign-in details and session tokens are never logged.
96
98
  - Fast polling switch turns off after: the auto-off period in minutes.
99
+ - Keep fast polling after a workout ends: how many minutes the plugin keeps the fast interval after any workout ends, even with the switch off, so a second workout is caught quickly. 5 by default, 0 turns it off.
97
100
  - Attention needed sensor: an occupancy sensor that is on while any account needs to be reconnected, for an automation that sends you a notification.
98
101
  - Daily check-in time: once a day the plugin refreshes each account's session and heart-rate zones, even when nobody is working out.
102
+ - Devices seen: a read-only list of the device codes the plugin has seen on your membership, each tagged Known or Unknown. An Unknown row has a Copy report button; see [Devices](#devices).
99
103
  - Restore from backup: loads a saved Peloton platform block, a whole config.json, or a saved draft of this page.
100
104
 
105
+ ## How I use it
106
+
107
+ My workouts start the same way every time: I turn on the gym light. A Home automation turns on the Peloton fast polling switch when that light comes on, so by the time I have clipped in the plugin is already checking every ten seconds. I do not use an automation to turn the switch off; the "Fast polling switch turns off after" setting under Advanced is set to 15 minutes, so polling winds down on its own after my last workout ends, and back-to-back sessions are caught without a gap.
108
+
109
+ One Workout trigger set to Any device drives the room: when it turns on, a scene sets the lights and the fan; when it turns off, another scene puts the room back. Because the trigger stays on for the whole workout, one sensor gives me both ends.
110
+
111
+ For different rooms I use the Device filter: a Bike trigger and a Tread trigger each drive their own scene, and a Phone or tablet app trigger handles classes I take in the living room on the Apple TV or on the iPad. A trigger set to Any device also fires when I start a class on my phone away from home, which is fine for me; if you do not want that, use the device filters instead.
112
+
113
+ The family each connected their own profile, and a per-person Workout trigger lets each of us have our own scene.
114
+
101
115
  ## Browser sign-in
102
116
 
103
117
  If Peloton does not accept the sign-in from the plugin, or an account has extra verification turned on, the connect panel offers Sign in with browser:
@@ -114,14 +128,35 @@ If Back does not show the callback address, long-press the Back button and pick
114
128
  - **Lock-on.** One workout is followed at a time. Other members' workouts are not polled while a workout is locked, so two riders on one membership should start the second ride after the first has ended, or use one Workout trigger for anyone.
115
129
  - **Hold.** A Workout sensor stays on for the keep-on time after the class ends, and a new matching workout during that time keeps it on without a gap. A Heart-rate zone sensor changes only after the zone has held for the hold time, and turns off when the workout ends.
116
130
  - **Third-party imports are ignored.** Runs and other activities synced into Peloton from Apple Health, Strava, or Fitbit never start or end a workout, even when they land at the top of your workout list mid-ride.
131
+ - **Fast polling after a workout.** After any workout ends the plugin keeps the fast interval for the minutes set under Advanced (5 by default), whatever the switch, then follows the switch again.
117
132
  - **Configuration.** The settings page writes the platform block in config.json; the shape and every default are in [SPEC.md](SPEC.md) section 6 and in `config.schema.json`, for anyone who edits by hand.
118
133
 
134
+ ## Devices
135
+
136
+ The Device filter on a Workout trigger matches the platform a workout was recorded on. These are the codes the plugin knows, as Peloton reports them:
137
+
138
+ | Hardware or source | Shown as | device_type | platform | Device filter |
139
+ | --- | --- | --- | --- | --- |
140
+ | Bike (original) | Bike | home_bike_v1 | home_bike | Bike |
141
+ | Bike+ | Bike+ | home_bike_plus | home_bike | Bike |
142
+ | Tread | Tread | prism | home_tread | Tread |
143
+ | Guide | Guide | t21n8m2 | tiger | Guide |
144
+ | Apple TV app | Apple TV | apple_tv | apple_tv | Apple TV |
145
+ | iPhone app | iPhone | iPhone | iOS_app | Phone or tablet app |
146
+ | iPad app | iPad | iPad | iOS_app | Phone or tablet app |
147
+ | Apple Health import | Apple Health import | apple_health | iOS_app | none, imports are ignored |
148
+
149
+ Every row but the original Bike was observed on a live membership between September 11 and 16, 2026; the original Bike's codes come from public logs. Row and Android: not yet observed; the Devices seen block under Advanced makes a report a copy and paste. An Android app class is expected to match Phone or tablet app once its codes are confirmed.
150
+
151
+ When the plugin sees a code it does not know it logs one line, "New Peloton device seen", and lists the pair under Advanced, Devices seen, tagged Unknown with a Copy report button. The report holds the two codes, the workout type such as cycling or strength, and the plugin version, nothing else; paste it into a [device report](https://github.com/arodbuilds/homebridge-peloton/issues/new?template=device-report.yml) and the next release can name the device and, for new hardware, give it a filter.
152
+
119
153
  ## Privacy and what is stored where
120
154
 
121
155
  - Session tokens live in `homebridge-peloton/accounts/` inside the Homebridge storage folder, one file per account with mode 0600, readable only by the Homebridge user. They are never written to config.json, the log, or the settings page.
122
156
  - Passwords are stored in config.json only for accounts connected with email and password on the settings page, so the plugin can sign in again by itself. Accounts connected with Sign in with browser store no password.
123
157
  - Profile photos are fetched by the plugin and proxied to the settings page; the page never talks to Peloton's servers itself.
124
158
  - The log never contains tokens, passwords, emails, or Peloton's responses. Debug logging prints workout ids and statuses only.
159
+ - The devices seen list keeps only device codes (device type and platform) and the workout type each was first seen on, in the owner's account file. No workout ids, titles, dates, or account details are kept for it.
125
160
  - To remove everything for an account, click Remove on its card. To remove every stored sign-in, delete the `homebridge-peloton` folder in the Homebridge storage folder.
126
161
 
127
162
  ## Troubleshooting
@@ -130,7 +165,8 @@ If Back does not show the callback address, long-press the Back button and pick
130
165
  - **Accounts with extra verification.** If Peloton asks for a verification code when the plugin signs in, the panel says so and offers Sign in with browser; complete the verification in the browser tab and paste the callback address. Please open an issue if you hit this, since it has not been seen on a household account yet.
131
166
  - **"Peloton sign-in did not complete."** Peloton changed something about its login page and the headless sign-in no longer fits it. Use Sign in with browser to keep going, and open an issue with the output of the auth probe (see [Development](#development)); the fix lives in one file.
132
167
  - **No heart-rate data.** The log says "no heart-rate data for this workout" once per workout when no heart-rate monitor is paired. The zone sensor stays off for that workout.
133
- - **A workout is noticed late.** Without the fast polling automation the plugin polls at the standby interval. Set up the automation, or lower the standby interval under Polling.
168
+ - **A workout is noticed late.** Without the fast polling automation the plugin polls at the standby interval. Set up the automation, or lower the standby interval under Polling. A second workout soon after the first is caught quickly either way, for the minutes set by Keep fast polling after a workout ends under Advanced.
169
+ - **A trigger with a Device filter never turns on.** The workout may come from hardware or an app the plugin does not know yet. Check Devices seen under Advanced: an Unknown row means the codes are new, and Copy report gives you everything a [device report](https://github.com/arodbuilds/homebridge-peloton/issues/new?template=device-report.yml) needs. A trigger set to Any device works meanwhile.
134
170
 
135
171
  ## Development
136
172
 
@@ -132,14 +132,16 @@
132
132
  },
133
133
  "device": {
134
134
  "title": "Device",
135
- "description": "Bike is a ride on the Bike or Bike+, Tread is a workout on the Tread or Tread+, Guide is a class taken on the Peloton Guide.",
135
+ "description": "Bike and Tread cover every model of each. Guide is a class on the Peloton Guide. Apple TV and Phone or tablet app are classes taken in the Peloton app.",
136
136
  "type": "string",
137
137
  "default": "any",
138
138
  "oneOf": [
139
139
  { "title": "Any device", "enum": ["any"] },
140
140
  { "title": "Bike", "enum": ["bike"] },
141
141
  { "title": "Tread", "enum": ["tread"] },
142
- { "title": "Guide", "enum": ["guide"] }
142
+ { "title": "Guide", "enum": ["guide"] },
143
+ { "title": "Apple TV", "enum": ["appletv"] },
144
+ { "title": "Phone or tablet app", "enum": ["app"] }
143
145
  ]
144
146
  },
145
147
  "holdAfterEnd": {
@@ -230,7 +232,7 @@
230
232
  },
231
233
  "advanced": {
232
234
  "title": "Advanced",
233
- "description": "Rarely needed options: the auto-off period, the Attention needed sensor, and the daily check-in time.",
235
+ "description": "Rarely needed options: the auto-off period, the fast interval kept after a workout ends, the Attention needed sensor, and the daily check-in time.",
234
236
  "type": "object",
235
237
  "default": {},
236
238
  "properties": {
@@ -241,6 +243,13 @@
241
243
  "minimum": 1,
242
244
  "default": 120
243
245
  },
246
+ "keepFastAfterEndMinutes": {
247
+ "title": "Keep fast polling after a workout ends (minutes)",
248
+ "description": "After any workout ends the plugin keeps the fast interval this long, even if the fast polling switch is off, so a second workout is caught quickly.",
249
+ "type": "integer",
250
+ "minimum": 0,
251
+ "default": 5
252
+ },
244
253
  "attentionSensor": {
245
254
  "title": "Attention needed sensor",
246
255
  "description": "Create an occupancy sensor that turns on when any account needs to be reconnected. Use it in an automation to get a notification.",
@@ -86,8 +86,8 @@ export interface WorkoutRide {
86
86
  /**
87
87
  * A workout as the list and the single-workout call return it (both carry the same fields).
88
88
  * Workouts carry no device id field (confirmed by the build 2 Pi probe, SPEC section 15 item 1):
89
- * device_type is the hardware model code (home_bike_plus, iOS, and so on), not an identifier of
90
- * the member's unit, so device matching maps it to attached_devices (SPEC section 8.3).
89
+ * device_type is the hardware model code (home_bike_plus, iPhone, and so on), not an identifier of
90
+ * the member's unit; device matching compares platform (SPEC section 8.3).
91
91
  */
92
92
  export interface Workout {
93
93
  id: string;
package/dist/config.d.ts CHANGED
@@ -7,8 +7,11 @@
7
7
  * the config is saved from the settings page.
8
8
  */
9
9
  export type AccessoryKind = 'occupancy' | 'switch';
10
- /** A workout trigger's device filter: any hardware, the Bike or Bike+, the Tread or Tread+, or the Guide (SPEC section 8.3). */
11
- export type DeviceFilter = 'any' | 'bike' | 'tread' | 'guide';
10
+ /**
11
+ * A workout trigger's device filter (SPEC section 8.3): any device, the Bike or Bike+, the Tread or
12
+ * Tread+, the Guide, the Apple TV app, or the phone and tablet app (iPhone, iPad, Android).
13
+ */
14
+ export type DeviceFilter = 'any' | 'bike' | 'tread' | 'guide' | 'appletv' | 'app';
12
15
  export declare const DEVICE_FILTERS: readonly DeviceFilter[];
13
16
  export interface AccountConfig {
14
17
  id: string;
@@ -26,7 +29,7 @@ export interface WorkoutTriggerConfig {
26
29
  who: string;
27
30
  /** Empty means all activities. */
28
31
  activities: string[];
29
- /** "any", "bike", "tread", or "guide"; matched against the workout's platform. */
32
+ /** "any", "bike", "tread", "guide", "appletv", or "app"; matched against the workout's platform. */
30
33
  device: DeviceFilter;
31
34
  /** Seconds the sensor stays on after the workout ends. */
32
35
  holdAfterEnd: number;
@@ -55,6 +58,8 @@ export interface PollingConfig {
55
58
  }
56
59
  export interface AdvancedConfig {
57
60
  fastSwitchAutoOffMinutes: number;
61
+ /** Minutes the fast interval is kept after any workout ends, whatever the switch; 0 means none. */
62
+ keepFastAfterEndMinutes: number;
58
63
  attentionSensor: boolean;
59
64
  /** Local time "HH:MM". */
60
65
  dailyCheckIn: string;
@@ -78,6 +83,7 @@ export declare const CONFIG_DEFAULTS: {
78
83
  readonly fastSwitch: true;
79
84
  readonly fastSwitchName: "Peloton fast polling";
80
85
  readonly fastSwitchAutoOffMinutes: 120;
86
+ readonly keepFastAfterEndMinutes: 5;
81
87
  readonly attentionSensor: false;
82
88
  readonly dailyCheckIn: "03:00";
83
89
  readonly workoutTriggerName: "Workout";
package/dist/config.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * the config is saved from the settings page.
8
8
  */
9
9
  import { randomUUID } from 'node:crypto';
10
- export const DEVICE_FILTERS = ['any', 'bike', 'tread', 'guide'];
10
+ export const DEVICE_FILTERS = ['any', 'bike', 'tread', 'guide', 'appletv', 'app'];
11
11
  export const CONFIG_DEFAULTS = {
12
12
  name: 'Peloton',
13
13
  fastInterval: 10,
@@ -19,6 +19,7 @@ export const CONFIG_DEFAULTS = {
19
19
  fastSwitch: true,
20
20
  fastSwitchName: 'Peloton fast polling',
21
21
  fastSwitchAutoOffMinutes: 120,
22
+ keepFastAfterEndMinutes: 5,
22
23
  attentionSensor: false,
23
24
  dailyCheckIn: '03:00',
24
25
  workoutTriggerName: 'Workout',
@@ -60,6 +61,9 @@ export function parseConfig(raw, options = {}) {
60
61
  fastSwitchAutoOffMinutes: integer(advanced.fastSwitchAutoOffMinutes, {
61
62
  name: 'advanced.fastSwitchAutoOffMinutes', fallback: CONFIG_DEFAULTS.fastSwitchAutoOffMinutes, min: 1,
62
63
  }, warn),
64
+ keepFastAfterEndMinutes: integer(advanced.keepFastAfterEndMinutes, {
65
+ name: 'advanced.keepFastAfterEndMinutes', fallback: CONFIG_DEFAULTS.keepFastAfterEndMinutes, min: 0,
66
+ }, warn),
63
67
  attentionSensor: bool(advanced.attentionSensor, CONFIG_DEFAULTS.attentionSensor, 'advanced.attentionSensor', warn),
64
68
  dailyCheckIn: dailyCheckIn(advanced.dailyCheckIn, warn),
65
69
  },
@@ -144,7 +148,7 @@ function deviceFilter(value, label, warn) {
144
148
  if (typeof value === 'string' && DEVICE_FILTERS.includes(value)) {
145
149
  return value;
146
150
  }
147
- warn(`${label}.device is not "any", "bike", "tread", or "guide", using "any"`);
151
+ warn(`${label}.device is not "any", "bike", "tread", "guide", "appletv", or "app", using "any"`);
148
152
  return 'any';
149
153
  }
150
154
  function activities(value, label, warn) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The one table that maps a workout's device_type (the hardware model or app code Peloton sends,
3
+ * SPEC section 4.2) to the name the plugin shows for it: the Devices seen block on the settings
4
+ * page (SPEC section 10) and the README device table read from here. Every code below was observed
5
+ * live between September 11 and 16, 2026, except home_bike_v1, which comes from public logs of 2020.
6
+ * A code that is not in the table displays as the raw code and counts as unknown, which is what
7
+ * the Devices seen block asks the user to report.
8
+ */
9
+ export declare const DEVICE_NAMES: Readonly<Record<string, string>>;
10
+ /** True when the device_type has a display name, that is, the plugin has seen this hardware or app before. */
11
+ export declare function isKnownDevice(deviceType: string): boolean;
12
+ /** The display name for a device_type, or the raw code when the table has no entry for it. */
13
+ export declare function deviceDisplayName(deviceType: string): string;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The one table that maps a workout's device_type (the hardware model or app code Peloton sends,
3
+ * SPEC section 4.2) to the name the plugin shows for it: the Devices seen block on the settings
4
+ * page (SPEC section 10) and the README device table read from here. Every code below was observed
5
+ * live between September 11 and 16, 2026, except home_bike_v1, which comes from public logs of 2020.
6
+ * A code that is not in the table displays as the raw code and counts as unknown, which is what
7
+ * the Devices seen block asks the user to report.
8
+ */
9
+ export const DEVICE_NAMES = {
10
+ home_bike_v1: 'Bike',
11
+ home_bike_plus: 'Bike+',
12
+ prism: 'Tread',
13
+ t21n8m2: 'Guide',
14
+ apple_tv: 'Apple TV',
15
+ iPhone: 'iPhone',
16
+ iPad: 'iPad',
17
+ apple_health: 'Apple Health import',
18
+ };
19
+ /** True when the device_type has a display name, that is, the plugin has seen this hardware or app before. */
20
+ export function isKnownDevice(deviceType) {
21
+ return Object.hasOwn(DEVICE_NAMES, deviceType);
22
+ }
23
+ /** The display name for a device_type, or the raw code when the table has no entry for it. */
24
+ export function deviceDisplayName(deviceType) {
25
+ return isKnownDevice(deviceType) ? DEVICE_NAMES[deviceType] : deviceType;
26
+ }
27
+ //# sourceMappingURL=devices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.js","sourceRoot":"","sources":["../src/devices.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,YAAY,GAAqC;IAC5D,YAAY,EAAE,MAAM;IACpB,cAAc,EAAE,OAAO;IACvB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,YAAY,EAAE,qBAAqB;CACpC,CAAC;AAEF,8GAA8G;AAC9G,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAE,YAAY,CAAC,UAAU,CAAY,CAAC,CAAC,CAAC,UAAU,CAAC;AACvF,CAAC"}
@@ -128,6 +128,12 @@ export declare const BACKOFF_CAP_SECONDS = 60;
128
128
  export declare const GRAPH_EVERY_N = 5;
129
129
  /** A sample counts as stale once this many polls pass without a new one. */
130
130
  export declare const STALE_SAMPLE_POLLS = 2;
131
+ /**
132
+ * What the "workout started" line says in brackets (SPEC section 11): the discipline, then the class
133
+ * title when there is one (ride.title, else the workout's title, else its name), so an app class
134
+ * without a ride title logs the discipline alone rather than an empty title.
135
+ */
136
+ export declare function workoutLabel(workout: Workout): string;
131
137
  /**
132
138
  * Epoch milliseconds of the next occurrence of a local "HH:MM" time strictly after now, using the
133
139
  * process time zone. A malformed time falls back to 03:00.
@@ -158,6 +164,12 @@ export declare class Poller {
158
164
  private lastWorkoutEndAt;
159
165
  private autoOffTimer;
160
166
  private checkInTimer;
167
+ /** The end of the fast interval kept after the last workout end (SPEC section 8.4), and its timer. */
168
+ private fastUntil;
169
+ private keepFastTimer;
170
+ /** Every device_type and platform pair already recorded (SPEC section 8.2), loaded from the store on first use. */
171
+ private seenDevices;
172
+ private seenDevicesLoading;
161
173
  constructor(options: PollerOptions);
162
174
  get state(): PollerState;
163
175
  get switchOn(): boolean;
@@ -179,6 +191,8 @@ export declare class Poller {
179
191
  setSwitch(on: boolean): void;
180
192
  /** Runs the daily check-in now. start() schedules it at dailyCheckIn local time; tests call it directly. */
181
193
  checkInNow(): Promise<void>;
194
+ /** When the fast interval kept after the last workout end runs out, or undefined while none is running. */
195
+ get keepFastUntil(): number | undefined;
182
196
  /** When the auto-off timer will fire, or undefined while the switch is off. */
183
197
  get autoOffAt(): number | undefined;
184
198
  /**
@@ -193,6 +207,13 @@ export declare class Poller {
193
207
  private armAutoOff;
194
208
  private clearAutoOff;
195
209
  private autoOff;
210
+ /**
211
+ * Keeps the fast interval for keepFastAfterEndMinutes after a workout ends, whatever the switch,
212
+ * so a second workout is caught within one fast interval. When the window closes with the switch
213
+ * off, the household goes back on the standby schedule; with it on, nothing changes.
214
+ */
215
+ private armKeepFast;
216
+ private clearKeepFast;
196
217
  private scheduleCheckIn;
197
218
  /**
198
219
  * For each connected account: refresh the token, fetch /api/me for zones, avatar, and name, and
@@ -206,7 +227,7 @@ export declare class Poller {
206
227
  */
207
228
  private updateHousehold;
208
229
  private setState;
209
- /** The interval for standby or scanning in seconds, 0 for no polling. */
230
+ /** The interval for standby or scanning in seconds, 0 for no polling: fast while the switch is on or a workout ended recently (8.4). */
210
231
  private listInterval;
211
232
  private applySwitchChange;
212
233
  /** Polls every account now, then starts the staggered schedule. */
@@ -233,6 +254,16 @@ export declare class Poller {
233
254
  * and never counts as a poll failure.
234
255
  */
235
256
  private recordChecked;
257
+ /**
258
+ * Records the workout's device_type and platform pair the first time it is seen (SPEC section
259
+ * 8.2): the two codes and the fitness discipline of that workout, on the owner's record when the
260
+ * store knows one, else on the polled account's record. Never a workout id, title, date, or
261
+ * account detail. A pair whose device_type has no display name (src/devices.ts) logs one info
262
+ * line asking for a report. A failure to persist is logged at debug and is not a poll failure.
263
+ */
264
+ private recordDeviceSeen;
265
+ /** The pairs every stored record already carries, read once and kept in memory. */
266
+ private loadSeenDevices;
236
267
  private handlePollError;
237
268
  private dropAccount;
238
269
  /** One re-login attempt after invalid_grant; a failure leaves the account reconnect_needed. */