Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(history): store data each hour #109

Merged
merged 51 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
c5072bc
Update .gitignore
lucienbl Apr 17, 2019
3b805f0
Implement translation package & translate ErrorScreen
lucienbl Apr 17, 2019
0f8f707
Finish translations setup
lucienbl Apr 17, 2019
8bb12ec
Minor lint fixes
lucienbl Apr 17, 2019
574268f
Possible dark video background issue fix
lucienbl Apr 17, 2019
917b767
Update App/localization/languages/en.json
amaury1093 Apr 17, 2019
389bffd
Update .gitignore
lucienbl Apr 17, 2019
cacc81f
Remove unused string
lucienbl Apr 17, 2019
c538eba
Merge pull request #1 from lucienbl/video-patch
lucienbl Apr 17, 2019
c1d746f
Merge pull request #2 from amaurymartiny/master
lucienbl Apr 17, 2019
0ab3cb9
Add history manager
lucienbl Apr 18, 2019
8b3502c
Minor lint fixes
lucienbl Apr 18, 2019
e875578
Store lat & lng in history
lucienbl Apr 23, 2019
319d2a2
Store coords with the history
lucienbl Apr 23, 2019
154eda6
Merge pull request #3 from amaurymartiny/master
lucienbl Jun 19, 2019
b5240e1
Expo version bump to 33.0.0
lucienbl Jun 19, 2019
98c7e4b
refactor: Use eslint instead of semistandard (#72)
amaury1093 Apr 17, 2019
7b7f617
chore: Use correct GPLv3 header (#77)
amaury1093 Apr 19, 2019
c96e27e
chore: Update README.md
amaury1093 Apr 23, 2019
c8ae8aa
Spanish translation (#79)
OlgaMorales Apr 25, 2019
6dbd5bd
fix: Add missing translations (#81)
amaury1093 Apr 25, 2019
0de36b3
feat: Spanish Translations added (#83)
OlgaMorales Apr 26, 2019
afbf2ff
chore: Update README.md with translations (#84)
amaury1093 Apr 26, 2019
f014d8d
feat: Add button to change language (#85)
amaury1093 Apr 26, 2019
a152cf6
fix: removes undefined style (#87)
pkhodaveissi May 2, 2019
601d5a9
chore: Update README.md (#88)
amaury1093 May 17, 2019
090fdc5
chore: Update axios (#90)
amaury1093 Jun 3, 2019
eb98f8c
chore(deps-dev): Bump jest from 24.5.0 to 24.8.0 (#91)
dependabot-preview[bot] Jun 3, 2019
155dcee
chore(deps): Bump sentry-expo from 1.11.2 to 1.12.0 (#92)
dependabot-preview[bot] Jun 3, 2019
8ac811b
chore(deps-dev): Bump eslint-plugin-import from 2.17.2 to 2.17.3 (#95)
dependabot-preview[bot] Jun 3, 2019
ebf944a
chore(deps): Bump truncate from 2.0.1 to 2.1.0 (#94)
dependabot-preview[bot] Jun 3, 2019
3b44265
Expo version bump to 33.0.0
lucienbl Jun 19, 2019
0d0683e
Minor type changes
lucienbl Jun 19, 2019
cf34284
Migrate expo packages
lucienbl Jun 19, 2019
bced5ec
Merge branch 'lb-expo-upgrade' into feature-history
lucienbl Jun 19, 2019
aa65935
Minor fixes
lucienbl Jun 19, 2019
3a93eab
Update Loading.js
lucienbl Jun 19, 2019
99a190c
Remove unused package import
lucienbl Jun 19, 2019
f7798f9
ESLint fixes
lucienbl Jun 19, 2019
f417ff2
Merge pull request #4 from lucienbl/lb-expo-upgrade
lucienbl Jun 23, 2019
2b6378b
Merge pull request #5 from lucienbl/master
lucienbl Jun 23, 2019
cbe6233
Import TaskManager
lucienbl Jun 23, 2019
d046e27
Merge branch 'master' into feature-history
lucienbl Jun 23, 2019
48e27ec
Remove TS
lucienbl Jun 29, 2019
28020c6
Auto increment SQL rows
lucienbl Jun 29, 2019
2e5032d
Remove debug console.log
lucienbl Jun 29, 2019
dd34b97
Factorize apiCall
amaury1093 Jun 30, 2019
44a04b3
Test getData
amaury1093 Jun 30, 2019
8f5abde
Merge pull request #6 from amaurymartiny/am-feature-history
lucienbl Jun 30, 2019
71ebfa6
Revert "Am feature history"
lucienbl Jun 30, 2019
dd2a355
Merge pull request #7 from lucienbl/revert-6-am-feature-history
lucienbl Jun 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 74 additions & 25 deletions App/Screens/Loading/Loading.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import * as Permissions from 'expo-permissions';
import * as TaskManager from 'expo-task-manager';
import * as Location from 'expo-location';
import retry from 'async-retry';
import { StyleSheet, Text } from 'react-native';

import { Background } from './Background';
import { i18n } from '../../localization';
import * as dataSources from '../../utils/dataSources';
import * as theme from '../../utils/theme';
import { i18n } from '../../localization';
import { AqiHistoryDb } from '../../managers';

const TASK_STORE_AQI_HISTORY = 'store-aqi-history';

@inject('stores')
@observer
Expand All @@ -35,8 +38,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 () {
Expand All @@ -45,6 +49,36 @@ export class Loading extends Component {
}
}

_startRecordingAqiHistory = async () => {
await Location.startLocationUpdatesAsync(TASK_STORE_AQI_HISTORY, {
accuracy: Location.Accuracy.BestForNavigation,
timeInterval: AqiHistoryDb.SAVE_DATA_INTERVAL,
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;
Expand Down Expand Up @@ -84,34 +118,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);
Expand Down Expand Up @@ -159,6 +173,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 AqiHistoryDb.isSaveNeeded()) {
await AqiHistoryDb.saveData(api.city.name, api.rawPm25, coords);
}
}
});

const styles = StyleSheet.create({
dots: {
color: theme.primaryColor
Expand Down
43 changes: 43 additions & 0 deletions App/managers/AqiHistory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class AqiHistory {
_id;
_location;
_lat;
_lng;
_rawPm25;
_creationTime;

constructor ({ id, location, lat, lng, rawPm25, creationTime }) {
this._id = id;
this._location = location;
this._lat = lat;
this._lng = lng;
this._rawPm25 = rawPm25;
this._creationTime = creationTime;
}

get id () {
return this._id;
}

get location () {
return this._location;
}

get lat () {
return this._lat;
}

get lng () {
return this._lng;
}

get rawPm25 () {
return this._rawPm25;
}

get creationTime () {
return this._creationTime;
}
}

export default AqiHistory;
88 changes: 88 additions & 0 deletions App/managers/AqiHistoryDb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { SQLite } from 'expo-sqlite';
import AqiHistory from './AqiHistory';

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 primary key autoincrement, location varchar(255) not null, lat numeric not null, lng numeric not null, rawPm25 decimal not null, creationTime timestamp not null)',
[],
() => {},
(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).creationTime + SAVE_DATA_INTERVAL) < Date.now()) {
resolve(true);
} else {
resolve(false);
}
},
(transaction, error) => reject(error)
);
});
});

return promise;
};

export const saveData = async (location, rawPm25, { latitude, longitude }) => {
const db = await init();

db.transaction((tx) => {
tx.executeSql(
'insert into history (location, lat, lng, rawPm25, creationTime) values (?, ?, ?, ?, ?)',
[location, latitude, longitude, 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 creationTime desc limit ' + limit,
[],
(transaction, resultSet) => {
let data = [];

for (let i = 0; i < resultSet.rows.length; i++) {
const result = new AqiHistory(resultSet.rows.item(i));
data.push(result);
}

resolve(data);
},
(transaction, error) => reject(error)
);
});
});

return promise;
};
5 changes: 5 additions & 0 deletions App/managers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as AqiHistoryDb from './AqiHistoryDb';

export {
AqiHistoryDb
};