Skip to content

Commit dd49698

Browse files
usmanvrtxM-Talha4
authored andcommitted
feat(activity): enhance motion data handling with pedometer support
1 parent af5474f commit dd49698

5 files changed

Lines changed: 404 additions & 170 deletions

File tree

modules/ensemble/lib/action/getMotionData.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ class GetMotionDataAction extends EnsembleAction {
4444
return GetMotionDataAction(
4545
initiator: initiator,
4646
id: Utils.optionalString(payload?['id']),
47-
onDataReceived: EnsembleAction.from(payload?['onDataReceived']),
48-
onError: EnsembleAction.from(payload?['onError']),
47+
onDataReceived:
48+
EnsembleAction.from(payload?['options']?['onDataReceived']),
49+
onError: EnsembleAction.from(payload?['options']?['onError']),
4950
recurring: Utils.optionalBool(payload?['options']?['recurring']),
5051
sensorType: sensorType,
5152
updateInterval: Utils.optionalInt(payload?['options']?['updateInterval']),

modules/ensemble/lib/framework/stub/activity_manager.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,22 @@ class MotionData {
3939
this.accelerometer,
4040
this.gyroscope,
4141
this.magnetometer,
42+
this.pedometer,
4243
required this.timestamp,
4344
});
4445

4546
final AccelerometerData? accelerometer;
4647
final GyroscopeData? gyroscope;
4748
final MagnetometerData? magnetometer;
49+
final PedometerData? pedometer;
4850
final DateTime timestamp;
4951

5052
Map<String, dynamic> toJson() {
5153
return {
5254
'accelerometer': accelerometer?.toJson(),
5355
'gyroscope': gyroscope?.toJson(),
5456
'magnetometer': magnetometer?.toJson(),
57+
'pedometer': pedometer?.toJson(),
5558
'timestamp': timestamp.toIso8601String(),
5659
};
5760
}
@@ -93,9 +96,32 @@ class MagnetometerData {
9396
}
9497
}
9598

99+
class PedometerData {
100+
PedometerData(
101+
{required this.steps,
102+
required this.stepsOnStart,
103+
required this.distanceMeters,
104+
required this.status});
105+
106+
final int steps;
107+
final int stepsOnStart;
108+
final double distanceMeters;
109+
final String status;
110+
111+
Map<String, dynamic> toJson() {
112+
return {
113+
'steps': steps,
114+
'stepsOnStart': stepsOnStart,
115+
'distanceMeters': distanceMeters,
116+
'status': status
117+
};
118+
}
119+
}
120+
96121
enum MotionSensorType {
97122
accelerometer,
98123
gyroscope,
99124
magnetometer,
125+
pedometer,
100126
all,
101127
}
Lines changed: 174 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,180 @@
11
# Ensemble Activity
22

3-
This ensemble activity module handles motion sensor (direction, movement patterns) functionality for tracking user activity and movement.
3+
The Ensemble Activity module provides access to device motion and activity sensors for tracking user movement and orientation. It supports real-time streaming and one-time reads of motion data, with optional sensor selection.
4+
5+
---
46

57
## Features
68

