Update to make sensorUI be the main source of notifications

This commit is contained in:
William Moore 2023-02-01 21:02:10 -06:00
parent 77763a4189
commit 2bdd988b0b
6 changed files with 1422 additions and 38 deletions

1372
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@
"@types/react": "^18.0.27", "@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10", "@types/react-dom": "^18.0.10",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"firebase": "^9.16.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",

View File

@ -72,7 +72,7 @@
} }
.header { .header {
background-color: #282c34; background-color: #146b37;
color: white; color: white;
text-align: center; text-align: center;
border: .01em solid black; border: .01em solid black;

View File

@ -1,10 +1,17 @@
import React from 'react'; import React, { useEffect } from 'react';
import './App.css'; import './App.css';
import Rainfall from './components/rainfall'; import Rainfall from './components/rainfall';
import Soil from './components/soil'; import Soil from './components/soil';
import TeaSense from './components/teasense'; import TeaSense from './components/teasense';
function App() { function App() {
useEffect(() => {
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
}
});
}, []);
return ( return (
<div className="App"> <div className="App">
<h1 className={'header'}>MooreForge Sensor Station</h1> <h1 className={'header'}>MooreForge Sensor Station</h1>

View File

@ -5,39 +5,26 @@ import { isBefore } from 'date-fns';
import './style.css'; import './style.css';
const Sensor = () => { const Sensor = () => {
const [temp, setTemp] = useState(); const [moisture, setMoisture] = useState();
const [cap, setCap] = useState();
async function pullTempFromBackend() { async function pullMoistureFromBackend() {
const response = await fetch(process.env.REACT_APP_SOIL_TEMP_DATA ?? ''); const response = await fetch(process.env.REACT_APP_SOIL_MOISTURE_DATA ?? '');
const data = await response.json(); const data = await response.json();
const result = data const result = data
.reduce((accum: any, datum: any) => ( ((accum && isBefore(new Date(accum?.timestamp), new Date(datum?.timestamp))) || !accum ) ? datum : accum )); .reduce((accum: any, datum: any) => ( ((accum && isBefore(new Date(accum?.timestamp), new Date(datum?.timestamp))) || !accum ) ? datum : accum ));
setTemp(result.value); setMoisture(result.value);
}
async function pullCapFromBackend() {
const response = await fetch(process.env.REACT_APP_SOIL_CAP_DATA ?? '');
const data = await response.json();
const result = data
.reduce((accum: any, datum: any) => ( ((accum && isBefore(new Date(accum?.timestamp), new Date(datum?.timestamp))) || !accum ) ? datum : accum ));
setCap(result.value);
} }
useEffect(() => { useEffect(() => {
setInterval(() => pullTempFromBackend(), 1000); setInterval(() => pullMoistureFromBackend(), 1000);
setInterval(() => pullCapFromBackend(), 1000);
}, []); }, []);
return ( return (
<div className={'gauge-body'}> <div className={'gauge-body'}>
<div className={'gauge-label'}>Soil</div> <div className={'gauge-label'}>Soil</div>
<div className={'gauge-label'}>Temperature (in C)</div> <div className={'gauge-label'}>Moisture</div>
<div>{temp}</div> <div>{moisture} V</div>
<div className={'gauge-label'}>Capacitance</div>
<div>{cap}</div>
</div> </div>
); );
}; };

View File

@ -3,6 +3,9 @@ import React, { useEffect, useState } from 'react';
import './style.css'; import './style.css';
const ALERT_THRESHOLD = parseInt(process.env.REACT_APP_TEASENSE_ALERT_THRESHOLD ?? '80.0');
const WARNING_THRESHOLD = parseInt(process.env.REACT_APP_TEASENSE_WARNING_THRESHOLD ?? '75.0');
const Sensor = () => { const Sensor = () => {
const [temp, setTemp] = useState(); const [temp, setTemp] = useState();
@ -11,31 +14,45 @@ const Sensor = () => {
const data = await response.json(); const data = await response.json();
const result = data const result = data
.reduce((accum: any, datum: any) => (((accum && isBefore(new Date(accum?.timestamp), new Date(datum?.timestamp))) || !accum) ? datum : accum)); .reduce((accum: any, datum: any) => (((accum && isBefore(new Date(accum?.timestamp), new Date(datum?.timestamp))) || !accum) ? datum : accum));
console.log(result);
setTemp(result.value); setTemp(result.value);
} }
function checkNotificationPromise() {
try {
Notification.requestPermission().then();
} catch (e) {
return false;
}
return true;
}
useEffect(() => { useEffect(() => {
setInterval(() => pullTempFromBackend(), 1000); setInterval(() => pullTempFromBackend(), 1000);
}, []); }, []);
useEffect(() => { useEffect(() => {
function handleNotification(title: string, notif: any) {
navigator.serviceWorker.ready.then((registration) => {
if (checkNotificationPromise()) {
registration.showNotification(title, notif);
} else {
registration.showNotification(title, notif);
}
});
}
if (temp) { if (temp) {
if (temp >= 82.2) { if (temp >= ALERT_THRESHOLD) {
Notification.requestPermission().then((result) => { handleNotification('TeaSense Alert', {
if (result === 'granted') { body: process.env.REACT_APP_TEASENSE_ALERT_MESSAGE,
new Notification('TeaSense Alert', { tag: 1,
body: '♨️',
}); });
} } else if (temp < ALERT_THRESHOLD && temp > WARNING_THRESHOLD) {
}); handleNotification('TeaSense Warning', {
} else if (temp >= 80.0) { body: process.env.REACT_APP_TEASENSE_WARNING_MESSAGE,
Notification.requestPermission().then((result) => { tag: 1,
if (result === 'granted') {
new Notification('TeaSense Warning', {
body: '🫖',
});
}
}); });
} }
} }