Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sensors_plus)!: add barometer support for all platforms #3079

Merged
merged 18 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
234321e
feat(sensors_plus): add barometer support for Android platform
aanas-sayed Jul 7, 2024
72fa27d
fix(sensors_plus): correct deprecated message for barometerEventStrea…
aanas-sayed Jul 8, 2024
fdd5bb5
feat(sensors_plus): implement non-existing barometer API for web plat…
aanas-sayed Jul 8, 2024
ecfe100
test(sensors_plus): add barometer unit test in /packages/sensors_plus…
aanas-sayed Jul 8, 2024
252c2e7
feat(sensors_plus): add barometer support for iOS platform (untested)
aanas-sayed Jul 8, 2024
f193d31
feat(sensors_plus): add barometer usage to /packages/sensors_plus/sen…
aanas-sayed Jul 8, 2024
dca0df8
docs(sensors_plus): update README.md
aanas-sayed Jul 8, 2024
3eb3d5d
test(sensors_plus): add barometer unit test in /packages/sensors_plus…
aanas-sayed Jul 8, 2024
97f309c
chore(sensors_plus): remove deprecated barometer methods
aanas-sayed Jul 8, 2024
fc5e91e
docs(sensors_plus): update plus plugins README.md
aanas-sayed Jul 10, 2024
1e319aa
Merge branch 'main' into dev/barometer-955
miquelbeltran Jul 12, 2024
8acef9e
add barometer comment for web
miquelbeltran Jul 12, 2024
f2cf878
fix(sensors_plus): remove unecessary barometer code for web
aanas-sayed Jul 13, 2024
df72c41
chore(sensors_plus): update packages/sensors_plus/sensors_plus/ios/se…
aanas-sayed Jul 14, 2024
cd65756
fix(sensors_plus): remove unnecessary CoreLocation for ios
aanas-sayed Jul 14, 2024
b1769e0
Merge branch 'fluttercommunity:main' into dev/barometer-955
aanas-sayed Jul 16, 2024
1147535
fix(sensors_plus): missing NSMotionUsageDescription for example
aanas-sayed Jul 17, 2024
f1dc2c9
fix(sensors_plus): incorrect type for pressure in FPPStreamHandlerPlu…
aanas-sayed Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ package, such as CFBundleVersion on iOS or versionCode on Android.

> [![sensors_plus][sensors_plus_badge_pub]][sensors_plus] [![pub points][sensors_plus_badge_pub_points]][sensors_plus_pub_points]

Flutter plugin for accessing accelerometer, gyroscope, and magnetometer sensors.
Flutter plugin for accessing accelerometer, gyroscope, magnetometer and barometer sensors.

[[View Source][sensors_plus_code]]

Expand Down
20 changes: 17 additions & 3 deletions packages/sensors_plus/sensors_plus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

