Skip to content

Commit

Permalink
Implemented Core API WS
Browse files Browse the repository at this point in the history
  • Loading branch information
BasWilson committed Nov 10, 2021
1 parent 910555d commit db602ea
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 14 deletions.
9 changes: 6 additions & 3 deletions components/cards/KitCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Button from "../Button";
import InProgress from "../InProgress";
import Card from "./Card";
import PeripheralCard from "./PeripheralCard";
import Link from "next/link";

const Container = styled(Card)`
flex-flow: column;
Expand Down Expand Up @@ -47,14 +48,16 @@ export default function KitCard(props) {

<TopContainer>
<h3>{props.kit.name}</h3>
<Button color={"secondary"} inverted label="Open dashboard" />
<Link passHref href={`/dashboard/${props.kit.serial}`}>
<Button color={"secondary"} inverted label="Open dashboard" />
</Link>
</TopContainer>

<PeripheralCardsContainer>
{props.kit.config?.peripherals?.map(peripheral => {
peripheral.measures = props.kit.measures?.measures?.filter(measure => measure.peripheralId === peripheral.id);
return peripheral.details.expectedQuantityTypes?.map(quantityType => {
return <PeripheralCard key={peripheral.id} color={Theme.dark} peripheral={peripheral} expectedQuantityType={quantityType} />
return peripheral.details.expectedQuantityTypes?.map((quantityType, i) => {
return <PeripheralCard key={i} color={Theme.dark} peripheral={peripheral} expectedQuantityType={quantityType} />
})
})}
</PeripheralCardsContainer>
Expand Down
32 changes: 25 additions & 7 deletions components/cards/PeripheralCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import styled from "styled-components";
import propTypes from "prop-types";
import Theme from "../../styles/theme";
import moment from "moment";
import { observer } from "mobx-react-lite"
import { useContext } from "react";
import { measurementCtx } from "../../stores/measurements";

const Container = styled.div`
background: ${props => props.theme.dark};
Expand Down Expand Up @@ -40,25 +43,38 @@ const TimeSince = styled.p`
align-self: flex-end;
`

export default function PeripheralCard(props) {
function PeripheralCard(props) {

const measurementsStore = useContext(measurementCtx);
const { peripheral } = props;

const quantityType = peripheral.details.quantityTypes.find(quantityType => quantityType.id === props.expectedQuantityType);
const measurement = peripheral.measures.find(measurement => measurement.quantityTypeId === props.expectedQuantityType);
if (!measurement) return null;
let measurement = Object.assign([], measurementsStore.measurements)
.sort((a, b) => moment(a.datetime).valueOf() > moment(b.datetime).valueOf() ? -1 : 1)
.find(measurement => measurement.quantityType === props.expectedQuantityType);

// Fallback incase the WS does not send us anything
if (!measurement) {
const oldMeasurement = peripheral.measures.sort((a, b) => moment(a.endDatetime).valueOf() > moment(b.endDatetime).valueOf() ? -1 : 1).find(measurement => measurement.quantityTypeId === props.expectedQuantityType);
measurement = {
value: oldMeasurement.values.average,
datetime: oldMeasurement.endDatetime
}
}

if (!measurement) return null;
return (
<Container {...props}>
<Type>{quantityType?.physicalQuantity || "-"}</Type>

<ValueUnitContainer>
<Value>{(measurement.values.average.toFixed(2)) || "-"}</Value>
<Unit>{quantityType.physicalUnitSymbol}</Unit>
<Value>{(measurement.value.toFixed(2)) || "-"}</Value>
<Unit>{quantityType?.physicalUnitSymbol}</Unit>
</ValueUnitContainer>

<PerifName>{peripheral.name}</PerifName>

<TimeSince>{moment(measurement.datetimeEnd).fromNow()}</TimeSince>
<TimeSince>{moment(measurement.datetime).fromNow()}</TimeSince>
</Container>
)
}
Expand All @@ -72,4 +88,6 @@ PeripheralCard.propTypes = {
PeripheralCard.defaultProps = {
color: Theme.greyDark,
peripheral: {}
};
};

export default observer(PeripheralCard);
54 changes: 51 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"formik": "^2.1.7",
"jwt-decode": "^2.2.0",
"leaflet": "^1.6.0",
"mobx": "^6.3.6",
"mobx-react-lite": "^3.2.2",
"moment": "^2.29.1",
"next": "9.5.4",
"react": "16.13.1",
Expand All @@ -39,4 +41,4 @@
"babel-plugin-styled-components": "^1.11.1",
"prop-types": "^15.7.2"
}
}
}
45 changes: 45 additions & 0 deletions pages/dashboard/[serial].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import styled from "styled-components";
import PageLayout from "../../components/layouts/PageLayout";
import { getLoggedUser, useAuth } from "../../providers/Auth";
import { getFullKit, getKitMeasures, getUserDetails, getUserMemberships } from "../../services/data-api";

