Skip to content

Commit

Permalink
Heading logic
Browse files Browse the repository at this point in the history
  • Loading branch information
firofame committed Aug 8, 2019
1 parent 32a30cc commit 633c087
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 14 deletions.
107 changes: 103 additions & 4 deletions android/src/main/java/com/reactlibrary/CompassHeadingModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,40 @@
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

public class CompassHeadingModule extends ReactContextBaseJavaModule {
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

import android.content.Context;

import com.facebook.react.modules.core.DeviceEventManagerModule;

public class CompassHeadingModule extends ReactContextBaseJavaModule implements SensorEventListener {

private final ReactApplicationContext reactContext;

private static Context mApplicationContext;

private int mAzimuth = 0; // degree
private int mFilter = 1;

private SensorManager sensorManager;

private Sensor gsensor;
private Sensor msensor;

private float[] mGravity = new float[3];
private float[] mGeomagnetic = new float[3];

private float[] R = new float[9];
private float[] I = new float[9];

public CompassHeadingModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;

mApplicationContext = reactContext.getApplicationContext();
}

@Override
Expand All @@ -20,8 +47,80 @@ public String getName() {
}

@ReactMethod
public void sampleMethod(String stringArgument, int numberArgument, Callback callback) {
// TODO: Implement some actually useful functionality
callback.invoke("Received numberArgument: " + numberArgument + " stringArgument: " + stringArgument);
public void start(int filter) {

sensorManager = (SensorManager) mApplicationContext.getSystemService(Context.SENSOR_SERVICE);

gsensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
msensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

sensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_GAME);

mFilter = filter;
}

@ReactMethod
public void stop() {
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}

@Override
public void onSensorChanged(SensorEvent event) {

final float alpha = 0.97f;

synchronized (this) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

mGravity[0] = alpha * mGravity[0] + (1 - alpha)
* event.values[0];
mGravity[1] = alpha * mGravity[1] + (1 - alpha)
* event.values[1];
mGravity[2] = alpha * mGravity[2] + (1 - alpha)
* event.values[2];
}

if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {

mGeomagnetic[0] = alpha * mGeomagnetic[0] + (1 - alpha)
* event.values[0];
mGeomagnetic[1] = alpha * mGeomagnetic[1] + (1 - alpha)
* event.values[1];
mGeomagnetic[2] = alpha * mGeomagnetic[2] + (1 - alpha)
* event.values[2];

}

boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);

if (success) {

float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);

int newAzimuth = (int) Math.toDegrees(orientation[0]);
newAzimuth = (newAzimuth + 360) % 360;

if (Math.abs(mAzimuth - newAzimuth) > mFilter) {

mAzimuth = newAzimuth;

getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("HeadingUpdated", mAzimuth);
}
}
}


}


@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
}
26 changes: 25 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
import { NativeModules } from 'react-native';
import { NativeModules, NativeEventEmitter } from 'react-native';

const { CompassHeading } = NativeModules;

let listener;

//Monkey patching
let _start = CompassHeading.start;
CompassHeading.start = (update_rate, callback) => {
if (listener) {
CompassHeading.stop();
}

const compassEventEmitter = new NativeEventEmitter(CompassHeading);
listener = compassEventEmitter.addListener('HeadingUpdated', (degree) => {
callback(degree);
});

_start(update_rate === null ? 0 : update_rate);
}

let _stop = CompassHeading.stop;
CompassHeading.stop = () => {
listener && listener.remove();
listener = null;
_stop();
}

export default CompassHeading;
3 changes: 2 additions & 1 deletion ios/CompassHeading.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>

@interface CompassHeading : NSObject <RCTBridgeModule>
@interface CompassHeading : RCTEventEmitter <RCTBridgeModule>

@end
68 changes: 65 additions & 3 deletions ios/CompassHeading.m
Original file line number Diff line number Diff line change
@@ -1,14 +1,76 @@
#import "CompassHeading.h"
#import <React/RCTEventDispatcher.h>
#import <Corelocation/CoreLocation.h>

#define kHeadingUpdated @"HeadingUpdated"

@interface CompassHeading() <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@end

@implementation CompassHeading

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(sampleMethod:(NSString *)stringArgument numberParameter:(nonnull NSNumber *)numberArgument callback:(RCTResponseSenderBlock)callback)
- (instancetype)init {
if (self = [super init]) {
if ([CLLocationManager headingAvailable]) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
}
else {
NSLog(@"Heading not available");
}
}

return self;
}

#pragma mark - RCTEventEmitter

- (NSArray<NSString *> *)supportedEvents {
return @[kHeadingUpdated];
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
if (newHeading.headingAccuracy < 0) {
return;
}
[self sendEventWithName:kHeadingUpdated body:@(newHeading.trueHeading)];
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
NSLog(@"AuthoriationStatus changed: %i", status);
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"Location manager failed: %@", error);
}

- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager
{
CLLocationDirection accuracy = [[manager heading] headingAccuracy];
return false; //accuracy <= 0.0f || accuracy > 10.0f;
}

#pragma mark - React

RCT_EXPORT_METHOD(start: (NSInteger) headingFilter) {
self.locationManager.headingFilter = headingFilter;
[self.locationManager startUpdatingHeading];
}

RCT_EXPORT_METHOD(stop) {
[self.locationManager stopUpdatingHeading];
}

RCT_EXPORT_MODULE()

+ (BOOL)requiresMainQueueSetup
{
// TODO: Implement some actually useful functionality
callback(@[[NSString stringWithFormat: @"numberArgument: %@ stringArgument: %@", numberArgument, stringArgument]]);
return NO;
}

@end
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/github_account/react-native-compass-heading.git",
"baseUrl": "https://github.com/github_account/react-native-compass-heading"
"url": "git+https://github.com/firofame/react-native-compass-heading.git",
"baseUrl": "https://github.com/firofame/react-native-compass-heading"
},
"keywords": [
"react-native"
Expand Down
6 changes: 3 additions & 3 deletions react-native-compass-heading.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ Pod::Spec.new do |s|
s.description = <<-DESC
react-native-compass-heading
DESC
s.homepage = "https://github.com/github_account/react-native-compass-heading"
s.homepage = "https://github.com/firofame/react-native-compass-heading"
s.license = "MIT"
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
s.authors = { "Your Name" => "yourname@email.com" }
s.authors = { "Your Name" => "firofame@gmail.com" }
s.platform = :ios, "7.0"
s.source = { :git => "https://github.com/github_account/react-native-compass-heading.git", :tag => "#{s.version}" }
s.source = { :git => "https://github.com/firofame/react-native-compass-heading.git", :tag => "#{s.version}" }

s.source_files = "ios/**/*.{h,m,swift}"
s.requires_arc = true
Expand Down

0 comments on commit 633c087

Please sign in to comment.