├── alarm.wav ├── flyer.pdf ├── assets ├── images │ ├── icon.png │ ├── splash.png │ ├── robot-dev.png │ ├── stretch_1.PNG │ ├── stretch_2.PNG │ ├── stretch_3.PNG │ ├── stretch_5.PNG │ ├── stretch_6.PNG │ ├── stretch_7.PNG │ ├── stretch_9.PNG │ ├── robot-prod.png │ ├── stretch_10.PNG │ ├── stretch_11.PNG │ ├── stretch_12.PNG │ ├── stretch_13.PNG │ └── stretch_14.PNG └── fonts │ └── SpaceMono-Regular.ttf ├── babel.config.js ├── .gitignore ├── components ├── StyledText.js ├── __tests__ │ ├── StyledText-test.js │ └── __snapshots__ │ │ └── StyledText-test.js.snap ├── TabBarIcon.js └── Button.js ├── constants ├── Layout.js └── Colors.js ├── .expo-shared └── assets.json ├── screens ├── SettingsScreen.js ├── LinksScreen.js ├── ArrivedScreen.js ├── HomeScreen.js ├── BreakScreen.js ├── HelpScreen.js └── QuizScreen.js ├── navigation ├── AppNavigator.js ├── AppNavigator.web.js └── MainTabNavigator.js ├── __tests__ ├── __snapshots__ │ └── App-test.js.snap └── App-test.js ├── README.md ├── app.json ├── package.json └── App.js /alarm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/alarm.wav -------------------------------------------------------------------------------- /flyer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/flyer.pdf -------------------------------------------------------------------------------- /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/splash.png -------------------------------------------------------------------------------- /assets/images/robot-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/robot-dev.png -------------------------------------------------------------------------------- /assets/images/stretch_1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_1.PNG -------------------------------------------------------------------------------- /assets/images/stretch_2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_2.PNG -------------------------------------------------------------------------------- /assets/images/stretch_3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_3.PNG -------------------------------------------------------------------------------- /assets/images/stretch_5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_5.PNG -------------------------------------------------------------------------------- /assets/images/stretch_6.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_6.PNG -------------------------------------------------------------------------------- /assets/images/stretch_7.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_7.PNG -------------------------------------------------------------------------------- /assets/images/stretch_9.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_9.PNG -------------------------------------------------------------------------------- /assets/images/robot-prod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/robot-prod.png -------------------------------------------------------------------------------- /assets/images/stretch_10.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_10.PNG -------------------------------------------------------------------------------- /assets/images/stretch_11.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_11.PNG -------------------------------------------------------------------------------- /assets/images/stretch_12.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_12.PNG -------------------------------------------------------------------------------- /assets/images/stretch_13.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_13.PNG -------------------------------------------------------------------------------- /assets/images/stretch_14.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/images/stretch_14.PNG -------------------------------------------------------------------------------- /assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CompSciLauren/drive-awake/master/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | web-report/ 12 | 13 | # macOS 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /components/StyledText.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Text } from 'react-native'; 3 | 4 | export function MonoText(props) { 5 | return ( 6 | 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /constants/Layout.js: -------------------------------------------------------------------------------- 1 | import { Dimensions } from 'react-native'; 2 | 3 | const width = Dimensions.get('window').width; 4 | const height = Dimensions.get('window').height; 5 | 6 | export default { 7 | window: { 8 | width, 9 | height, 10 | }, 11 | isSmallDevice: width < 375, 12 | }; 13 | -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "0cae4d70c6df3e5e96ee8b5c442b59d55c8ab8deb466992ab9abc523822f2a1b": true, 3 | "e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true, 4 | "af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true, 5 | "e7fc0741cc6562975a990e3d9ef820571588dab20aba97032df9f00caa9cd57a": true 6 | } -------------------------------------------------------------------------------- /components/__tests__/StyledText-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | 4 | import { MonoText } from '../StyledText'; 5 | 6 | it(`renders correctly`, () => { 7 | const tree = renderer.create(Snapshot test!).toJSON(); 8 | 9 | expect(tree).toMatchSnapshot(); 10 | }); 11 | -------------------------------------------------------------------------------- /components/__tests__/__snapshots__/StyledText-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders correctly 1`] = ` 4 | 14 | Snapshot test! 15 | 16 | `; 17 | -------------------------------------------------------------------------------- /constants/Colors.js: -------------------------------------------------------------------------------- 1 | const tintColor = '#2f95dc'; 2 | 3 | export default { 4 | tintColor, 5 | tabIconDefault: '#ccc', 6 | tabIconSelected: tintColor, 7 | tabBar: '#fefefe', 8 | errorBackground: 'red', 9 | errorText: '#fff', 10 | warningBackground: '#EAEB5E', 11 | warningText: '#666804', 12 | noticeBackground: tintColor, 13 | noticeText: '#fff', 14 | }; 15 | -------------------------------------------------------------------------------- /components/TabBarIcon.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Ionicons } from '@expo/vector-icons'; 3 | 4 | import Colors from '../constants/Colors'; 5 | 6 | export default function TabBarIcon(props) { 7 | return ( 8 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /screens/SettingsScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ExpoConfigView } from '@expo/samples'; 3 | 4 | export default function SettingsScreen() { 5 | /** 6 | * Go ahead and delete ExpoConfigView and replace it with your content; 7 | * we just wanted to give you a quick view of your config. 8 | */ 9 | return ; 10 | } 11 | 12 | SettingsScreen.navigationOptions = { 13 | header: null, 14 | }; 15 | -------------------------------------------------------------------------------- /navigation/AppNavigator.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createAppContainer, createSwitchNavigator } from 'react-navigation'; 3 | 4 | import MainTabNavigator from './MainTabNavigator'; 5 | 6 | export default createAppContainer( 7 | createSwitchNavigator({ 8 | // You could add another route here for authentication. 9 | // Read more at https://reactnavigation.org/docs/en/auth-flow.html 10 | Main: MainTabNavigator, 11 | }) 12 | ); 13 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/App-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`App renders the loading screen 1`] = ` 4 | 9 | `; 10 | 11 | exports[`App renders the root without loading screen 1`] = ` 12 | 20 | 21 | 22 | `; 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ASTIR 2 | 3 | A mobile app and hardware component that work together to help detect and prevent drowsy driving. 4 | 5 | ## Devpost Link 6 | 7 | https://devpost.com/software/astir 8 | 9 | ## Flyer 10 | 11 | [Flyer](https://github.com/CompSciLauren/drive-awake/blob/master/flyer.pdf) 12 | 13 | ## Related GitHub Repos 14 | 15 | https://github.com/SebastianMcMillan/astir-sensors 16 | 17 | https://github.com/ellyrichardson/HackKU-2020_Backend-API 18 | 19 | https://github.com/ellyrichardson/HackKU-2020_Drowsy-Detection 20 | -------------------------------------------------------------------------------- /navigation/AppNavigator.web.js: -------------------------------------------------------------------------------- 1 | import { createBrowserApp } from '@react-navigation/web'; 2 | import { createSwitchNavigator } from 'react-navigation'; 3 | 4 | import MainTabNavigator from './MainTabNavigator'; 5 | 6 | const switchNavigator = createSwitchNavigator({ 7 | // You could add another route here for authentication. 8 | // Read more at https://reactnavigation.org/docs/en/auth-flow.html 9 | Main: MainTabNavigator, 10 | }); 11 | switchNavigator.path = ''; 12 | 13 | export default createBrowserApp(switchNavigator, { history: 'hash' }); 14 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "Tab Navigation Template", 4 | "slug": "drive-awake", 5 | "privacy": "public", 6 | "sdkVersion": "36.0.0", 7 | "platforms": ["ios", "android", "web"], 8 | "version": "1.0.0", 9 | "orientation": "portrait", 10 | "icon": "./assets/images/icon.png", 11 | "splash": { 12 | "image": "./assets/images/splash.png", 13 | "resizeMode": "contain", 14 | "backgroundColor": "#ffffff" 15 | }, 16 | "updates": { 17 | "fallbackToCacheTimeout": 0 18 | }, 19 | "assetBundlePatterns": ["**/*"], 20 | "ios": { 21 | "supportsTablet": true 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import NavigationTestUtils from 'react-navigation/NavigationTestUtils'; 3 | import renderer from 'react-test-renderer'; 4 | 5 | import App from '../App'; 6 | 7 | jest.mock('expo', () => ({ 8 | AppLoading: 'AppLoading', 9 | })); 10 | 11 | jest.mock('../navigation/AppNavigator', () => 'AppNavigator'); 12 | 13 | describe('App', () => { 14 | jest.useFakeTimers(); 15 | 16 | beforeEach(() => { 17 | NavigationTestUtils.resetInternalState(); 18 | }); 19 | 20 | it(`renders the loading screen`, () => { 21 | const tree = renderer.create().toJSON(); 22 | expect(tree).toMatchSnapshot(); 23 | }); 24 | 25 | it(`renders the root without loading screen`, () => { 26 | const tree = renderer.create().toJSON(); 27 | expect(tree).toMatchSnapshot(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /components/Button.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Platform, 4 | StyleSheet, 5 | Text, 6 | TouchableOpacity, 7 | View, 8 | } from 'react-native'; 9 | 10 | export function Button(props) { 11 | const { title } = props; 12 | return ( 13 | 14 | 15 | {title} 16 | 17 | 18 | ); 19 | } 20 | 21 | const styles = StyleSheet.create({ 22 | buttonContainer: { 23 | paddingHorizontal: 100, 24 | }, 25 | buttonButton: { 26 | width: 154, 27 | height: 72, 28 | backgroundColor: '#930101', 29 | borderRadius: 10, 30 | marginTop: 10, 31 | marginBottom: 25, 32 | justifyContent: 'center', 33 | alignItems: 'center', 34 | ...Platform.select({ 35 | ios: { 36 | shadowColor: 'black', 37 | shadowOffset: { width: 0, height: -3 }, 38 | shadowOpacity: 0.1, 39 | shadowRadius: 3, 40 | }, 41 | android: { 42 | elevation: 5, 43 | }, 44 | }), 45 | }, 46 | buttonText: { 47 | fontSize: 17, 48 | fontWeight: 'bold', 49 | color: 'white', 50 | paddingVertical: 10, 51 | }, 52 | }); 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject", 9 | "test": "jest --watchAll" 10 | }, 11 | "jest": { 12 | "preset": "jest-expo" 13 | }, 14 | "dependencies": { 15 | "@expo/samples": "~36.0.0", 16 | "@expo/vector-icons": "~10.0.0", 17 | "@react-navigation/web": "~1.0.0-alpha.9", 18 | "expo": "~36.0.0", 19 | "expo-asset": "~8.0.0", 20 | "expo-constants": "~8.0.0", 21 | "expo-font": "~8.0.0", 22 | "expo-web-browser": "~8.0.0", 23 | "react": "~16.9.0", 24 | "react-dom": "~16.9.0", 25 | "react-native": "https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz", 26 | "react-native-countdown-component": "^2.6.0", 27 | "react-native-geocoding": "^0.4.0", 28 | "react-native-geolocation-service": "^4.0.0", 29 | "react-native-gesture-handler": "~1.5.0", 30 | "react-native-play-sound": "^1.0.24", 31 | "react-native-reanimated": "~1.4.0", 32 | "react-native-screens": "2.0.0-alpha.12", 33 | "react-native-sound": "^0.11.0", 34 | "react-native-swipe-gestures": "^1.0.4", 35 | "react-native-web": "~0.11.7", 36 | "react-navigation": "~4.0.10", 37 | "react-navigation-stack": "~1.10.3", 38 | "react-navigation-tabs": "~2.6.2" 39 | }, 40 | "devDependencies": { 41 | "@babel/core": "^7.0.0", 42 | "babel-preset-expo": "~8.0.0", 43 | "jest-expo": "~36.0.1" 44 | }, 45 | "private": true 46 | } 47 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import { AppLoading } from 'expo'; 2 | import { Asset } from 'expo-asset'; 3 | import * as Font from 'expo-font'; 4 | import React, { useState } from 'react'; 5 | import { Platform, StatusBar, StyleSheet, View } from 'react-native'; 6 | import { Ionicons } from '@expo/vector-icons'; 7 | 8 | import AppNavigator from './navigation/AppNavigator'; 9 | 10 | export default function App(props) { 11 | const [isLoadingComplete, setLoadingComplete] = useState(false); 12 | 13 | if (!isLoadingComplete && !props.skipLoadingScreen) { 14 | return ( 15 | handleFinishLoading(setLoadingComplete)} 19 | /> 20 | ); 21 | } else { 22 | return ( 23 | 24 | {Platform.OS === 'ios' && } 25 | 26 | 27 | ); 28 | } 29 | } 30 | 31 | async function loadResourcesAsync() { 32 | await Promise.all([ 33 | Asset.loadAsync([ 34 | require('./assets/images/robot-dev.png'), 35 | require('./assets/images/robot-prod.png'), 36 | ]), 37 | Font.loadAsync({ 38 | // This is the font that we are using for our tab bar 39 | ...Ionicons.font, 40 | // We include SpaceMono because we use it in HomeScreen.js. Feel free to 41 | // remove this if you are not using it in your app 42 | 'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf'), 43 | }), 44 | ]); 45 | } 46 | 47 | function handleLoadingError(error) { 48 | // In this case, you might want to report the error to your error reporting 49 | // service, for example Sentry 50 | console.warn(error); 51 | } 52 | 53 | function handleFinishLoading(setLoadingComplete) { 54 | setLoadingComplete(true); 55 | } 56 | 57 | const styles = StyleSheet.create({ 58 | container: { 59 | flex: 1, 60 | backgroundColor: '#fff', 61 | }, 62 | }); 63 | -------------------------------------------------------------------------------- /screens/LinksScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TouchableOpacity, View, Text, Vibration } from 'react-native'; 3 | import { Button } from '../components/Button'; 4 | 5 | export default class LinksScreen extends React.Component { 6 | handleTurnDeviceOn = async () => { 7 | fetch('http://13.58.89.149:8000/endpoint/api/onoff/', { 8 | method: 'POST', 9 | headers: { 10 | Accept: 'application/json', 11 | 'Content-Type': 'application/json', 12 | }, 13 | body: JSON.stringify({ 14 | turnOnConnection: true, 15 | }), 16 | }); 17 | }; 18 | 19 | handleTurnDeviceOff = async () => { 20 | fetch('http://13.58.89.149:8000/endpoint/api/onoff/', { 21 | method: 'POST', 22 | headers: { 23 | Accept: 'application/json', 24 | 'Content-Type': 'application/json', 25 | }, 26 | body: JSON.stringify({ 27 | turnOnConnection: false, 28 | }), 29 | }); 30 | }; 31 | 32 | componentDidMount() { 33 | this.timer = setInterval(() => this.handleGetRequest(), 5000); 34 | } 35 | 36 | handleGetRequest = async () => { 37 | fetch('http://13.58.89.149:8000/endpoint/api/status/', { 38 | method: 'GET', 39 | //Request Type 40 | }) 41 | .then(response => response.json()) 42 | //If response is in json then in success 43 | .then(responseJson => { 44 | //Success 45 | if (responseJson[responseJson.length - 1].isDrowsy == true) { 46 | const DURATION = 5000; 47 | 48 | Vibration.vibrate(DURATION); 49 | alert('You are falling asleep. Pull over as soon as possible.'); 50 | } 51 | }) 52 | //If response is not in json then in error 53 | .catch(error => { 54 | //Error 55 | console.error(error); 56 | }); 57 | }; 58 | 59 | render() { 60 | return ( 61 | 62 | 63 |