Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sensor plot example with interval #840

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43,474 changes: 43,474 additions & 0 deletions examples/sensor-interval/package-lock.json

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions examples/sensor-interval/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "sensor-interval",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.21.1",
"bootstrap": "^4.6.0",
"jquery": "^3.5.1",
"moment": "^2.29.1",
"named-urls": "^2.0.0",
"plotly.js": "^1.58.4",
"react": "^17.0.1",
"react-bootstrap": "^1.5.0",
"react-datepicker": "^4.16.0",
"react-dom": "^17.0.1",
"react-intl": "^6.4.4",
"react-plotly.js": "^2.5.1",
"react-scripts": "^4.0.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write \"src/**/*.{js,jsx,css}\""
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"prettier": "^2.2.1"
}
}
11 changes: 11 additions & 0 deletions examples/sensor-interval/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Sensor Graph Example</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
167 changes: 167 additions & 0 deletions examples/sensor-interval/src/apiHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { reverse } from "named-urls";
import axios from "axios";

export const constant = {
ID: "id",
ALIAS: "alias",
AVAILABLE_SENSORS: "AvailableSensors",
VALUES: "Values",
SAMPLING_RATE: "SamplingRate",
REALM: "realm",
TOKEN: "token",
ENDPOINT: "endpoint",
};
const Endpoint = {
device_alias: "devices-by-alias/:device_alias/",
device_id: "devices/:id?",
interface_by_alias: "devices/:device_alias/interfaces/:interface/",
interface_by_id: "devices/:device_id/interfaces/:interface/",
interface_id_path: "devices/:device_id/interfaces/:interface/:path/value",
interface_alias_path:
"devices/:device_alias/interfaces/:interface/:path/value",
interface_id_interval_path: "devices/:device_id/interfaces/:interface",
};

function getAPIUrl(endPoint, params = null) {
const path = reverse(Endpoint[endPoint], params);
return getEndPoint() + "appengine/v1/" + getRealmName() + "/" + path;
}

function GET(url, params) {
const headers = {
"Content-Type": "application/json",
Authorization: `Bearer ${getAuthToken()}`,
};
return axios.get(url, { headers: headers, params: params });
}

// API Functions

function getDeviceById(id, params = {}) {
const URL = getAPIUrl("device_id", { id: id });
return GET(URL, params);
}

export function getAvailableSensors(device_id, interface_id) {
// Construct the URL to fetch available sensors
const URL = getAPIUrl("interface_id_interval_path", {
device_id: device_id,
interface: interface_id,
});

// Use the GET function to fetch available sensors
return GET(URL)
.then((response) => {
const availableSensors = response.data.data;
return Promise.resolve(availableSensors);
})
.catch((err) => {
console.error("Error fetching available sensors:", err);
return Promise.reject(err);
});
}

export const getDeviceDataById = (id, params = {}) => {
return getDeviceById(id, params)
.then((response) => {
const data = response.data.data;
const interfaces = Object.keys(data.introspection);
const availableIndex = interfaces.findIndex(
(key) => key.search(constant.AVAILABLE_SENSORS) > -1
);
const valueIndex = interfaces.findIndex(
(key) => key.search(constant.VALUES) > -1
);
return Promise.resolve({ valueIndex, availableIndex, interfaces });
})
.catch((err) => {
return Promise.reject(err);
});
};

export const getDeviceDataByAlias = (alias, params = {}) => {
return getDeviceByAlias(alias, params)
.then((response) => {
const data = response.data.data;
const interfaces = Object.keys(data.introspection);
const availableIndex = interfaces.findIndex(
(key) => key.search(constant.AVAILABLE_SENSORS) > -1
);
const valueIndex = interfaces.findIndex(
(key) => key.search(constant.VALUES) > -1
);
return Promise.resolve({ valueIndex, availableIndex, interfaces });
})
.catch((err) => {
return Promise.reject(err);
});
};

function getDeviceByAlias(alias, params = {}) {
const URL = getAPIUrl("device_alias", { device_alias: alias });
return GET(URL, params);
}

export function getInterfaceById(device_id, interface_id, params = {}) {
const URL = getAPIUrl("interface_by_id", {
device_id: device_id,
interface: interface_id,
});
return GET(URL, params).then((response) => response.data.data);
}

export function getSensorValueById(
device_id,
interface_id,
path,
startDate,
endDate,
params = {}
) {
const URL = getAPIUrl("interface_id_path", {
device_id: device_id,
interface: interface_id,
path: path,
startDate: startDate,
endDate: endDate,
});
return GET(URL, params);
}

