forked from astarte-platform/astarte
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added example of sensor sampling rate
Displays Sensor rate and status data Can Update status (On, Off, Handled by device) and sampling period value Uses "SamplingRate", "Values" interfaces in this example Fix astarte-platform#99 Signed-off-by: Shubham Wadhwa <shubham.wadhwa@ispirata.com>
- Loading branch information
Shubham Wadhwa
committed
May 5, 2020
1 parent
a2b2688
commit 90c6e88
Showing
10 changed files
with
15,701 additions
and
0 deletions.
There are no files selected for viewing
14,827 changes: 14,827 additions & 0 deletions
14,827
examples/sensor-samplingrate/package-lock.json
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"name": "sensor-samplingrate", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"axios": "^0.19.2", | ||
"named-urls": "^2.0.0", | ||
"bootstrap": "^4.4.1", | ||
"react": "^16.12.0", | ||
"react-bootstrap": "^1.0.0-beta.16", | ||
"react-dom": "^16.12.0", | ||
"react-scripts": "3.4.0" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test", | ||
"eject": "react-scripts eject", | ||
"format-js": "prettier --write \"src/**/*.js\"" | ||
}, | ||
"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": "^1.19.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<meta name="theme-color" content="#000000" /> | ||
<title>SENSOR SAMPLING VIEWER</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { reverse } from "named-urls"; | ||
import axios from "axios"; | ||
|
||
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/:sensor_id/:key" | ||
}; | ||
|
||
export default class ApiHandler { | ||
constructor({ endpoint, realm, token, version = "v1" }) { | ||
this.token = token; | ||
this.endpoint = new URL(endpoint); | ||
this.realm = realm; | ||
this.version = version; | ||
this.socket = null; | ||
} | ||
|
||
getDevice(device) { | ||
if (this.isDeviceId(device)) { | ||
return this.getDeviceDataById(device); | ||
} else { | ||
return this.getDeviceDataByAlias(device); | ||
} | ||
} | ||
|
||
getHeaders() { | ||
return { | ||
"Content-Type": "application/json", | ||
Authorization: `Bearer ${this.token}` | ||
}; | ||
} | ||
|
||
getAPIUrl(endPoint, params) { | ||
const path = reverse(ENDPOINT[endPoint], params); | ||
return new URL( | ||
`/appengine/${this.version}/${this.realm}/${path}`, | ||
this.endpoint | ||
); | ||
} | ||
|
||
GET(url, params) { | ||
return axios.get(url, { headers: this.getHeaders(), params: params }); | ||
} | ||
|
||
PUT(url, params) { | ||
return axios.put(url, params, { headers: this.getHeaders() }); | ||
} | ||
|
||
DELETE(url) { | ||
return axios.delete(url, { headers: this.getHeaders() }); | ||
} | ||
|
||
isDeviceId(value) { | ||
const expression = new RegExp(/^[a-zA-Z0-9-_]{22}$/g); | ||
return expression.test(value); | ||
} | ||
|
||
getDeviceDataById(device, params = {}) { | ||
const URL = this.getAPIUrl("device_id", { id: device }); | ||
return this.GET(URL, params) | ||
.then(response => Promise.resolve(response.data.data)) | ||
.catch(err => Promise.reject(err)); | ||
} | ||
|
||
getDeviceDataByAlias(alias, params = {}) { | ||
const URL = this.getAPIUrl("device_alias", { device_alias: alias }); | ||
return this.GET(URL, params) | ||
.then(response => Promise.resolve(response.data.data)) | ||
.catch(err => Promise.reject(err)); | ||
} | ||
|
||
getSensorValueById(id, interfaces, sensor_id, key, params = {}) { | ||
const URL = this.getAPIUrl("interface_id_path", { | ||
device_id: id, | ||
interface: interfaces, | ||
sensor_id: sensor_id, | ||
key: key | ||
}); | ||
return this.GET(URL, params); | ||
} | ||
|
||
setSensorSamplingById(data) { | ||
const { id, interfaces, sensor_id, key, unset = false, params = {} } = data; | ||
const URL = this.getAPIUrl("interface_id_path", { | ||
device_id: id, | ||
interface: interfaces, | ||
sensor_id: sensor_id, | ||
key: key | ||
}); | ||
if (unset) return this.DELETE(URL); | ||
return this.PUT(URL, params); | ||
} | ||
|
||
getInterfaceById(device_id, interface_id, params = {}) { | ||
const URL = this.getAPIUrl("interface_by_id", { | ||
device_id: device_id, | ||
interface: interface_id | ||
}); | ||
return this.GET(URL, params).then(response => response.data.data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
:root { | ||
--gray-light-dark: #ced4da; | ||
--lighter-gray: #f8f8f8; | ||
} | ||
body { | ||
font-family: "Montserrat", sans-serif; | ||
} | ||
.sensor-id-search-div, | ||
.main-modal .form-control, | ||
.main-modal .form-control:focus, | ||
.main-card .list-group { | ||
background: var(--lighter-gray); | ||
} | ||
.btn.btn-primary, | ||
.main-modal .form-control, | ||
.main-row .input-group .form-control { | ||
height: 2.5rem; | ||
} | ||
.device-status-div .status-tag { | ||
width: 0.625rem; | ||
height: 0.625rem; | ||
} | ||
.temperature-list h1 { | ||
text-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.2); | ||
} | ||
.main-card.card .btn { | ||
font-size: 1rem; | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
min-height: 57px; | ||
} | ||
.main-card.card .btn:focus, | ||
.main-card.card .btn:hover, | ||
.main-modal .form-control:focus, | ||
.btn.btn-primary:focus, | ||
.btn.btn-primary:hover { | ||
box-shadow: none; | ||
} | ||
.main-card.card .btn img { | ||
height: 0.9375rem; | ||
} | ||
.main-card .list-group-item, | ||
.main-modal .form-label, | ||
.main-modal .form-control, | ||
.btn.btn-primary, | ||
.main-row .input-group .form-control { | ||
font-size: 0.875rem; | ||
} | ||
.main-modal .form-control:focus { | ||
border-color: var(--gray-light-dark); | ||
} | ||
.main-card.card { | ||
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.09); | ||
} | ||
.bg-sensor-theme,.btn-primary { | ||
background-color: #6aa8d8 !important; | ||
border: #6aa8d8; | ||
} | ||
|
||
.connected { | ||
background-color: #008000; | ||
} | ||
|
||
.disconnected { | ||
background-color: #ff0000; | ||
} | ||
.sensor-sampling-div .form-group{ | ||
margin: 1rem 0; | ||
} | ||
.border-separate{ | ||
border-top: 1px solid #cccccc; | ||
padding-top: 0.9rem; | ||
} |
107 changes: 107 additions & 0 deletions
107
examples/sensor-samplingrate/src/components/CredentialsModal.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import React, { Component } from "react"; | ||
import { Col, Form, Modal } from "react-bootstrap"; | ||
|
||
class CredentialsModal extends Component { | ||
state = { | ||
realm: 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(); | ||
} | ||
this.props.setCredentials(this.state); | ||
}; | ||
|
||
componentDidUpdate(prevProps) { | ||
const { visible } = this.props; | ||
if (visible && prevProps.visible !== visible) { | ||
const config = localStorage.AstarteConfig; | ||
if (config) this.setState(JSON.parse(config)); | ||
} | ||
} | ||
|
||
render() { | ||
const { visible } = this.props; | ||
const { realm, 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 mb-4"> | ||
<b>Enter Your Details</b> | ||
</h6> | ||
</Col> | ||
<Form onSubmit={this.handleSubmit}> | ||
<Form.Group controlId="endPoint"> | ||
<Form.Label className="mb-1"> | ||
<b>Endpoint URL</b> | ||
</Form.Label> | ||
<Form.Control | ||
value={endpoint} | ||
required | ||
name="endpoint" | ||
onChange={this.handleValue} | ||
type="text" | ||
placeholder="Enter EndPoint" | ||
className="rounded" | ||
/> | ||
</Form.Group> | ||
<Form.Group controlId="realmName"> | ||
<Form.Label className="mb-1"> | ||
<b>Realm Name</b> | ||
</Form.Label> | ||
<Form.Control | ||
value={realm} | ||
required | ||
name="realm" | ||
onChange={this.handleValue} | ||
type="text" | ||
placeholder="Enter Realm Name" | ||
className="rounded" | ||
/> | ||
</Form.Group> | ||
|
||
<Form.Group controlId="token"> | ||
<Form.Label className="mb-1"> | ||
<b>Token</b> | ||
</Form.Label> | ||
<Form.Control | ||
value={token} | ||
required | ||
onChange={this.handleValue} | ||
name="token" | ||
type="text" | ||
placeholder="Enter Token Number" | ||
className="rounded" | ||
/> | ||
</Form.Group> | ||
<button | ||
className="mt-3 bg-sensor-theme font-14 text-white py-2 text-uppercase px-4 rounded text-decoration-none" | ||
type="submit" | ||
> | ||
Submit | ||
</button> | ||
</Form> | ||
</Modal.Body> | ||
</Modal> | ||
); | ||
} | ||
} | ||
|
||
export default CredentialsModal; |
Oops, something went wrong.