Compare commits
5 Commits
df7470f147
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| a1dc088a23 | |||
| d4a19060e8 | |||
| fe9f7e81e9 | |||
| 6e07c2be85 | |||
| 03db7575fd |
@@ -42,6 +42,8 @@ function Core() {
|
|||||||
label="Smart Home" margin="0 0 0 1em" />
|
label="Smart Home" margin="0 0 0 1em" />
|
||||||
<Button onClick={() => dispatch(setPlugin("maps"))} primary
|
<Button onClick={() => dispatch(setPlugin("maps"))} primary
|
||||||
label="Maps" margin="0 0 0 1em" />
|
label="Maps" margin="0 0 0 1em" />
|
||||||
|
<Button onClick={() => dispatch(setPlugin("marketplace"))} primary
|
||||||
|
label="Marketplace" margin="0 0 0 1em" />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>)
|
</Box>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from "react";
|
|||||||
|
|
||||||
function VoiceBars() {
|
function VoiceBars() {
|
||||||
return (
|
return (
|
||||||
<div className="waves" style={{transform: "rotate(180deg)", marginTop: "130px"}}>
|
<div className="waves" style={{transform: "rotate(180deg)", marginTop: "130px", transition: "1s"}}>
|
||||||
<svg width="100vw" fill="none" version="1.1"
|
<svg width="100vw" fill="none" version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
|
|||||||
@@ -9,18 +9,18 @@ import { TG_API, TG_USERID } from "../config";
|
|||||||
function sendNotification(close) {
|
function sendNotification(close) {
|
||||||
if (window.sendingAccidentAlert)
|
if (window.sendingAccidentAlert)
|
||||||
return;
|
return;
|
||||||
window.sending = true;
|
window.sendingAccidentAlert = true;
|
||||||
const bot = new Telegram(TG_API);
|
const bot = new Telegram(TG_API);
|
||||||
bot.sendMessage(TG_USERID, "User detected in an accident. Location has been attached below.");
|
bot.sendMessage(TG_USERID, "User detected in an accident. Location has been attached below.");
|
||||||
navigator.geolocation.getCurrentPosition(
|
navigator.geolocation.getCurrentPosition(
|
||||||
position => {
|
position => {
|
||||||
|
window.sendingAccidentAlert = false;
|
||||||
bot.sendLocation( TG_USERID,
|
bot.sendLocation( TG_USERID,
|
||||||
position.coords.latitude, position.coords.longitude);
|
position.coords.latitude, position.coords.longitude);
|
||||||
window.sendingAccidentAlert = false;
|
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
bot.sendMessage(TG_USERID, "Error retrieving location");
|
|
||||||
window.sendingAccidentAlert = false;
|
window.sendingAccidentAlert = false;
|
||||||
|
bot.sendMessage(TG_USERID, "Error retrieving location");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
setTimeout(close, 2000);
|
setTimeout(close, 2000);
|
||||||
|
|||||||
@@ -12,10 +12,13 @@ function GenericPageWithIcon(props) {
|
|||||||
direction="column"
|
direction="column"
|
||||||
alignContent="center"
|
alignContent="center"
|
||||||
height="95vh"
|
height="95vh"
|
||||||
|
style={{
|
||||||
|
padding: "0 3em",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{props.icon}
|
{props.icon}
|
||||||
<Heading>{props.title}</Heading>
|
<Heading>{props.title}</Heading>
|
||||||
<Text>{props.description}</Text>
|
<Text style={{ textAlign: "center" }}>{props.description}</Text>
|
||||||
<Button primary size="large" onClick={props.close}
|
<Button primary size="large" onClick={props.close}
|
||||||
label="Dismiss" margin="1.5em" />
|
label="Dismiss" margin="1.5em" />
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
67
src/plugins/Marketplace.js
Normal file
67
src/plugins/Marketplace.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { Box, Button, Card, CardBody, CardFooter, CardHeader, Heading } from "grommet";
|
||||||
|
import { InstallOption, Trash } from "grommet-icons";
|
||||||
|
|
||||||
|
|
||||||
|
function Marketplace(props) {
|
||||||
|
const plugins = [
|
||||||
|
{
|
||||||
|
name: "Maps",
|
||||||
|
description: "Google Maps is a mapping service. It offers satellite imagery, aerial photography, street maps, 360° interactive panoramic views of streets, real-time traffic conditions, and route planning for traveling.",
|
||||||
|
installed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Smart Home",
|
||||||
|
description: "Smart Home Plugin lets you integrate with various well known smart devices allowing you to stream video from various devices.",
|
||||||
|
installed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Spotify",
|
||||||
|
description: "With Spotify, you have access to a world of music. You can listen to artists and albums, or create your own playlist of your favourite songs.",
|
||||||
|
installed: false
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
align="center"
|
||||||
|
background="light-1"
|
||||||
|
width="100vw"
|
||||||
|
justify="center"
|
||||||
|
direction="column"
|
||||||
|
alignContent="center"
|
||||||
|
height="95vh"
|
||||||
|
>
|
||||||
|
<Box wrap="wrap" direction="row">
|
||||||
|
{
|
||||||
|
plugins.map(i =>
|
||||||
|
<Card key={i.name} style={{margin: "1em", width: "30%"}}>
|
||||||
|
<CardHeader pad="medium"><Heading>{i.name}</Heading></CardHeader>
|
||||||
|
<CardBody pad="medium">{i.description}</CardBody>
|
||||||
|
<CardFooter pad="medium" justify="center">
|
||||||
|
<Button
|
||||||
|
label={i.installed ? "Uninstall": "Install"}
|
||||||
|
icon={i.installed ?
|
||||||
|
<Trash color="status-error" /> :
|
||||||
|
<InstallOption color="status-ok" />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
<Button primary size="large" onClick={props.close}
|
||||||
|
label="Dismiss" margin="1.5em" />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Marketplace.propTypes = {
|
||||||
|
data: PropTypes.object,
|
||||||
|
close: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
Marketplace.pluginName = "Marketplace";
|
||||||
|
|
||||||
|
export default Marketplace;
|
||||||
@@ -3,16 +3,38 @@ import PropTypes from "prop-types";
|
|||||||
import GenericPageWithIcon from "./GenericPageWithIcon";
|
import GenericPageWithIcon from "./GenericPageWithIcon";
|
||||||
import { Sun } from "grommet-icons";
|
import { Sun } from "grommet-icons";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { CAR_API } from "../config";
|
|
||||||
|
import Telegram from "../utils/telegram";
|
||||||
|
import { CAR_API, TG_API, TG_USERID } from "../config";
|
||||||
|
|
||||||
|
function sendNotification(temp) {
|
||||||
|
if (window.sendingPetAlert)
|
||||||
|
return;
|
||||||
|
window.sendingPetAlert = true;
|
||||||
|
const bot = new Telegram(TG_API);
|
||||||
|
bot.sendMessage(TG_USERID, `The temperature in the car is ${temp}°C. Please check your child/pet.`);
|
||||||
|
window.sendingPetAlert = false;
|
||||||
|
}
|
||||||
|
|
||||||
function PetMode(props) {
|
function PetMode(props) {
|
||||||
const [ temp, setTemp ] = useState(null);
|
const [ temp, setTemp ] = useState(null);
|
||||||
|
const [ , setNotified ] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
axios.get(`${CAR_API}data/InsideTemperature`)
|
axios.get(`${CAR_API}data/InsideTemperature`)
|
||||||
.then(resp => setTemp(resp.data.value));
|
.then(resp => setTemp(resp.data.value));
|
||||||
const id = setInterval(
|
const id = setInterval(
|
||||||
() => axios.get(`${CAR_API}data/InsideTemperature`)
|
() => axios.get(`${CAR_API}data/InsideTemperature`)
|
||||||
.then(resp => setTemp(resp.data.value)),
|
.then(resp => {
|
||||||
|
setTemp(resp.data.value);
|
||||||
|
if (resp.data.value > 35 || resp.data.value < 5) {
|
||||||
|
setNotified(notified => {
|
||||||
|
if (notified)
|
||||||
|
return true;
|
||||||
|
sendNotification(resp.data.value);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, {useState, useEffect} from "react";
|
import React, {useState, useEffect} from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { Box, Button } from "grommet";
|
import { Box, Button } from "grommet";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
import { CAMERA_URL } from "../config";
|
import { CAMERA_URL, LIGHTS_URL } from "../config";
|
||||||
|
|
||||||
function SmartHome(props) {
|
function SmartHome(props) {
|
||||||
const [ idx, setIdx ] = useState(0);
|
const [ idx, setIdx ] = useState(0);
|
||||||
@@ -10,6 +11,12 @@ function SmartHome(props) {
|
|||||||
const id = setInterval(() => setIdx(i => i + 1), 20);
|
const id = setInterval(() => setIdx(i => i + 1), 20);
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, []);
|
}, []);
|
||||||
|
function turnOn() {
|
||||||
|
axios.get(`${LIGHTS_URL}/on`);
|
||||||
|
}
|
||||||
|
function turnOff() {
|
||||||
|
axios.get(`${LIGHTS_URL}/off`);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
align="center"
|
align="center"
|
||||||
@@ -21,8 +28,14 @@ function SmartHome(props) {
|
|||||||
height="95vh"
|
height="95vh"
|
||||||
>
|
>
|
||||||
<img src={`${CAMERA_URL}?id=${idx}`} />
|
<img src={`${CAMERA_URL}?id=${idx}`} />
|
||||||
|
<Box direction="row" margin="1em 0">
|
||||||
|
<Button primary size="large" onClick={turnOn}
|
||||||
|
label="Turn On Lights" margin="0 0 0 0" />
|
||||||
|
<Button primary size="large" onClick={turnOff}
|
||||||
|
label="Turn Off Lights" margin="0 0 0 1em" />
|
||||||
|
</Box>
|
||||||
<Button primary size="large" onClick={props.close}
|
<Button primary size="large" onClick={props.close}
|
||||||
label="Dismiss" margin="1.5em" />
|
label="Dismiss" margin="0" />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Accident from "./Accident";
|
|||||||
import PetMode from "./PetMode";
|
import PetMode from "./PetMode";
|
||||||
import SmartHome from "./SmartHome";
|
import SmartHome from "./SmartHome";
|
||||||
import Maps from "./Maps";
|
import Maps from "./Maps";
|
||||||
|
import Marketplace from "./Marketplace";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
warning: Warning,
|
warning: Warning,
|
||||||
@@ -14,4 +15,5 @@ export default {
|
|||||||
petMode: PetMode,
|
petMode: PetMode,
|
||||||
smartHome: SmartHome,
|
smartHome: SmartHome,
|
||||||
maps: Maps,
|
maps: Maps,
|
||||||
|
marketplace: Marketplace,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ const TG_USERID = 123456789;
|
|||||||
const CAR_API = "http://localhost:5000/";
|
const CAR_API = "http://localhost:5000/";
|
||||||
const CAMERA_URL = "http://path.to/still/image.jpg";
|
const CAMERA_URL = "http://path.to/still/image.jpg";
|
||||||
const MAPS_API = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
const MAPS_API = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||||
|
const LIGHTS_URL = "http://192.168.1.50:5000/";
|
||||||
|
|
||||||
export { WS_BASE, TG_API, TG_USERID, CAR_API, CAMERA_URL, MAPS_API };
|
export { WS_BASE, TG_API, TG_USERID, CAR_API, CAMERA_URL, MAPS_API, LIGHTS_URL };
|
||||||
|
|||||||
Reference in New Issue
Block a user