export function getInterfaceByAlias(device_alias, interface_id, params = {}) {
const URL = getAPIUrl("interface_by_id", {
device_alias: device_alias,
interface: interface_id,
});
return GET(URL, params).then((response) => response.data.data);
}

// LocalStorage Config

export function setAuthToken(token) {
localStorage.setItem(constant.TOKEN, token);
}

export function getAuthToken() {
return localStorage.getItem(constant.TOKEN) || undefined;
}

export function setRealmName(realm_name) {
localStorage.setItem(constant.REALM, realm_name);
}

export function getRealmName() {
return localStorage.getItem(constant.REALM) || undefined;
}

export function setEndPoint(endpoint) {
localStorage.setItem(constant.ENDPOINT, endpoint);
}

export function getEndPoint() {
return localStorage.getItem(constant.ENDPOINT) || undefined;
}

export function isMissingCredentials() {
return !(getEndPoint() && getAuthToken() && getRealmName());
}
44 changes: 44 additions & 0 deletions examples/sensor-interval/src/assets/css/cast.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
body {
font-family: "Montserrat", sans-serif;
}
.sensor-id-search-div,
.list-group-item {
background: #f3f3f3;
}
.main-row .input-group .form-control {
height: 2.5rem;
}

.main-card.card .btn img {
height: 0.9375rem;
}
.main-row .input-group .form-control,
.font-14 {
font-size: 0.875rem;
}
.main-card {
box-shadow: 0 0.0625rem 0.25rem 0 rgba(0, 0, 0, 0.09);
}
.list-div-main .list-group-item,
.list-div-main .list-group-item:first-child {
border-radius: 0;
}
.bg-sensor-theme {
background-color: #6aa8d8;
border: 1px solid #6aa8d8;
}

.font-14:hover {
background-color: #6aa8d8;
border: 1px solid #6aa8d8;
}

.font-14:focus {
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
outline: 0;
}

.sensor-values-card{
width: 300px;
}

119 changes: 119 additions & 0 deletions examples/sensor-interval/src/components/CredentialsModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React, { Component } from "react";
import { Col, Form, Modal } from "react-bootstrap";
import {
getAuthToken,
getEndPoint,
getRealmName,
setAuthToken,
setEndPoint,
setRealmName,
} from "../apiHandler";

class CredentialsModal extends Component {
state = {
realm_name: undefined,
token: undefined,
endpoint: undefined,
};

handleValue = (e) => {
e.preventDefault();
this.setState({ [e.target.name]: e.target.value });
};

handleSubmit = (e) => {
const form = e.currentTarget;
e.preventDefault();
if (form.checkValidity() === false) {
e.stopPropagation();
}
const { token, realm_name, endpoint } = this.state;
setAuthToken(token);
setRealmName(realm_name);
setEndPoint(new window.URL(endpoint).href);
this.props.handleCredentialModal();
};

componentDidUpdate(prevProps) {
const { visible } = this.props;
if (visible && prevProps.visible !== visible) {
this.setState({
realm_name: getRealmName(),
token: getAuthToken(),
endpoint: getEndPoint(),
});
}
}

render() {
const { visible } = this.props;
const { realm_name, endpoint, token } = this.state;
return (
<Modal
show={visible}
animation={true}
centered={true}
dialogClassName="main-modal"
backdrop="static"
>
<Modal.Body className="p-5">
<Col xs={12}>
<h6 className="text-center font-weight-bold mb-4">
Enter Your Details
</h6>
</Col>
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="endPoint">
<Form.Label className="mb-1 font-weight-bold">
Endpoint URL
</Form.Label>
<Form.Control
value={endpoint}
required
name="endpoint"
onChange={this.handleValue}
type="text"
placeholder="Enter EndPoint"
className="font-weight-normal rounded"
/>
</Form.Group>
<Form.Group controlId="realmName">
<Form.Label className="mb-1 font-weight-bold">
Realm Name
</Form.Label>
<Form.Control
value={realm_name}
required
name="realm_name"
onChange={this.handleValue}
type="text"
placeholder="Enter Realm Name"
className="font-weight-normal rounded"
/>
</Form.Group>
<Form.Group controlId="token">
<Form.Label className="mb-1 font-weight-bold">Token</Form.Label>
<Form.Control
value={token}
required
onChange={this.handleValue}
name="token"
type="text"
placeholder="Enter Token Number"
className="font-weight-normal rounded"
/>
</Form.Group>
<button
className="mt-3 bg-sensor-theme font-14 text-white py-2 text-uppercase font-weight-normal px-4 rounded text-decoration-none"
type="submit"
>
Submit
</button>
</Form>
</Modal.Body>
</Modal>
);
}
}

export default CredentialsModal;
Loading