Quickstart
A very simple example to get you started with Dimension Four.
For an explanation about the terms you see used here, like space, points and signals, see the api reference
Dashboard
Start in the dashboard by creating and logging in to an account, creating a tenant, and finally a couple of tokens.
Create Account
Go to Dashboard, create an account and log in.
Create tenant
Create a new tenant.
Create tokens
Create two tokens. One admin token, (and if you plan on sharing this with anyone - one readonly token).
API
You can use any http client or graphql client, but the grapgql playground is quick and easy for testing.
Create Space
Query
mutation CREATE_SPACE {
space {
create(input: { name: "All devices" }) {
id
name
}
}
}
Create Point
Query
mutation CREATE_POINT {
point {
create(input: {
spaceId: "<insert_spaceId>"
name: "Our device with sensors"
}){
id
}
}
}
Create Signal
Query
mutation CREATE_SIGNAL {
signal {
create(input: {
pointId: "<insert_pointId>"
signals: [
{
unit: CELSIUS_DEGREES
value: "22.2"
type: "air temperature"
timestamp: "2021-11-17T14:30:21.000+00:00"
}
]
}) {
id
pointId
unit
type
data {
numericValue
rawValue
}
}
}
}
Query last 10 signals from any device
Query
query LATEST_SIGNALS {
signals(
paginate: { last:10 }
){
edges {
node {
id
timestamp
createdAt
type
unit
pointId
data {
numericValue
rawValue
}
}
}
}
}
Query signal from one point
Query
query LATEST_SIGNAL_FROM_MY_DEVICE {
points(where: { name: { _EQ: "Our device with sensors" } }) {
edges {
node {
temperature: signals(
where: { type: { _EQ: "air temperature" }}
paginate: { last:1 }
){
edges {
node {
id
timestamp
createdAt
type
unit
pointId
data {
numericValue
rawValue
}
}
}
}
}
}
}
}
Browser example (counter)
Finally, you can use this example code to see how this could be used client side in a browser. For more examples see http examples
Code
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<div id="counter" class="counter">
<div id="number" class="number"></div>
</div>
<div id="error" class="error"></div>
</body>
<style>
html {
font-family: Arial, Helvetica, sans-serif;
background-color: blanchedalmond;
}
.counter {
background-color: blueviolet;
max-width: fit-content;
min-width: 40px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
font-size: large;
font-weight: bold;
color: white;
}
.number {
padding: 5px;
}
.error {
color: red;
}
</style>
<script>
const API_URL = "https://iot.dimensionfour.io/graph";
const TENANT_ID = "<tenant-id>";
const TENANT_KEY = "<tenant-key>";
const QUERY = `
query LATEST_SIGNAL_FROM_MY_DEVICE {
points(where: { name: { _EQ: "Our device with sensors" } }) {
edges {
node {
temperature: signals(
where: { type: { _EQ: "air temperature" }}
paginate: { last:1 }
){
edges {
node {
id
timestamp
createdAt
type
unit
pointId
data {
numericValue
rawValue
}
}
}
}
}
}
}
}`;
let variables = {
deviceName: "Our device with sensors",
type: "air temperature",
};
run();
function showError(error) {
let holder = document.getElementById("error");
holder.innerHTML = holder.innerHTML + JSON.stringify(error);
let _x = document.getElementById("error");
_x.style.display = "block";
}
async function run() {
const data = await getData();
if (data && data.data.points.edges.length > 0) {
let count =
data.data.points.edges[0].node.temperature.edges[0].node.data
.rawValue;
document.getElementById("number").innerHTML = count;
} else {
showError("No data found");
}
}
async function getData() {
try {
const res = await fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-tenant-id": TENANT_ID,
"x-tenant-key": TENANT_KEY,
},
body: JSON.stringify({ query: QUERY, variables: variables }),
});
const body = await res.json();
if (body.errors) {
showError(body.errors);
return;
}
return body;
} catch (error) {
showError(error.toString());
}
}
</script>
</html>
Make sure to use your readonly token in this example if you want to share this with anyone.
Browser example (chart)
Code
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.27.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<meta charset="utf-8" />
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<div id="error" class="error"></div>
<div id="chartContainer" class="chartContainer">
<canvas id="myChart" width="100%" height="100%"></canvas>
</div>
</body>
<style>
html {
font-family: Arial, Helvetica, sans-serif;
background-color: blanchedalmond;
}
.counter {
background-color: blueviolet;
max-width: fit-content;
min-width: 40px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
font-size: large;
font-weight: bold;
color: white;
}
.number {
padding: 5px;
}
.error {
color: red;
}
.chartContainer {
height: 200px;
width: 200px;
}
</style>
<script>
const API_URL = "https://iot.dimensionfour.io/graph";
const TENANT_ID = "<your tenant id>";
const TENANT_KEY = "<your readonly token>";
const QUERY = `
query LATEST_SIGNAL_FROM_MY_DEVICE(
$deviceName: String!
$type: String!
$fromTime: Timestamp!
) {
points(where: {
name: { _EQ: $deviceName }
createdAt: { _GT: $fromTime }
}) {
edges {
node {
temperature: signals(
where: { type: { _EQ: $type }}
paginate: { last: 10 }
){
edges {
node {
id
timestamp
createdAt
type
unit
pointId
data {
numericValue
rawValue
}
}
}
}
}
}
}
}`;
let lastXHours = 2;
let fromTime = new Date();
fromTime.setHours(fromTime.getHours() - lastXHours);
let variables = {
deviceName: "Our device with sensors",
type: "air temperature",
fromTime: fromTime,
};
run();
async function run() {
const data = await getData();
if (data && data.data.points.edges.length > 0) {
const { timestamps, values } = formatData(data);
drawChart({ timestamps, values });
} else {
showError("No data found");
}
}
function showError(error) {
let holder = document.getElementById("error");
holder.innerHTML = holder.innerHTML + JSON.stringify(error);
let _x = document.getElementById("error");
_x.style.display = "block";
}
function formatData(data) {
let input = data.data.points.edges[0].node.temperature.edges;
let timestamps = [];
let values = [];
input.forEach((item) => {
timestamps.push(new Date(item.node.createdAt));
values.push(item.node.data.numericValue);
});
return { timestamps, values };
}
async function getData() {
try {
const res = await fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-tenant-id": TENANT_ID,
"x-tenant-key": TENANT_KEY,
},
body: JSON.stringify({ query: QUERY, variables: variables }),
});
const body = await res.json();
if (body.errors) {
showError(body.errors);
return;
}
return body;
} catch (error) {
showError(error.toString());
}
}
function drawChart(data) {
const ctx = document.getElementById("myChart").getContext("2d");
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: data.timestamps,
datasets: [
{
label: `ºC`,
data: data.values,
backgroundColor: ["rgba(153, 102, 255, 0.2)"],
borderColor: ["rgba(153, 102, 255, 1)"],
borderWidth: 3,
},
],
},
options: {
plugins: {
legend: {
display: false,
},
},
scales: {
x: {
type: "time",
display: false,
ticks: {
source: "auto",
},
},
},
},
});
}
</script>
</html>
Make sure to use your readonly token in this example if you want to share this with anyone.