79
### Motion Sensors
8-
- Accelerometer data (x, y, z axes)
9-
- Gyroscope data (rotation rates)
10-
- Magnetometer data (compass direction)
11-
- Combined motion data streams
12-
- Configurable update intervals
13-
14-
## Usage
15-
16-
The module provides actions that can be used in Ensemble YAML configurations:
17-
18-
- `getMotionData`: Get motion sensor data (accelerometer, gyroscope, magnetometer)
19-
- `id`: Optional identifier for the motion data stream
20-
- `options`: Optional options for the motion data stream
21-
- `recurring`: Whether to get motion data recurringly
22-
- `sensorType`: The type of sensor to get data from (accelerometer, gyroscope, magnetometer, all)
23-
- `updateInterval`: The interval in milliseconds to get motion data (default is 1000 milliseconds)
24-
- `onDataReceived`: The action to execute when motion data is received
25-
- `onError`: The action to execute when an error occurs
26-
- Example:
27-
- ```yaml
28-
getMotionData:
29-
id: motion_stream_1
30-
options:
31-
recurring: true
32-
sensorType: all
33-
updateInterval: 1000
34-
onDataReceived:
35-
executeCode:
36-
body: |-
37-
console.log(event.data);
38-
onError:
39-
showToast:
40-
message: "Error: ${event.error}"
41-
```
42-
- `stopMotionData`: Stop motion sensor data stream
43-
- `id`: Optional identifier for the motion data stream
44-
- Example:
45-
- ```yaml
46-
stopMotionData:
47-
id: motion_stream_1
48-
```
10+
- Accelerometer (x, y, z axes)
11+
- Gyroscope (rotation rates)
12+
- Magnetometer (compass / magnetic field)
13+
- Pedometer
14+
- Step count since stream start
15+
- Pedestrian status (walking, stopped, etc.)
16+
- Distance estimation
17+
18+
### Streaming Capabilities
19+
- Combined or single-sensor streams
20+
- Broadcast streams (multiple listeners supported)
21+
- Explicit start / stop lifecycle
22+
- Automatic cleanup on cancel
23+
24+
### Permissions
25+
- Automatically requests **Activity Recognition** permission when using:
26+
- `pedometer`
27+
- `all`
28+
- Emits an error if permission is denied
29+
30+
---
31+
32+
## Motion Data Model
33+
34+
Each emitted event contains a `MotionData` object:
35+
36+
```json
37+
{
38+
"accelerometer": { "x": 0.0, "y": 0.0, "z": 0.0 },
39+
"gyroscope": { "x": 0.0, "y": 0.0, "z": 0.0 },
40+
"magnetometer": { "x": 0.0, "y": 0.0, "z": 0.0 },
41+
"pedometer": {
42+
"steps": 120,
43+
"status": "walking",
44+
"stepsOnStart": 3450,
45+
"distanceMeters": 90.0
46+
},
47+
"timestamp": "2026-02-07T10:30:00.000Z"
48+
}
49+
```
50+
51+
> Only the requested sensors will be populated. Others may be `null`.
52+
53+
---
54+
55+
## Available Actions (YAML)
56+
57+
### `getMotionData`
58+
59+
Starts a motion sensor stream or retrieves motion data.
60+
61+
#### Parameters
62+
63+
| Field | Type | Description |
64+
|------|------|------------|
65+
| `id` | string (optional) | Identifier for the motion stream |
66+
| `options.recurring` | boolean | If `true`, keeps streaming until stopped |
67+
| `options.sensorType` | string | `accelerometer`, `gyroscope`, `magnetometer`, `pedometer`, `all` |
68+
| `options.updateInterval` | number | Update interval in milliseconds (default: 1000) |
69+
| `options.onDataReceived` | action | Executed when motion data is emitted |
70+
| `options.onError` | action | Executed when an error occurs |
71+
72+
#### Notes
73+
- If a stream with the same `id` is already running, the existing stream is reused
74+
- For `pedometer` and `all`, activity permission is requested automatically
75+
- Pedometer steps are reset when the stream starts
76+
77+
---
78+
79+
### Example: All Sensors (Recurring)
80+
81+
```yaml
82+
getMotionData:
83+
id: motion_all
84+
options:
85+
recurring: true
86+
sensorType: all
87+
updateInterval: 1000
88+
onDataReceived:
89+
executeCode:
90+
body: |-
91+
console.log('All motion:', event.data);
92+
onError:
93+
executeCode:
94+
body: |-
95+
console.log('Motion error:', event.error);
96+
```
97+
98+
---
99+
100+
### Example: Pedometer Only
101+
102+
```yaml
103+
getMotionData:
104+
id: pedometer_stream
105+
options:
106+
recurring: true
107+
sensorType: pedometer
108+
updateInterval: 1000
109+
onDataReceived:
110+
executeCode:
111+
body: |-
112+
if (event.data.pedometer) {
113+
console.log(
114+
'Steps:',
115+
event.data.pedometer.steps,
116+
'Distance:',
117+
event.data.pedometer.distanceMeters
118+
);
119+
}
120+
```
121+
122+
---
123+
124+
### One-Time Motion Read
125+
126+
Returns the first available motion event and automatically stops the stream.
127+
128+
```yaml
129+
getMotionData:
130+
options:
131+
sensorType: accelerometer
132+
onDataReceived:
133+
executeCode:
134+
body: |-
135+
console.log('Single accelerometer read:', event.data);
136+
```
137+
138+
---
139+
140+
## `stopMotionData`
141+
142+
Stops a running motion stream and releases all sensor subscriptions.
143+
144+
### Parameters
145+
146+
| Field | Type | Description |
147+
|------|------|------------|
148+
| `id` | string (optional) | ID of the motion stream to stop |
149+
150+
### Behavior
151+
- Cancels all active sensor subscriptions
152+
- Stops pedometer tracking
153+
- Resets internal state (steps and cached sensor values)
154+
- Closes the motion stream controller
155+
156+
### Example
157+
158+
```yaml
159+
stopMotionData:
160+
id: motion_all
161+
```
162+
163+
---
164+
165+
## Lifecycle Notes
166+
167+
- Multiple sensors are merged into a single stream
168+
- A new `MotionData` event is emitted whenever any sensor updates
169+
- Calling `stopMotionData` fully resets the activity state
170+
- Cancelling the stream from the UI automatically stops motion tracking
171+
172+
---
173+
174+
## Platform Notes
175+
176+
- **Android**
177+
- Requires `ACTIVITY_RECOGNITION` permission for pedometer
178+
- **iOS**
179+
- Uses Core Motion pedometer APIs
180+
- Distance is estimated using a fixed step length of `0.75 meters`

0 commit comments

Comments
 (0)