function Dashboard({ }) {
const { user, isLogged } = useAuth();

return (
<PageLayout
metaTitle={"Home"}
metaDescription={
"The AstroPlant community platform. Read the latest astroplant news, share your results and stories with your fellow space farmers! Manage your kits, and find help and support for your kit issues. AstroPlant, growing a new generation of urban and space farmers."
}
>
</PageLayout>
);
}

export async function getServerSideProps(ctx) {
let mainKit = null;
const user = getLoggedUser(ctx.req.headers.cookie);

let completeUser = null;
let memberships = null;

if (user) {
completeUser = await getUserDetails(user.username);
memberships = await getUserMemberships(user.username);

if (Array.isArray(memberships) && memberships[0]?.kit) {
const kit = await getFullKit(memberships[0].kit.serial);
kit.measures = await getKitMeasures(memberships[0].kit.serial, {});
mainKit = kit;
}
}

return {
props: {
mainKit: mainKit,
},
};
}

export default Dashboard;
9 changes: 9 additions & 0 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useContext, useEffect } from "react";
import styled from "styled-components";
import ChallengeCard from "../components/cards/ChallengeCard";
import DashboardLinkCard from "../components/cards/DashboardLinkCard";
Expand All @@ -12,6 +13,7 @@ import HelpIcon from "../public/icons/help.svg";
import LibraryIcon from "../public/icons/library.svg";
import SlackIcon from "../public/icons/slack.svg";
import { getFullKit, getKitMeasures, getUserDetails, getUserMemberships } from "../services/data-api";
import { measurementCtx } from "../stores/measurements";
import Breaks from "../utils/breakpoints";

const WelcomeMessage = styled.h1`
Expand All @@ -24,6 +26,13 @@ const WelcomeMessage = styled.h1`

function Home({ mainKit }) {
const { user, isLogged } = useAuth();
const measurementsStore = useContext(measurementCtx);

useEffect(() => {
if (mainKit) {
measurementsStore.setSerial(mainKit.serial);
}
}, [mainKit, measurementsStore])

return (
<PageLayout
Expand Down
1 change: 1 addition & 0 deletions services/data-api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fetchJson, hasError, postJson } from "../utils/fetchTools";

export const API_URL = "https://api.astroplant.sda-projects.nl";
export const WS_API_URL = "wss://api.astroplant.sda-projects.nl/ws";

function postRequest(path, body, options) {
const url = API_URL + path;
Expand Down
62 changes: 62 additions & 0 deletions stores/measurements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { makeAutoObservable } from "mobx"
import { createContext } from "react"
import { WS_API_URL } from "../services/data-api";

class Measurements {

socket = null;
serial = "";
measurements = []

constructor() {
makeAutoObservable(this)
}

setMeasurements = (measurements) => {
this.measurements = measurements;
}

addMeasurement = (measurement) => {
this.measurements = this.measurements.concat(measurement);
}

connect = () => {

if (this.socket?.readyState < 2) {
this.disconnect();
}

this.socket = new WebSocket(WS_API_URL);

this.socket?.addEventListener("open", () => {

if (!this.serial) return;

this.socket.send(JSON.stringify({
id: 1,
jsonrpc: "2.0",
method: "subscribe_rawMeasurements",
params: { kitSerial: this.serial }
}));

this.socket.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.method === "rawMeasurements" && data.params.result) {
this.addMeasurement(data.params.result);
}
})
})
}

disconnect = () => {
this.socket?.close();
}

setSerial = (newSerial) => {
this.serial = newSerial;
this.connect();
}
}

export const measurementsStore = new Measurements();
export const measurementCtx = createContext(measurementsStore);

0 comments on commit db602ea

Please sign in to comment.