Basic spotify and plant
This commit is contained in:
parent
f3f01f9717
commit
c0cc162ae4
@ -9,7 +9,7 @@ module.exports = {
|
|||||||
resolve: "gatsby-plugin-react-svg",
|
resolve: "gatsby-plugin-react-svg",
|
||||||
options: {
|
options: {
|
||||||
rule: {
|
rule: {
|
||||||
include: /weather/ // See below to configure properly
|
include: /weather/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
package-lock.json
generated
18
package-lock.json
generated
@ -13,7 +13,8 @@
|
|||||||
"gatsby-plugin-react-svg": "^3.1.0",
|
"gatsby-plugin-react-svg": "^3.1.0",
|
||||||
"os-browserify": "^0.3.0",
|
"os-browserify": "^0.3.0",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1"
|
"react-dom": "^17.0.1",
|
||||||
|
"react-use-websocket": "^2.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/webpack-env": "^1.16.3"
|
"@types/webpack-env": "^1.16.3"
|
||||||
@ -13263,6 +13264,15 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-use-websocket": {
|
||||||
|
"version": "2.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-2.9.1.tgz",
|
||||||
|
"integrity": "sha512-jV6OxXuxWi6BiPVlbAJd/uWNaoQwkeGARFO9f6HidJeWUatB4J2UopbxI/fduiGpcpHGhRAmpLdfVjeRzrcTnQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.8.0",
|
||||||
|
"react-dom": ">= 16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/read": {
|
"node_modules/read": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
||||||
@ -26439,6 +26449,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz",
|
||||||
"integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ=="
|
"integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ=="
|
||||||
},
|
},
|
||||||
|
"react-use-websocket": {
|
||||||
|
"version": "2.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-2.9.1.tgz",
|
||||||
|
"integrity": "sha512-jV6OxXuxWi6BiPVlbAJd/uWNaoQwkeGARFO9f6HidJeWUatB4J2UopbxI/fduiGpcpHGhRAmpLdfVjeRzrcTnQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"read": {
|
"read": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
"gatsby-plugin-react-svg": "^3.1.0",
|
"gatsby-plugin-react-svg": "^3.1.0",
|
||||||
"os-browserify": "^0.3.0",
|
"os-browserify": "^0.3.0",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1"
|
"react-dom": "^17.0.1",
|
||||||
|
"react-use-websocket": "^2.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/webpack-env": "^1.16.3"
|
"@types/webpack-env": "^1.16.3"
|
||||||
|
53
src/components/PlantState.tsx
Normal file
53
src/components/PlantState.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { PlantState as PlantStateType } from "../lib/interfaces";
|
||||||
|
import * as styles from "../styles/containers/PlantState.module.css"
|
||||||
|
|
||||||
|
const PLANT_REFRESH_INTERVAL = 15 * 60 * 1000;
|
||||||
|
|
||||||
|
const PlantState = ({ hassUrl, token, plants }: { hassUrl: string, token: string, plants: string[] }) => {
|
||||||
|
const [plantStates, setPlantStates] = React.useState<Record<string, PlantStateType>>({});
|
||||||
|
|
||||||
|
const pullPlants = async () => {
|
||||||
|
const plantStates: Record<string, PlantStateType> = {}
|
||||||
|
|
||||||
|
for (const plant of plants) {
|
||||||
|
const response = await fetch(`${hassUrl}/api/states/plant.${plant.toLowerCase()}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${token}`,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
plantStates[plant] = data.attributes
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(plantStates);
|
||||||
|
setPlantStates(plantStates);
|
||||||
|
}
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
pullPlants()
|
||||||
|
const plantInterval = setInterval(pullPlants, PLANT_REFRESH_INTERVAL);
|
||||||
|
|
||||||
|
return () => clearInterval(plantInterval);
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return <div className={`container ${styles.container}`}>
|
||||||
|
{Object.keys(plantStates).map((key) => {
|
||||||
|
return <div key={key} className={styles.plant}>
|
||||||
|
<div>{key}</div>
|
||||||
|
<div className={plantStates[key].problem.includes("moisture") ? styles.problem : ""}>
|
||||||
|
<span className={styles.icon}>💧</span><br />
|
||||||
|
{plantStates[key].moisture === "unavailable" ? "?" : plantStates[key].moisture} {plantStates[key].unit_of_measurement_dict.moisture}
|
||||||
|
</div>
|
||||||
|
<div className={plantStates[key].problem.includes("conductivity") ? styles.problem : ""}>
|
||||||
|
<span className={styles.icon}>🪴</span><br />
|
||||||
|
{plantStates[key].conductivity === "unavailable" ? "?" : plantStates[key].conductivity} {plantStates[key].unit_of_measurement_dict.conductivity}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlantState;
|
28
src/components/Spotify.tsx
Normal file
28
src/components/Spotify.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import useWebSocket from "react-use-websocket";
|
||||||
|
import * as styles from "../styles/containers/Spotify.module.css"
|
||||||
|
|
||||||
|
const Spotify = ({ wsUrl, Alternative }: { wsUrl: string, Alternative: any }) => {
|
||||||
|
const { lastJsonMessage, getWebSocket, sendJsonMessage } = useWebSocket(wsUrl, {
|
||||||
|
onOpen: () => sendJsonMessage({GET:1}),
|
||||||
|
onMessage: (evt) => {
|
||||||
|
console.log(evt.data)
|
||||||
|
},
|
||||||
|
//Will attempt to reconnect on all close events, such as server shutting down
|
||||||
|
shouldReconnect: (closeEvent) => closeEvent.code !== 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
console.log(lastJsonMessage)
|
||||||
|
}, [lastJsonMessage])
|
||||||
|
|
||||||
|
if (!lastJsonMessage || lastJsonMessage.playbackState !== "Play") {
|
||||||
|
return Alternative;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={`container ${styles.container}`}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Spotify;
|
@ -51,3 +51,17 @@ export interface Departure {
|
|||||||
State?: "Delayed" | "InTime" | "Canceled";
|
State?: "Delayed" | "InTime" | "Canceled";
|
||||||
CancelReasons?: string[];
|
CancelReasons?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PlantState {
|
||||||
|
brightness: number | "unavailable";
|
||||||
|
conductivity: number | "unavailable";
|
||||||
|
moisture: number | "unavailable";
|
||||||
|
problem: string;
|
||||||
|
temperature: number | "unavailable";
|
||||||
|
unit_of_measurement_dict: {
|
||||||
|
brightness: string;
|
||||||
|
conductivity: string;
|
||||||
|
moisture: string;
|
||||||
|
temperature: string;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ import secrets from "../../secrets.json"
|
|||||||
import Calendar from "../components/Calendar";
|
import Calendar from "../components/Calendar";
|
||||||
import DVB from "../components/DVB";
|
import DVB from "../components/DVB";
|
||||||
import News from "../components/News";
|
import News from "../components/News";
|
||||||
|
import Spotify from "../components/Spotify";
|
||||||
|
import PlantState from "../components/PlantState";
|
||||||
import WeatherAndTimeContainer from "../components/WeatherAndTime"
|
import WeatherAndTimeContainer from "../components/WeatherAndTime"
|
||||||
import WeatherRadar from "../components/WeatherRadar";
|
import WeatherRadar from "../components/WeatherRadar";
|
||||||
|
|
||||||
@ -38,6 +40,7 @@ const IndexPage = () => {
|
|||||||
<WeatherRadar />
|
<WeatherRadar />
|
||||||
<News />
|
<News />
|
||||||
<DVB stopId={secrets.dvb.stopId} />
|
<DVB stopId={secrets.dvb.stopId} />
|
||||||
|
<Spotify wsUrl="ws://localhost:10000" Alternative={<PlantState hassUrl={secrets.hass.url} token={secrets.hass.token} plants={["Chili", "Basilikum"]} />} />
|
||||||
</main>)
|
</main>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
src/styles/containers/PlantState.module.css
Normal file
44
src/styles/containers/PlantState.module.css
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plant {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas:
|
||||||
|
"plantName plantName"
|
||||||
|
"moisture conductivity";
|
||||||
|
text-align: center;
|
||||||
|
border-right: 1px solid var(--iconColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.plant:last-of-type {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plant div:nth-child(1) {
|
||||||
|
grid-area: plantName;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 200%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plant div:nth-child(2) {
|
||||||
|
grid-area: moisture;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 190%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plant div:nth-child(3) {
|
||||||
|
grid-area: conductivity;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 190%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 250%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.problem {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
21
src/styles/containers/Spotify.module.css
Normal file
21
src/styles/containers/Spotify.module.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.container {
|
||||||
|
grid-area: spotify;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto max-content;
|
||||||
|
justify-content: start;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
padding:5px;
|
||||||
|
background: var(--spotifyColor);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.container p {
|
||||||
|
max-width: 21vw;
|
||||||
|
color: inherit;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 180%;
|
||||||
|
font-weight: bold;
|
||||||
|
color: inherit;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user