diff --git a/android/src/main/java/com/sensorworks/RNBarometer/RNBarometerModule.java b/android/src/main/java/com/sensorworks/RNBarometer/RNBarometerModule.java index d90f49e..23014db 100644 --- a/android/src/main/java/com/sensorworks/RNBarometer/RNBarometerModule.java +++ b/android/src/main/java/com/sensorworks/RNBarometer/RNBarometerModule.java @@ -26,14 +26,19 @@ @ReactModule(name = RNBarometerModule.NAME) public class RNBarometerModule extends ReactContextBaseJavaModule implements LifecycleEventListener, SensorEventListener { + public static final String NAME = "RNBarometer"; - private static final double kPressFilteringFactor = 0.3; + + public static final int DEFAULT_INTERVAL_MS = 200; // 5 Hz + public static final double DEFAULT_SMOOTHING_FACTOR = 0.7; + private static final int ignoreSamples = 10; private final ReactApplicationContext reactContext; private final SensorManager mSensorManager; private final Sensor mPressureSensor; private boolean isRunning; - private int mIntervalMillis; + private int mIntervalMillis = DEFAULT_INTERVAL_MS; + private double mSmoothingFactor = DEFAULT_SMOOTHING_FACTOR; private long mLastSampleTime; private double mInitialAltitude; private double mRelativeAltitude; @@ -55,7 +60,8 @@ public RNBarometerModule(ReactApplicationContext reactContext) { mLastSampleTime = 0; mRelativeAltitude = 0; mInitialAltitude = -1; - mIntervalMillis = 200; // 5Hz + mIntervalMillis = DEFAULT_INTERVAL_MS; + mSmoothingFactor = DEFAULT_SMOOTHING_FACTOR; isRunning = false; } @@ -120,6 +126,23 @@ public void setLocalPressure(double pressurehPa) { mLocalPressurehPa = pressurehPa; } + @ReactMethod + // Sets smoothing factor [0 -1]. + // Note: More smoothing means more latency before + // the smoothed value has "caught up with" current + // conditions. + public void setSmoothingFactor(double smoothingFactor) { + if (smoothingFactor >= 0 && smoothingFactor <= 1.0) { + mSmoothingFactor = smoothingFactor; + } + } + + @ReactMethod + // Gets smoothing factor + public void getSmoothingFactor(Promise promise) { + promise.resolve(mSmoothingFactor); + } + @ReactMethod // Starts observing pressure public void startObserving(Promise promise) { @@ -155,8 +178,8 @@ public void onSensorChanged(SensorEvent sensorEvent) { long timeSinceLastUpdate = tempMs - mLastSampleTime; if (timeSinceLastUpdate >= mIntervalMillis) { double lastAltitudeASL = mAltitudeASL; - // Get the filtered raw pressure in millibar/hPa - mRawPressure = (sensorEvent.values[0] * kPressFilteringFactor + mRawPressure * (1.0 - kPressFilteringFactor)); + // Get the smoothed raw pressure in millibar/hPa + mRawPressure = (sensorEvent.values[0] * (((double)1.0) - mSmoothingFactor) + mRawPressure * mSmoothingFactor); // Calculate standard atmosphere altitude in metres mAltitudeASL = getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, mRawPressure); // Calculate our vertical speed in metres per second diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..062bae1 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,43 @@ +// Module d.ts file + +// Enables using module in typescript react-native projects, +// with editor auto-complete and type-validation (in VS Code) + +// See: +// Typescript docs: +// https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html +// Typescript Playground, for automatic generation of .d.ts file from .js: +// https://www.typescriptlang.org/play?filetype=js&useJavaScript=true#code/Q +// Simplest approach: +// https://stackoverflow.com/a/51355583 + +declare module "react-native-barometer"; + +interface BarometerPayload { // See module README for field descriptions + timestamp:number, + pressure:number, + altitudeASL:number, + altitude:number, + relativeAltitude:number, + verticalSpeed:number, +}; + +type BarometerWatchCallbackFn = (payload:BarometerPayload) => void; + +declare namespace Barometer { // See module README for function descriptions + function isSupported(): Promise; + function setInterval(interval: number): void; + function setLocalPressure(pressure: number): void; + function watch(success: BarometerWatchCallbackFn): number; + function clearWatch(watchID: any): void; + function stopObserving(): void; + function setSmoothingFactor(smoothingFactor:double): void; + function getSmoothingFactor(): Promise; +} + +export { + BarometerPayload, + BarometerWatchCallbackFn +}; + +export default Barometer; diff --git a/index.js b/index.js index 091e171..fecde53 100644 --- a/index.js +++ b/index.js @@ -73,6 +73,19 @@ const Barometer = { // Sets the local air pressure in hPA/Millibars setLocalPressure: function(pressure) { RNBarometer.setLocalPressure(pressure); + }, + + // Sets smoothingFactor, a value [0 - 1] that determines + // how much smoothing is applied to the raw value. + // Note: More smoothing means more latency before + // the smoothed value has "caught up with" current + // conditions. + setSmoothingFactor: function(smoothingFactor) { + RNBarometer.setSmoothingFactor(smoothingFactor); + }, + + getSmoothingFactor: async function() { + return await RNBarometer.getSmoothingFactor(); } }; diff --git a/ios/RNBarometer.h b/ios/RNBarometer.h index c14ceef..e491551 100644 --- a/ios/RNBarometer.h +++ b/ios/RNBarometer.h @@ -13,6 +13,7 @@ double rawPressure; double altitudeASL; double altitude; + double smoothingFactor; } @end diff --git a/ios/RNBarometer.m b/ios/RNBarometer.m index cfb228b..c6ab717 100644 --- a/ios/RNBarometer.m +++ b/ios/RNBarometer.m @@ -8,6 +8,8 @@ #import const double STANDARD_ATMOSPHERE = 1013.25; +const long DEFAULT_INTERVAL_MS = 0.7; // 5 Hz +const double DEFAULT_SMOOTHING_FACTOR = 0.7; @implementation RNBarometer @@ -24,8 +26,9 @@ - (id) init { rawPressure = 0; altitudeASL = 0; lastSampleTime = 0; - intervalMillis = 200; // 5Hz + intervalMillis = DEFAULT_INTERVAL_MS; isRunning = false; + smoothingFactor = DEFAULT_SMOOTHING_FACTOR; } return self; } @@ -62,6 +65,24 @@ + (BOOL)requiresMainQueueSetup localPressurehPa = pressurehPa; } +// Sets smoothing factor [0 -1]. +// Note: More smoothing means more latency before +// the smoothed value has "caught up with" current +// conditions. +RCT_EXPORT_METHOD(setSmoothingFactor:(double) smoothingFactor) { + if (smoothingFactor >= 0 && smoothingFactor <= 1.0) { + self->smoothingFactor = smoothingFactor; + } +} + +// Get the smoothing factor +RCT_EXPORT_METHOD(getSmoothingFactor, + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { + return resolve(self->smoothingFactor); +} + + // Starts observing pressure RCT_EXPORT_METHOD(startObserving) { if(!isRunning) { @@ -71,7 +92,9 @@ + (BOOL)requiresMainQueueSetup if(timeSinceLastUpdate >= self->intervalMillis && altitudeData){ double lastAltitudeASL = self->altitudeASL; // Get the raw pressure in millibar/hPa - self->rawPressure = altitudeData.pressure.doubleValue * 10.0; // the x10 converts to millibar + double newRawPressure = altitudeData.pressure.doubleValue * 10.0; // the x10 converts to millibar + // Apply any smoothing + self->rawPressure = (newRawPressure * (((double)1.0) - mSmoothingFactor) + self->rawPressure * mSmoothingFactor); // Calculate standard atmpsphere altitude in metres self->altitudeASL = getAltitude(STANDARD_ATMOSPHERE, self->rawPressure); // Calculate our vertical speed in metres per second @@ -115,5 +138,6 @@ + (BOOL)requiresMainQueueSetup return 44330.0 * (1.0 - pow(p/p0, coef)); } + @end