-
-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
169 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,19 @@ | ||
// Copyright (c) 2018-2019, Amaury Martiny | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
import React, { Component } from 'react'; | ||
import { inject, observer } from 'mobx-react'; | ||
import { Location, Permissions } from 'expo'; | ||
import React, {Component} from 'react'; | ||
import {inject, observer} from 'mobx-react'; | ||
import {Location, Permissions, TaskManager} from 'expo'; | ||
import retry from 'async-retry'; | ||
import { StyleSheet, Text } from 'react-native'; | ||
import {StyleSheet, Text} from 'react-native'; | ||
|
||
import { Background } from './Background'; | ||
import {Background} from './Background'; | ||
import * as dataSources from '../../utils/dataSources'; | ||
import * as theme from '../../utils/theme'; | ||
import {i18n} from '../../localization'; | ||
import {AqiHistoryManager} from "../../managers"; | ||
|
||
const TASK_STORE_AQI_HISTORY = 'store-aqi-history'; | ||
|
||
@inject('stores') | ||
@observer | ||
|
@@ -21,8 +24,9 @@ export class Loading extends Component { | |
|
||
longWaitingTimeout = null; // The variable returned by setTimeout for longWaiting | ||
|
||
componentDidMount () { | ||
this.fetchData(); | ||
async componentDidMount () { | ||
await this.fetchData(); | ||
await this._startRecordingAqiHistory(); | ||
} | ||
|
||
componentWillUnmount () { | ||
|
@@ -31,6 +35,37 @@ export class Loading extends Component { | |
} | ||
} | ||
|
||
_startRecordingAqiHistory = async () => { | ||
await Location.startLocationUpdatesAsync(TASK_STORE_AQI_HISTORY, { | ||
accuracy: Location.Accuracy.BestForNavigation, | ||
timeInterval: AqiHistoryManager.SAVE_DATA_INTERVAL, | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
lucienbl
Author
Contributor
|
||
distanceInterval: 0, | ||
}); | ||
}; | ||
|
||
_apiCall = async (currentPosition) => { | ||
|
||
// We currently have 2 sources, aqicn, and windWaqi | ||
// We put them in an array | ||
const sources = [dataSources.aqicn, dataSources.windWaqi]; | ||
|
||
return retry( | ||
async (_, attempt) => { | ||
// Attempt starts at 1 | ||
console.log( | ||
`<Loading> - fetchData - Attempt #${attempt}: ${ | ||
sources[(attempt - 1) % 2].name | ||
}` | ||
); | ||
const result = await sources[(attempt - 1) % 2](currentPosition); | ||
console.log('<Loading> - fetchData - Got result', result); | ||
|
||
return result; | ||
}, | ||
{retries: 3} // 2 attempts per source | ||
); | ||
}; | ||
|
||
async fetchData () { | ||
const { stores } = this.props; | ||
const { location } = stores; | ||
|
@@ -70,34 +105,14 @@ export class Loading extends Component { | |
location.setGps(coords); | ||
} | ||
|
||
// We currently have 2 sources, aqicn, and windWaqi | ||
// We put them in an array | ||
const sources = [dataSources.aqicn, dataSources.windWaqi]; | ||
|
||
// Set a 2s timer that will set `longWaiting` to true. Used to show an | ||
// additional "cough" message on the loading screen | ||
this.longWaitingTimeout = setTimeout( | ||
() => this.setState({ longWaiting: true }), | ||
2000 | ||
); | ||
|
||
const api = await retry( | ||
async (_, attempt) => { | ||
// Attempt starts at 1 | ||
console.log( | ||
`<Loading> - fetchData - Attempt #${attempt}: ${ | ||
sources[(attempt - 1) % 2].name | ||
}` | ||
); | ||
const result = await sources[(attempt - 1) % 2](currentPosition); | ||
console.log('<Loading> - fetchData - Got result', result); | ||
|
||
return result; | ||
}, | ||
{ retries: 3 } // 2 attemps per source | ||
); | ||
|
||
stores.setApi(api); | ||
stores.setApi(await this._apiCall(currentPosition)); | ||
} catch (error) { | ||
console.log('<Loading> - fetchData - Error', error); | ||
stores.setError(error.message); | ||
|
@@ -145,6 +160,41 @@ export class Loading extends Component { | |
}; | ||
} | ||
|
||
TaskManager.defineTask(TASK_STORE_AQI_HISTORY, async ({ data, error }) => { | ||
if (error) { | ||
console.log('<Loading> - TaskManager - defineTask - Error', error.message); | ||
return; | ||
} | ||
if (data) { | ||
const { locations } = data; | ||
const { coords } = locations[0]; | ||
|
||
// We currently have 2 sources, aqicn, and windWaqi | ||
// We put them in an array | ||
const sources = [dataSources.aqicn, dataSources.windWaqi]; | ||
|
||
const api = await retry( | ||
async (_, attempt) => { | ||
// Attempt starts at 1 | ||
console.log( | ||
`<Loading> - fetchData - Attempt #${attempt}: ${ | ||
sources[(attempt - 1) % 2].name | ||
}` | ||
); | ||
const result = await sources[(attempt - 1) % 2](coords); | ||
console.log('<Loading> - fetchData - Got result', result); | ||
|
||
return result; | ||
}, | ||
{retries: 3} // 2 attempts per source | ||
); | ||
|
||
if (await AqiHistoryManager.isSaveNeeded()) { | ||
await AqiHistoryManager.saveData(api.city.name, api.rawPm25); | ||
} | ||
} | ||
}); | ||
|
||
const styles = StyleSheet.create({ | ||
dots: { | ||
color: theme.primaryColor | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { SQLite } from 'expo'; | ||
|
||
export const SAVE_DATA_INTERVAL = 3600000; // 1 hour | ||
const DB_AQI_HISTORY = "aqi-history"; | ||
|
||
export const initDb = () => { | ||
return SQLite.openDatabase(DB_AQI_HISTORY, '1.0', 'Aqi History', 5*1024*1024); | ||
}; | ||
|
||
export const init = async () => { | ||
const db = await initDb(); | ||
|
||
await db.transaction((tx) => { | ||
tx.executeSql( | ||
"create table if not exists history(id integer not null, location varchar(255) not null, rawPm25 decimal not null, creation_time timestamp not null, primary key (id))", | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
lucienbl
Author
Contributor
|
||
[], | ||
() => {}, | ||
(transaction, error) => console.log("DB init error", error) | ||
); | ||
}); | ||
|
||
return db; | ||
}; | ||
|
||
export const isSaveNeeded = async () => { | ||
const db = await init(); | ||
|
||
const promise = new Promise((resolve, reject) => { | ||
db.readTransaction((tx) => { | ||
tx.executeSql( | ||
"select * from history order by id desc limit 1", | ||
[], | ||
(transaction, resultSet) => { | ||
if (resultSet.rows.length === 0) { | ||
resolve(true); | ||
} else if ((resultSet.rows.item(0).creation_time + SAVE_DATA_INTERVAL) < Date.now()) { | ||
resolve(true); | ||
} else { | ||
resolve(false); | ||
} | ||
}, | ||
(transaction, error) => reject(error) | ||
); | ||
}); | ||
}); | ||
|
||
return promise; | ||
}; | ||
|
||
export const saveData = async (location, rawPm25) => { | ||
const db = await init(); | ||
|
||
db.transaction((tx) => { | ||
tx.executeSql( | ||
"insert into history (id, location, rawPm25, creation_time) values (?, ?, ?, ?)", | ||
[Date.now(), location, rawPm25, Date.now()], | ||
() => {}, | ||
((transaction, error) => console.log("DB insert error", error)) | ||
); | ||
}); | ||
}; | ||
|
||
export const getData = async (limit) => { | ||
const db = await init(); | ||
|
||
const promise = new Promise((resolve, reject) => { | ||
db.readTransaction((tx) => { | ||
tx.executeSql( | ||
"select * from history order by creation_time desc limit " + limit, | ||
[], | ||
((transaction, resultSet) => { | ||
let data = []; | ||
|
||
for (let i = 0; i < resultSet.rows.length; i++) { | ||
data.push(resultSet.rows.item(i)); | ||
} | ||
|
||
resolve(data); | ||
}), | ||
((transaction, error) => reject(error)) | ||
); | ||
}); | ||
}); | ||
|
||
return promise; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import * as AqiHistoryManager from './AqiHistoryManager'; | ||
|
||
export { | ||
AqiHistoryManager | ||
} |
This is android only. Do you know how often iOS fetches location? Permanently?