import { Subscription } from '@unimodules/core';
import * as Sensors from 'expo-sensors';
import React from 'react';
import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const FAST_INTERVAL = 16;
const SLOW_INTERVAL = 1000;
export default class SensorScreen extends React.Component {
static navigationOptions = {
title: 'Sensors',
};
render() {
return (
);
}
}
interface State {
data: M;
isAvailable?: boolean;
}
// See: https://github.com/expo/expo/pull/10229#discussion_r490961694
// eslint-disable-next-line @typescript-eslint/ban-types
abstract class SensorBlock extends React.Component<{}, State> {
readonly state: State = { data: {} as M };
_subscription?: Subscription;
componentDidMount() {
this.checkAvailability();
}
checkAvailability = async () => {
const isAvailable = await this.getSensor().isAvailableAsync();
this.setState({ isAvailable });
};
componentWillUnmount() {
this._unsubscribe();
}
abstract getName: () => string;
abstract getSensor: () => Sensors.DeviceSensor;
abstract renderData: () => JSX.Element;
_toggle = () => {
if (this._subscription) {
this._unsubscribe();
} else {
this._subscribe();
}
};
_slow = () => {
this.getSensor().setUpdateInterval(SLOW_INTERVAL);
};
_fast = () => {
this.getSensor().setUpdateInterval(FAST_INTERVAL);
};
_subscribe = () => {
this._subscription = this.getSensor().addListener((data: any) => {
this.setState({ data });
});
};
_unsubscribe = () => {
this._subscription && this._subscription.remove();
this._subscription = undefined;
};
render() {
if (this.state.isAvailable !== true) {
return null;
}
return (
{this.getName()}:
{this.renderData()}
Toggle
Slow
Fast
);
}
}
abstract class ThreeAxisSensorBlock extends SensorBlock {
renderData = () => (
x: {round(this.state.data.x)} y: {round(this.state.data.y)} z: {round(this.state.data.z)}
);
}
class GyroscopeSensor extends ThreeAxisSensorBlock {
getName = () => 'Gyroscope';
getSensor = () => Sensors.Gyroscope;
}
class AccelerometerSensor extends ThreeAxisSensorBlock {
getName = () => 'Accelerometer';
getSensor = () => Sensors.Accelerometer;
}
class MagnetometerSensor extends ThreeAxisSensorBlock {
getName = () => 'Magnetometer';
getSensor = () => Sensors.Magnetometer;
}
class MagnetometerUncalibratedSensor extends ThreeAxisSensorBlock {
getName = () => 'Magnetometer (Uncalibrated)';
getSensor = () => Sensors.MagnetometerUncalibrated;
}
class DeviceMotionSensor extends SensorBlock {
getName = () => 'DeviceMotion';
getSensor = () => Sensors.DeviceMotion;
renderXYZBlock = (name: string, event: null | { x?: number; y?: number; z?: number } = {}) => {
if (!event) return null;
const { x, y, z } = event;
return (
{name}: x: {round(x)} y: {round(y)} z: {round(z)}
);
};
renderABGBlock = (
name: string,
event: null | { alpha?: number; beta?: number; gamma?: number } = {}
) => {
if (!event) return null;
const { alpha, beta, gamma } = event;
return (
{name}: α: {round(alpha)} β: {round(beta)} γ: {round(gamma)}
);
};
renderData = () => (
{this.renderXYZBlock('Acceleration', this.state.data.acceleration)}
{this.renderXYZBlock('Acceleration w/gravity', this.state.data.accelerationIncludingGravity)}
{this.renderABGBlock('Rotation', this.state.data.rotation)}
{this.renderABGBlock('Rotation rate', this.state.data.rotationRate)}
Orientation: {this.state.data.orientation}
);
}
class BarometerSensor extends SensorBlock {
getName = () => 'Barometer';
getSensor = () => Sensors.Barometer;
renderData = () => (
Pressure: {this.state.data.pressure}
Relative Altitude: {this.state.data.relativeAltitude}
);
}
function round(n?: number) {
if (!n) {
return 0;
}
return Math.floor(n * 100) / 100;
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginBottom: 10,
},
buttonContainer: {
flexDirection: 'row',
alignItems: 'stretch',
marginTop: 15,
},
button: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#eee',
padding: 10,
},
middleButton: {
borderLeftWidth: 1,
borderRightWidth: 1,
borderColor: '#ccc',
},
sensor: {
marginTop: 15,
paddingHorizontal: 10,
},
});