395 lines
15 KiB
JavaScript
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'
|
|
}
|
|
}); |