Files
birdbam/UserInterface.js
2020-06-23 12:31:32 -05:00

395 lines
15 KiB
JavaScript

// Secrets
/*
Secrets
Inputs:
trackme - hit set token to set fixed location to dynamic
setrad:<feet> - hit scan button to set scan radius
map: shows a map UI
*/
import React from 'react';
import { Alert, StyleSheet, AsyncStorage, Image, Text, View } from 'react-native';
import Button from './Button';
import PTextInput from './TextInput';
import Hero from 'react-native-hero';
export default class UserInterface extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "",
status: "Not logged in",
token: undefined,
radius: "10000.0",
location: {
"timestamp": 1533729980953.91,
"coords": {
"accuracy": 5,
"altitude": 0,
"altitudeAccuracy": -1,
"heading": -1,
"latitude": 39.03467555,
"longitude": -94.5804479,
"speed": -1
}
},
birdsobj: undefined
}
}
// Feet calculation
distance(lat1, lon1, lat2, lon2) {
if ((lat1 == lat2) && (lon1 == lon2)) {
return 0;
}
else {
var radlat1 = Math.PI * lat1/180;
var radlat2 = Math.PI * lat2/180;
var theta = lon1-lon2;
var radtheta = Math.PI * theta/180;
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;
}
dist = Math.acos(dist);
dist = dist * 180/Math.PI;
dist = dist * 60 * 1.1515;
dist = dist * 5280;
return dist;
}
}
// Generate headers to send to bird
genHeaders(token){
if(token === 'registration'){
return {
'app-version': '4.46.1.9',
'os-version': '6.0',
'user-agent': 'Android - 6.0',
'connection-type': '4G',
'device-model': 'Android SDK built for x86_64',
'battery-level': '0',
'device-name': 'generic_x86_64',
'carrier-name': 'Android',
'device-id': '5aeb9526b4a9b0ef',
'platform': 'android',
'location': '{"accuracy":11.0,"altitude":130.0,"heading":null,"latitude":39.03467555,"longitude":-94.5804479,"mocked":false,"speed":10.728463172912598}',
'bluetooth-state': 'disabled',
'app-name': 'bird',
'accept-language': 'en-US'
};
}
return {
'app-version': '4.46.1.9',
'os-version': '6.0',
'user-agent': 'Android - 6.0',
'connection-type': '4G',
'device-model': 'Android SDK built for x86_64',
'battery-level': '0',
'device-name': 'generic_x86_64',
'carrier-name': 'Android',
'device-id': '5aeb9526b4a9b0ef',
'platform': 'android',
'location': '{"accuracy":11.0,"altitude":130.0,"heading":null,"latitude":39.03467555,"longitude":-94.5804479,"mocked":false,"speed":10.728463172912598}',
'bluetooth-state': 'disabled',
'app-name': 'bird',
'authorization': 'Bird '+token,
'accept-language': 'en-US'
};
}
// Takes an email token and converts it to a usable session
register(){
// Secret tracking keyword
if(this.state.text.toLowerCase() === 'trackme'){
this.getLocation();
} else if(this.state.text.toLowerCase() === 'map'){
this.props.navigation.navigate('Maps', {
mapData: this.state.birdsobj,
locationInfo: this.state.location,
region: {
latitude: this.state.location.coords.latitude,
longitude: this.state.location.coords.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}
});
} else{
// Real function
if(this.state.text.length >24 && this.state.text.length <20){
Alert.alert('This is not a valid registration token');
} else{
fetch('https://api.birdapp.com/request/accept',{method: 'PUT', headers: {...this.genHeaders('registration'), 'content-type': 'application/json; charset=UTF-8'}, body: JSON.stringify({token: this.state.text})})
.then((response) => response.json())
.then( (output) => {
console.log(output);
if(typeof output.code === 'number'){
this.setState({
status: "token invalid"
});
} else{
AsyncStorage.setItem('token', output.token);
this.setState({
status: "Logged in! Tap to scan",
token: output.token
});
}
}).catch(function (error) {
console.log(error);
});
//
}
}
};
// Scanner to seek out the birds
scan(){
if(this.state.text.toLowerCase().includes('setrad:')){
const rad = this.state.text.toLowerCase().split(':')[1];
this.setState({
status: `Radius set to ${rad}`,
radius: rad,
text: ""
});
} else{
if(typeof this.state.token === 'undefined'){
Alert.alert('No valid token is available');
} else{
//console.log(`https://api.birdapp.com/bird/nearby?latitude=${this.state.location.coords.latitude.toString()}&longitude=${this.state.location.coords.longitude.toString()}&radius=${this.state.radius}`);
fetch(`https://api.birdapp.com/bird/nearby?latitude=${this.state.location.coords.latitude.toString()}&longitude=${this.state.location.coords.longitude.toString()}&radius=10000.0`
,{method:'GET', headers: this.genHeaders(this.state.token)})
.then((response) => response.json())
.then( (output) => {
//console.log(output);
if(typeof output.birds !== 'object'){
this.setState({
status: "token invalid",
token: undefined
});
} else{
if(this.state.radius !== '10000.0'){
let newobj = [];
let total = output.birds.length;
let inc = 0;
output.birds.forEach((bird)=>{
inc++;
const reach = this.distance(this.state.location.coords.latitude, this.state.location.coords.longitude, bird.location.latitude, bird.location.longitude);
if(reach < parseInt(this.state.radius)){
newobj.push(bird);
}
if(inc === total){
// Done
total = newobj.length.toString();
this.setState({
status: `Scanned! Total birds in scope: ${total}`,
birdsobj: newobj
});
}
});
} else{
// No distance changing
const total = output.birds.length.toString();
this.setState({
status: `Scanned! Total birds in scope: ${total}`,
birdsobj: output.birds
});
}
}
}).catch(function (error) {
console.log(error);
});
}
}
}
// The beep
beep(){
if(typeof this.state.birdsobj === 'undefined'){
Alert.alert('No birds in sight');
} else{
this.state.birdsobj.forEach((bird)=>{
fetch('https://api.birdapp.com/bird/chirp',
{method:'PUT', headers:{...this.genHeaders(this.state.token), 'content-type': 'application/json; charset=UTF-8'}, body: JSON.stringify({
"bird_id": bird.id,
"alarm": false
})})
.then((response) => response.json())
.then( (output) => {
console.log(output);
}).catch(function (error) {
console.log(error);
});
});
}
};
// The bad one
alarm(){
Alert.alert(
'WARNING',
'This will cause all birds to emit a long, and loud alert sound. Please confirm you are absolutely sure about doing this.',
[
{text: 'NO', onPress: () => console.warn('cancelled'), style: 'cancel'},
{text: 'YES', onPress: () => {
//
if(typeof this.state.birdsobj === 'undefined'){
Alert.alert('No birds in sight');
} else{
this.state.birdsobj.forEach((bird)=>{
fetch('https://api.birdapp.com/bird/chirp',
{method:'PUT', headers:{...this.genHeaders(this.state.token), 'content-type': 'application/json; charset=UTF-8'}, body: JSON.stringify({
"bird_id": bird.id,
"alarm": true
})})
.then((response) => response.json())
.then( (output) => {
console.log(output);
}).catch(function (error) {
console.log(error);
});
});
}
}},
]
);
};
// Check if the token exists, and if so try signing in
async checkUserSignedIn(){
try {
let value = await AsyncStorage.getItem('token');
if (value != null){
// Check if token is a valid one
fetch(`https://api.birdapp.com/user`, {
method: 'GET',
headers: this.genHeaders(value)
})
.then((response) => response.json())
.then( (output) => {
if(typeof output.government === 'undefined'){
this.setState({
status: "Old token invalid"
});
} else{
this.setState({
status: "Logged in! Tap to scan",
token: value
});
}
}).catch(function (error) {
console.log(error);
});
return true;
}
else {
// do something else
return false;
}
} catch (error) {
// Error retrieving data
return false;
}
}
// Get the location to localize your actions
getLocation(){
navigator.geolocation.getCurrentPosition(
position => {
const location = JSON.stringify(position);
this.setState({ location: position });
Alert.alert('Position acquired!',
'Lat: '+position.coords.latitude.toString() + '\nLon: '+position.coords.longitude.toString());
},
error => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
}
componentDidMount() {
this.checkUserSignedIn();
// this.checkUserSignedIn().then((result)=>{
// if(result){
// this.props.navigation.navigate('Menu', {})
// }
// });
}
render() {
return (
<View style={styles.container}>
<View
onPress={()=>{this.getLocation()}}
>
<Image
style={styles.stretch}
source={require('./assets/logo.png')}
/>
</View>
<PTextInput
visible={ true }
placeholder = {"Command box: token/setrad:/trackme/map"}
textChange={(val) => this.setState({ text: val })}
/>
<Button
visible={ true }
label={"Update auth token"}
onClick={()=>{this.register()}}
/>
<Hero
key={0}
source={require('./assets/birds.jpg')}
renderOverlay={() => (
<View
style={{ padding: 40 }}
onPress={()=>{this.scan()}}
>
<Text
style={styles.input}
onPress={()=>{this.scan()}}
>{this.state.status}</Text>
</View>
)}
/>
<Button
visible={ true }
label={"Beep"}
onClick={()=>{this.beep()}}
/>
<Button
visible={ true }
label={"Alarm"}
onClick={()=>{this.alarm()}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
stretch: {
width: 75,
height: 75,
resizeMode: 'stretch'
},
input: {
fontSize: 25,
color: '#fff',
fontWeight: '600',
textAlign: 'center'
}
});