Device status
Read the device information, model, battery level and system states of a connected sensor.
Once a sensor is connected, your app can check which model it is and which firmware it runs. It can also check whether the battery is low, and follow states such as taps and the attachment to a strap. MovesenseDevice reads all of this from the sensor through the Movesense mobile library (MDS):
| Member | Type | Resource |
|---|---|---|
deviceInfo, getDeviceInfo() | MovesenseDeviceInfo? | /Info |
deviceType | MovesenseDeviceType | /Info |
batteryLevel, getBatteryStatus() | MovesenseBatteryLevel | /System/States/1 |
getState() | MovesenseState? | /System/States/<state_id> |
getStateEvents() | Stream<MovesenseState> | /System/States/<state_id> |
The samples on this page assume a connected MovesenseDevice named device. To connect one, see Connecting a device.
Read the device information
deviceInfo holds the /Info resource of the sensor as a MovesenseDeviceInfo. MovesenseDevice reads it when the sensor connects.
If that read fails, the connection still completes, and deviceInfo may be null. deviceInfo keeps its value after the sensor disconnects.
getDeviceInfo() reads /Info again and caches the result in deviceInfo. It returns null when the sensor is not connected, and throws an MdsError when MDS reports an error:
MovesenseDeviceInfo has these fields:
| Field | Type | Description |
|---|---|---|
manufacturerName | String | The manufacturer, such as Movesense Ltd. |
brandName | String? | The brand name of the sensor. |
productName | String | The product name, such as Movesense. |
variant | String | The internal name of the firmware variant, such as Avocado. |
design | String | The product design name, such as black. |
hwCompatibilityId | String | Identifies which firmware can be installed on the sensor. |
serial | String | The unique 12-digit serial number of the sensor. MDS addresses the sensor by it. |
pcbaSerial | String | The unique identifier of the printed circuit board assembly (PCBA). |
sw | String | The firmware version, such as 2.1.5. |
hw | String | The hardware type, such as H4. deviceType derives the model from it. |
additionalVersionInfo | String? | More version information, converted to a string. |
addressInfo | List<MovesenseAddressInfo> | The addresses of the sensor. Each has a name, which is the address type such as BLE or DFU-BLE, and an address. |
apiLevel | String | The Movesense API level, such as 1. |
A missing or null value in the response becomes an empty string, or an empty list for addressInfo. Only brandName and additionalVersionInfo can be null. Other fields of the response, such as hwConfig, are dropped.
The plugin's tests use this /Info response of a Movesense HR2:
For a MovesenseDeviceInfo that you build yourself, for example from a raw request or from stored JSON, use these members:
| Member | Description |
|---|---|
MovesenseDeviceInfo.fromMovesenseData() | Builds the information from a decoded /Info response, with or without its Content wrapper. |
MovesenseDeviceInfo.fromJson() | Builds the information from the bare content object, the form that toJson() writes. |
toJson() | Returns the fields in the table above as a map, with addressInfo as a list of maps with name and address. |
deviceType | Derives the model from hw with the same mapping as MovesenseDevice, so it also works for stored information without a connected sensor. |
To keep the device information between app starts, encode it as JSON:
Identify the model
deviceType derives the model of the sensor, a MovesenseDeviceType, from the hw field of deviceInfo:
hw | deviceType | Sensor |
|---|---|---|
A1 | md | Movesense MD |
H3 | hrPlus | Movesense Active HR+ |
H4 | hr2 | Movesense HR2 |
| Any other value | unknown | Unrecognized hardware |
The comparison ignores case, and deviceType is unknown while deviceInfo is null. MovesenseDeviceType.fromHardwareType() derives the model from a raw hw string in the same way. The enum also has flash for the Movesense FLASH sensor, but the plugin never derives it.
This switch turns the model into a name to show the user:
The model also tells you which data the sensor offers: the Movesense HR2 has no temperature sensor. See Stream temperature.
Read the battery level
batteryLevel holds the battery state as a MovesenseBatteryLevel: ok, low or unknown. /System/States/1 reports only whether the battery is OK or low, not a percentage.
MovesenseDevice reads the level when the sensor connects and does not read it again by itself. disconnect() and a disconnected event reset it to unknown. To refresh the level, call getBatteryStatus(), which reads /System/States/1 and caches the result in batteryLevel:
getBatteryStatus() does not throw for MDS errors. It returns unknown when the sensor is not connected or answers with an MDS error. It also returns unknown for any value other than 0 and 1.
The Movesense API also defines /System/Energy/Level, which gives an estimated charge in percent. To read it, see Send a request.
Read a system state
The system states of a sensor describe its movement, battery, connector, taps and free fall. getState() reads the current state of one MovesenseSystemState component from /System/States/<state_id>.
It returns a MovesenseState, or null when the sensor is not connected or answers with an MDS error. The error may mean that the sensor does not support the component.
Each component has a StateId in the Movesense API. The plugin decodes the raw value into a MovesenseDeviceState:
| Component | StateId | Raw values | Decoded state |
|---|---|---|---|
movement | 0 | 0 not moving, 1 moving | notMoving for 0, otherwise moving |
battery | 1 | 0 OK, 1 low | Always unknown |
connectors | 2 | 0 disconnected, 1 connected to gear, 2 unknown | disconnected for 0, otherwise connected |
doubleTap | 3 | 0 normal, 1 double-tapped, 2 unknown | doubleTap for 1, otherwise unknown |
tap | 4 | 0 no tap, 1 tapped, 2 unknown | tap for 1, otherwise unknown |
freeFall | 5 | 0 under acceleration, 1 free fall, 2 unknown | acceleration for 0, otherwise freeFall |
stateId returns the StateId of a component, for example to build the resource '/System/States/${MovesenseSystemState.connectors.stateId}' for an MDS request.
The decoded state hides some raw values, and some states are hard to read with getState():
- Connectors: the unknown value
2decodes asconnected. To tell an unknown state from a connected one, checkvalue. - Free fall: the unknown value
2decodes asfreeFall. To tell an unknown state from a free fall, checkvalue. - Battery:
stateis alwaysunknown. Readvalueand map it withMovesenseBatteryLevel.fromStateValue(), or usegetBatteryStatus(). - Movement: a read may return
nullunless the accelerometer is running, for example while you stream inertial measurement unit (IMU) data. See Stream IMU data. - Tap and double tap: the value is
1when the sensor detects a tap and returns to0right after, which decodes asunknown. Follow taps with state events.
MovesenseState has these fields:
| Field | Type | Description |
|---|---|---|
component | MovesenseSystemState | The component that the state belongs to. |
state | MovesenseDeviceState | The decoded state. |
value | int | The raw value that the sensor reported. |
timestamp | int? | The sensor's timestamp in milliseconds for state events, and null for getState() reads. |
This read checks the connector through value:
Subscribe to state events
getStateEvents() subscribes to one component and emits a MovesenseState each time its state changes:
The stream does not emit the state at the time you subscribe; if you need it, read it with getState() first. Like the data streams, it is single-subscription: listening subscribes on the sensor, and canceling unsubscribes. It emits a StateError when the sensor is not connected, and an MdsError when the sensor rejects the subscription.
The sensor allows only one subscription at a time to the motion states: movement, tap, doubleTap and freeFall. A further one fails with an MdsError, as issue #15 of mdsflutter reports, so subscribe to one motion state at a time.
Not every sensor supports every component either: the plugin's authors have confirmed only connectors and tap on the Movesense MD and Movesense HR2.
timestamp comes from the sensor's own clock, in milliseconds since the sensor started, not from the phone. See Timestamps.