[<img src="../../../assets/flutter-favorite-badge.png" width="100" />](https://flutter.dev/docs/development/packages-and-plugins/favorites)

A Flutter plugin to access the accelerometer, gyroscope, and magnetometer
sensors.
A Flutter plugin to access the accelerometer, gyroscope, magnetometer and
barometer sensors.

## Platform Support

Expand Down Expand Up @@ -54,9 +54,11 @@ This will expose such classes of sensor events through a set of streams:
- `GyroscopeEvent` describes the rotation of the device.
- `MagnetometerEvent` describes the ambient magnetic field surrounding the
device. A compass is an example usage of this data.
- `BarometerEvent` describes the atmospheric pressure surrounding the device.
An altimeter is an example usage of this data. Not supported on web browsers.

These events are exposed through a `BroadcastStream`: `accelerometerEvents`,
`userAccelerometerEvents`, `gyroscopeEvents`, and `magnetometerEvents`,
`userAccelerometerEvents`, `gyroscopeEvents`, `magnetometerEvents`, and `barometerEvents`,
respectively.

> [!NOTE]
Expand Down Expand Up @@ -116,6 +118,18 @@ magnetometerEvents.listen(
cancelOnError: true,
);
// [MagnetometerEvent (x: -23.6, y: 6.2, z: -34.9)]

barometerEvents.listen(
(BarometerEvent event) {
print(event);
},
onError: (error) {
// Logic to handle error
// Needed for Android in case sensor is not available
},
cancelOnError: true,
);
// [BarometerEvent (pressure: 1000.0)]
```

Alternatively, every stream allows to specify the sampling rate for its sensor using one of predefined constants or using a custom value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ class SensorsPlugin : FlutterPlugin {
private lateinit var userAccelChannel: EventChannel
private lateinit var gyroscopeChannel: EventChannel
private lateinit var magnetometerChannel: EventChannel
private lateinit var barometerChannel: EventChannel

private lateinit var accelerometerStreamHandler: StreamHandlerImpl
private lateinit var userAccelStreamHandler: StreamHandlerImpl
private lateinit var gyroscopeStreamHandler: StreamHandlerImpl
private lateinit var magnetometerStreamHandler: StreamHandlerImpl
private lateinit var barometerStreamHandler: StreamHandlerImpl

override fun onAttachedToEngine(binding: FlutterPluginBinding) {
setupMethodChannel(binding.binaryMessenger)
Expand All @@ -41,6 +43,7 @@ class SensorsPlugin : FlutterPlugin {
"setUserAccelerometerSamplingPeriod" -> userAccelStreamHandler
"setGyroscopeSamplingPeriod" -> gyroscopeStreamHandler
"setMagnetometerSamplingPeriod" -> magnetometerStreamHandler
"setBarometerSamplingPeriod" -> barometerStreamHandler
else -> null
}
streamHandler?.samplingPeriod = call.arguments as Int
Expand Down Expand Up @@ -86,18 +89,27 @@ class SensorsPlugin : FlutterPlugin {
Sensor.TYPE_MAGNETIC_FIELD
)
magnetometerChannel.setStreamHandler(magnetometerStreamHandler)

barometerChannel = EventChannel(messenger, BAROMETER_CHANNEL_NAME)
barometerStreamHandler = StreamHandlerImpl(
sensorsManager,
Sensor.TYPE_PRESSURE
)
barometerChannel.setStreamHandler(barometerStreamHandler)
}

private fun teardownEventChannels() {
accelerometerChannel.setStreamHandler(null)
userAccelChannel.setStreamHandler(null)
gyroscopeChannel.setStreamHandler(null)
magnetometerChannel.setStreamHandler(null)
barometerChannel.setStreamHandler(null)

accelerometerStreamHandler.onCancel(null)
userAccelStreamHandler.onCancel(null)
gyroscopeStreamHandler.onCancel(null)
magnetometerStreamHandler.onCancel(null)
barometerStreamHandler.onCancel(null)
}

companion object {
Expand All @@ -111,5 +123,7 @@ class SensorsPlugin : FlutterPlugin {
"dev.fluttercommunity.plus/sensors/user_accel"
private const val MAGNETOMETER_CHANNEL_NAME =
"dev.fluttercommunity.plus/sensors/magnetometer"
private const val BAROMETER_CHANNEL_NAME =
"dev.fluttercommunity.plus/sensors/barometer"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ internal class StreamHandlerImpl(
Sensor.TYPE_LINEAR_ACCELERATION -> "User Accelerometer"
Sensor.TYPE_GYROSCOPE -> "Gyroscope"
Sensor.TYPE_MAGNETIC_FIELD -> "Magnetometer"
Sensor.TYPE_PRESSURE -> "Barometer"
else -> "Undefined"
}
}
Expand Down
64 changes: 63 additions & 1 deletion packages/sensors_plus/sensors_plus/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,19 @@ class _MyHomePageState extends State<MyHomePage> {
AccelerometerEvent? _accelerometerEvent;
GyroscopeEvent? _gyroscopeEvent;
MagnetometerEvent? _magnetometerEvent;
BarometerEvent? _barometerEvent;

DateTime? _userAccelerometerUpdateTime;
DateTime? _accelerometerUpdateTime;
DateTime? _gyroscopeUpdateTime;
DateTime? _magnetometerUpdateTime;
DateTime? _barometerUpdateTime;

int? _userAccelerometerLastInterval;
int? _accelerometerLastInterval;
int? _gyroscopeLastInterval;
int? _magnetometerLastInterval;
int? _barometerLastInterval;
final _streamSubscriptions = <StreamSubscription<dynamic>>[];

Duration sensorInterval = SensorInterval.normalInterval;
Expand Down Expand Up @@ -101,7 +104,7 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
Padding(
padding: const EdgeInsets.all(20.0),
padding: const EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 0.0),
child: Table(
columnWidths: const {
0: FlexColumnWidth(4),
Expand Down Expand Up @@ -169,6 +172,35 @@ class _MyHomePageState extends State<MyHomePage> {
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 20.0),
child: Table(
columnWidths: const {
0: FlexColumnWidth(4),
1: FlexColumnWidth(3),
2: FlexColumnWidth(2),
},
children: [
const TableRow(
children: [
SizedBox.shrink(),
Text('Pressure'),
Text('Interval'),
],
),
TableRow(
children: [
const Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: Text('Barometer'),
),
Text(_barometerEvent?.pressure.toStringAsFixed(1) ?? '?'),
Text('${_barometerLastInterval?.toString() ?? '?'} ms'),
],
),
],
),
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Expand Down Expand Up @@ -209,6 +241,7 @@ class _MyHomePageState extends State<MyHomePage> {
accelerometerEventStream(samplingPeriod: sensorInterval);
gyroscopeEventStream(samplingPeriod: sensorInterval);
magnetometerEventStream(samplingPeriod: sensorInterval);
barometerEventStream(samplingPeriod: sensorInterval);
});
},
),
Expand Down Expand Up @@ -346,5 +379,34 @@ class _MyHomePageState extends State<MyHomePage> {
cancelOnError: true,
),
);
_streamSubscriptions.add(
barometerEventStream(samplingPeriod: sensorInterval).listen(
(BarometerEvent event) {
final now = DateTime.now();
setState(() {
_barometerEvent = event;
if (_barometerUpdateTime != null) {
final interval = now.difference(_barometerUpdateTime!);
if (interval > _ignoreDuration) {
_barometerLastInterval = interval.inMilliseconds;
}
}
});
_barometerUpdateTime = now;
},
onError: (e) {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text("Sensor Not Found"),
content: Text(
"It seems that your device doesn't support Barometer Sensor"),
);
});
},
cancelOnError: true,
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ public class FPPSensorsPlusPlugin: NSObject, FlutterPlugin {
_eventChannels[magnetometerStreamHandlerName] = magnetometerChannel
_streamHandlers[magnetometerStreamHandlerName] = magnetometerStreamHandler

let barometerStreamHandler = FPPBarometerStreamHandlerPlus()
let barometerStreamHandlerName = "dev.fluttercommunity.plus/sensors/barometer"
let barometerChannel = FlutterEventChannel(
name: barometerStreamHandlerName,
binaryMessenger: registrar.messenger()
)
barometerChannel.setStreamHandler(barometerStreamHandler)
_eventChannels[barometerStreamHandlerName] = barometerChannel
_streamHandlers[barometerStreamHandlerName] = barometerStreamHandler

let methodChannel = FlutterMethodChannel(
name: "dev.fluttercommunity.plus/sensors/method",
binaryMessenger: registrar.messenger()
Expand All @@ -66,6 +76,8 @@ public class FPPSensorsPlusPlugin: NSObject, FlutterPlugin {
streamHandler = _streamHandlers[gyroscopeStreamHandlerName]
case "setMagnetometerSamplingPeriod":
streamHandler = _streamHandlers[magnetometerStreamHandlerName]
case "setBarometerSamplingPeriod":
streamHandler = _streamHandlers[barometerStreamHandlerName]
default:
return result(FlutterMethodNotImplemented)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import Foundation
import Flutter
import UIKit
import CoreMotion
import CoreLocation
aanas-sayed marked this conversation as resolved.
Show resolved Hide resolved

let GRAVITY = 9.81
var _motionManager: CMMotionManager!
var _altimeter: CMAltimeter!

public protocol MotionStreamHandler: FlutterStreamHandler {
var samplingPeriod: Int { get set }
Expand All @@ -24,6 +26,12 @@ func _initMotionManager() {
}
}

func _initAltimeter() {
if (_altimeter == nil) {
_altimeter = CMAltimeter()
}
}

func sendTriplet(x: Float64, y: Float64, z: Float64, sink: @escaping FlutterEventSink) {
if _isCleanUp {
return
Expand Down Expand Up @@ -219,3 +227,56 @@ class FPPMagnetometerStreamHandlerPlus: NSObject, MotionStreamHandler {
FPPSensorsPlusPlugin._cleanUp()
}
}

class FPPBarometerStreamHandlerPlus: NSObject, MotionStreamHandler {

var samplingPeriod = 200000 {
didSet {
_initAltimeter()
// Note: CMAltimeter does not provide a way to set the sampling period directly.
// The sampling period would typically be managed by starting/stopping the updates.
}
}

func onListen(
withArguments arguments: Any?,
eventSink sink: @escaping FlutterEventSink
) -> FlutterError? {
_initAltimeter()
if CMAltimeter.isRelativeAltitudeAvailable() {
_altimeter.startRelativeAltitudeUpdates(to: OperationQueue()) { data, error in
if _isCleanUp {
return
}
if (error != nil) {
sink(FlutterError(
code: "UNAVAILABLE",
message: error!.localizedDescription,
details: nil
))
return
}
let pressure = data!.pressure.doubleValue * 10.0 // kPa to hPa (hectopascals)
DispatchQueue.main.async {
sink(pressure)
}
}
} else {
return FlutterError(
code: "UNAVAILABLE",
message: "Barometer is not available on this device",
details: nil
)
}
return nil
}

func onCancel(withArguments arguments: Any?) -> FlutterError? {
_altimeter.stopRelativeAltitudeUpdates()
return nil
}

func dealloc() {
FPPSensorsPlusPlugin._cleanUp()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Pod::Spec.new do |s|
s.version = '0.0.1'
s.summary = 'Flutter Sensors'
s.description = <<-DESC
Flutter plugin to access the accelerometer, gyroscope, and magnetometer sensors.
Flutter plugin to access the accelerometer, gyroscope, magnetometer, and barometer sensors.
aanas-sayed marked this conversation as resolved.
Show resolved Hide resolved
DESC
s.homepage = 'https://github.com/fluttercommunity/plus_plugins'
s.license = { :type => 'BSD', :file => '../LICENSE' }
Expand Down
9 changes: 9 additions & 0 deletions packages/sensors_plus/sensors_plus/lib/sensors_plus.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,12 @@ Stream<MagnetometerEvent> magnetometerEventStream({
}) {
return _sensors.magnetometerEventStream(samplingPeriod: samplingPeriod);
}

/// Returns a broadcast stream of events from the device barometer at the
/// given sampling frequency.
@override
Stream<BarometerEvent> barometerEventStream({
Duration samplingPeriod = SensorInterval.normalInterval,
}) {
return _sensors.barometerEventStream(samplingPeriod: samplingPeriod);
}
13 changes: 13 additions & 0 deletions packages/sensors_plus/sensors_plus/lib/src/sensors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,17 @@ class Sensors extends SensorsPlatform {
}) {
return _platform.magnetometerEventStream(samplingPeriod: samplingPeriod);
}

/// Returns a broadcast stream of events from the device barometer at the
/// given sampling frequency.
///
/// This method always returning the same stream. If this method is called
/// again, the sampling period of the stream will be update. All previous
/// listener will also be affected.
@override
Stream<BarometerEvent> barometerEventStream({
Duration samplingPeriod = SensorInterval.normalInterval,
}) {
return _platform.barometerEventStream(samplingPeriod: samplingPeriod);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ Stream<MagnetometerEvent> magnetometerEventStream({
}) {
return _sensors.magnetometerEventStream(samplingPeriod: samplingPeriod);
}

/// Returns a broadcast stream of events from the device barometer at the
/// given sampling frequency.
@override
Stream<BarometerEvent> barometerEventStream({
Duration samplingPeriod = SensorInterval.normalInterval,
}) {
return _sensors.barometerEventStream(samplingPeriod: samplingPeriod);
}
Loading
Loading