Advanced Features¶
High Frequency Streaming¶
Some developers may want to stream data from multiple motion sensors simultaneously or individually at frequencies higher than 100Hz. To accommodate this use case, acceleration, angular velocity, and magnetic field data have a packed output mode that combines 3 data samples into 1 ble packett increasing the data throughput by 3x.
// stream at 200Hz
accelerometer.Configure(odr: 200f, range: 4f);
await accelerometer.PackedAcceleration.AddRouteAsync(source =>
source.Stream(data => Console.WriteLine(data.Value<Acceleration>()))
);
accelerometer.PackedAcceleration.Start();
accelerometer.Start();
In addition to using packed output, developers will also need to reduce the max connection interval to 7.5ms (11.25ms for Android M+). Reducing the max connection interval can also be used to speed up log downloads.
settings.EditBleConnParams(maxConnInterval: 7.5f);
Serialization¶
The internal state of the IMetaWearBoard
interface can be saved to persist the object through app crashes or combined with the Macro ssystem
to rebuild the object state after saved commands are executed. Use
SerializeAsync to save the state to the local disk
and call DeserializeAsync to restore the state.
With regards to data routes, the delegates that are used with the Stream
and Log
components cannot be serialized so you will need to reassign
them after deserialization by calling AttachSubscriber
.
public async Task SerializeAccRoute() {
var route = await accelerometer.Acceleration.AddRouteAsync(source => source.Log());
Console.WriteLine("route id = " + route.ID);
// save route ID as well
await metawear.SerializeAsync();
}
public async Task DeserializeAccRoute() {
await metawear.DeserializeAsync();
// deserialize route ID: uint id = ...
var route = metawear.LookupRoute(id);
route.AttachSubscriber(0, data => Console.WriteLine(data.Value<Acceleration>()));
}
Forwarding Data¶
As you may have noticed, there are variant Map and Filter components that accept strings rather than numbers. These strings are used to signify that right hand operands for math and comparison operations should come from the data producer, and will automatically update with the newest data vaues.
For example, lets say you wanted to find the difference between the y and x axis values for acceleration data. Setup the mapper to use the x-axis data
by naming it then using the same name in the Map
construct.
await accelerometer.Acceleration.AddRouteAsync(source =>
source.Split()
.Index(0).Name("x-axis")
.Index(1).Delay(1).Map(Function2.Subtract, "x-axis")
.Stream(data => Console.WriteLine("y - x = " + data.Value<float>())
);
You can use the same ideas to create feedback loops by passing in the name assigned to the source processor.
await metawear.GetModule<IGpio>().Pins[0].Adc.AddRouteAsync(source =>
source.Filter(Comparison.Gt, "reference").Name("reference")
);
Data Token¶
The IDataToken interface is another mechanism for forwarding
data. Unlike the string keys, IDataToken
objects are used with the API functions that are not a part of the data route API.
var iswitch = metawear.GetModule<ISwitch>();
await iswitch.State.AddRouteAsync(source => source.Count().React(token => ibeacon.SetMajor(token)));
Anonymous Routes¶
Anonymous routes are a pared down variant of the IRoute interface that only has one subscriber. They are used to retrieved logged data from a board that was not programmed by the current device.
Because of the anonymous nature of the interface, users will need to rely on an identifier string to determine what kind of data is being passed to each route. Developers can manage these identifiers by calling GenerateIdentifier for every logging subscriber and hardcoding the strings into the anonymous routes.
// create a route to log gyro y-axis data
var route = await metawear.GetModule<IGyroBmi160>().AngularVelocity.AddRouteAsync(source =>
source.Split().Index(1).Log()
);
Console.WriteLine("subscriber(0) = " + route.Subscribers[0].Identifier);
// Use createAnonymousRoutesAsync to retrieve log data from
// another device
foreach(var route in await metawear.CreateAnonymousRoutesAsync()) {
route.Subscribe(data => {
switch (route.Identifier) {
case "angular-velocity[1]":
Console.WriteLine("gyro y-axis: " + data.Value<float>());
break;
}
});
}
await metawear.GetModule<ILogging>().DownloadAsync();
Console.WriteLine("Log download completed");