Skip to content

Commit

Permalink
feat: Store history data each hour (#109)
Browse files Browse the repository at this point in the history
* Update .gitignore

* Implement translation package & translate ErrorScreen

* Finish translations setup

* Minor lint fixes

* Possible dark video background issue fix

* Update App/localization/languages/en.json

Co-Authored-By: lucienbl <[email protected]>

* Update .gitignore

* Remove unused string

* Add history manager

* Minor lint fixes

* Store lat & lng in history

* Store coords with the history

* Expo version bump to 33.0.0

* refactor: Use eslint instead of semistandard (#72)

* Add eslint

* Run eslint on files

* Update contributing guide

* Update README

* Typo

* chore: Use correct GPLv3 header (#77)

* chore: Update README.md

* Spanish translation (#79)

* Spanish translation

* correction

* improvement spanish translation

* fix: Add missing translations (#81)

* Add spanish

* Add missing translations

* feat: Spanish Translations added (#83)

* Spanish translation

* correction

* improvement spanish translation

* missing spanish translations added

* chore: Update README.md with translations (#84)

* Update README.md

* Update README.md

* feat: Add button to change language (#85)

* cherry-pick

* Add button on picker

* Add button to change language

* fix: removes undefined style (#87)

* chore: Update README.md (#88)

* chore: Update axios (#90)

* chore(deps-dev): Bump jest from 24.5.0 to 24.8.0 (#91)

Bumps [jest](https://github.com/facebook/jest) from 24.5.0 to 24.8.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](jestjs/jest@v24.5.0...v24.8.0)

* chore(deps): Bump sentry-expo from 1.11.2 to 1.12.0 (#92)

Bumps sentry-expo from 1.11.2 to 1.12.0.

* chore(deps-dev): Bump eslint-plugin-import from 2.17.2 to 2.17.3 (#95)

Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.17.2 to 2.17.3.
- [Release notes](https://github.com/benmosher/eslint-plugin-import/releases)
- [Changelog](https://github.com/benmosher/eslint-plugin-import/blob/master/CHANGELOG.md)
- [Commits](import-js/eslint-plugin-import@v2.17.2...v2.17.3)

* chore(deps): Bump truncate from 2.0.1 to 2.1.0 (#94)

Bumps [truncate](https://github.com/FGRibreau/node-truncate) from 2.0.1 to 2.1.0.
- [Release notes](https://github.com/FGRibreau/node-truncate/releases)
- [Changelog](https://github.com/FGRibreau/node-truncate/blob/master/CHANGELOG.md)
- [Commits](FGRibreau/node-truncate@v2.0.1...v2.1.0)

* Expo version bump to 33.0.0

* Minor type changes

* Migrate expo packages

* Minor fixes

* Update Loading.js

* Remove unused package import

* ESLint fixes

* Import TaskManager

* Remove TS

* Auto increment SQL rows

* Remove debug console.log

* Factorize apiCall

* Test getData

* Revert "Am feature history"
  • Loading branch information
lucienbl authored and amaury1093 committed Jul 1, 2019
1 parent 8f3043b commit 079ab7c
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 25 deletions.
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
};

0 comments on commit 079ab7c

Please sign in to comment.