.. highlight:: csharp 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())) ); 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 :doc:`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())); } 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()) ); You can use the same ideas to create feedback loops by passing in the name assigned to the source processor. :: await metawear.GetModule().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(); 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().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()); break; } }); } await metawear.GetModule().DownloadAsync(); Console.WriteLine("Log download completed");