Skip to content

HTML & JavaScript example applications

These examples should only require an updated web browser.

Showing a location list

This will let you log in and show a location list.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <style>
            body {
                font-family: sans-serif;
            }
            ul {
                display: none;
                margin-left: 1em;
            }
        </style>
        <script>
            let sessionId;
            let host;

            let graphql = (query, variables) => {
                return fetch(`https://${host}/graphql`, {
                    method: "POST",
                    headers: { Authorization: `bearer ${sessionId}` },
                    body: JSON.stringify({ query, variables })
                }).then(r => r.json());
            };

            let getLocations = async () => {
                let response = await graphql(
                    `
                        query {
                            locations(first: 10) {
                                list {
                                    name
                                    locationId
                                }
                            }
                        }
                    `
                );

                let ul = document.querySelector("ul");
                for (let location of response.data.locations.list) {
                    let li = document.createElement("li");
                    li.textContent =
                        location.name + "(" + location.locationId + ")";
                    ul.appendChild(li);
                }
            };

            let getSessionId = event => {
                let elements = event.target.elements;
                host = elements["host"].value;
                e.preventDefault();
                fetch(`https://${host}/login`, {
                    method: "POST",
                    body: JSON.stringify({
                        username: elements["user"].value,
                        password: elements["pass"].value
                    })
                })
                    .then(res => res.json())
                    .then(res => {
                        if (res.sessionId) {
                            sessionId = res.sessionId;
                            document.querySelector(
                                "form"
                            ).textContent = sessionId;
                            document.querySelector("ul").style.display =
                                "block";
                            getLocations();
                        } else {
                            alert("login failed :(");
                        }
                    });
            };
        </script>
    </head>
    <body>
        <form onsubmit="getSessionId(event)">
            <label for="host">Host</label>
            <input
                type="text"
                placeholder="devshrek.yanzi.nu"
                name="host"
                required
            />
            <label for="user">Username</label>
            <input
                type="text"
                placeholder="Enter Username"
                name="user"
                required
            />
            <label for="pass">Password</label>
            <input type="password" placeholder="hunter2" name="pass" required />
            <button type="submit">Login</button>
        </form>
        <ul>
            <li>
                <h3>Locations</h3>
            </li>
        </ul>
    </body>
</html>

Showing live samples

Copy this code and put it in a file called live.html, and then open it in your browser. To make it work a sessionId has to be put after a # at the end of the url. It should end up looking like file://some/path.../live.html#YW5kcmVhcy5tYXJ0ZW5.... Unfortunately you may not have access to the location with locationId "699166", so you will likely have to edit this number to match a location you do have access to.

<!DOCTYPE html>
<html>
    <head>
        <script src="https://unpkg.com/subscriptions-transport-ws/browser/client.js"></script>

        <script>
            if (!location.hash.slice(1)) {
                document.write("Unable to find sessionId!<br>");
                document.write("You need to end the URL with #YW5kcmV...");
            } else {
                document.write(
                    'Latest temperature sample: <pre id="sample"></pre>'
                );
                let el = document.getElementById("sample");
                let subscriptionsClient = new SubscriptionsTransportWs.SubscriptionClient(
                    "wss://devshrek.yanzi.nu/graphql",
                    {
                        reconnect: true,
                        connectionParams: {
                            sessionId: location.hash.slice(1)
                        }
                    }
                );

                let query = `subscription { subscribeLocation(locationId:"699166", subscriptionType:data) { locationId } }`;

                subscriptionsClient.request({ query }).subscribe(data => {
                    if (
                        data.subscribeLocation.list[0].dataSourceAddress
                            .variableName.name === "temperatureK"
                    ) {
                        el.innerHTML = JSON.stringify(data, null, 2);
                    }
                });
            }
        </script>
    </head>
    <body></body>
</html>

Getting more information

This is an example that is a bit larger and shows a very simple nested list view of some of the things that can be found in the API. Using the lit-html library makes this example quite small and quick to get started with, however for a larger project one should at least research other alternatives.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <style>
            body {
                font-family: sans-serif;
            }
            ul {
                margin-left: 1em;
            }
        </style>
        <script type="module">
            import { html, render } from "https://cdn.pika.dev/lit-html/v1";

            let sessionId = sessionStorage.getItem("sessionId");
            let host = sessionStorage.getItem("host") || "devshrek.yanzi.nu";

            let accountList = [];
            let locationStore = {};
            let deviceStore = {};
            let datasourceStore = {};

            let login = () => html`
                <form @submit=${getSessionId}>
                    <label for="host">Hostname</label>
                    <input
                        type="text"
                        placeholder="devshrek.yanzi.nu"
                        name="hostname"
                        required
                    />
                    <label for="user">Username</label>
                    <input
                        type="text"
                        placeholder="Enter Username"
                        name="user"
                        required
                    />

                    <label for="pass">Password</label>
                    <input
                        type="password"
                        placeholder="Enter Password"
                        name="pass"
                        required
                    />

                    <button type="submit">Login</button>
                </form>
            `;

            let accounts = () => html`
                <ul>
                    <li>
                        <h2>Accounts</h2>
                        <button @click=${getAccounts}>fetch</button>
                    </li>
                    ${accountList.map(
                        ({ accountName, accountNumber }) =>
                            html`
                                <li>
                                    ${accountName} (${accountNumber}) ${locationStore[
                                        accountNumber
                                    ]
                                        ? locations(accountNumber)
                                        : html`
                                                <button
                                                    @click=${() =>
                                                        getLocations(
                                                            accountNumber
                                                        )}
                                                >
                                                    Get locations
                                                </button>
                                          `}
                                </li>
                            `
                    )}
                </ul>
            `;

            let locations = accountNumber => html`
                <ul>
                    <li>
                        <h3>Locations</h3>
                    </li>
                    ${locationStore[accountNumber].list.map(
                        ({ name, locationId }) =>
                            html`
                                <li>
                                    ${name} (${locationId}) ${deviceStore[
                                        locationId
                                    ]
                                        ? devices(locationId)
                                        : html`
                                                <button
                                                    @click=${() =>
                                                        getDevices(locationId)}
                                                >
                                                    Get devices
                                                </button>
                                          `}
                                </li>
                            `
                    )}
                    <button
                        @click=${() =>
                            getLocations(
                                accountNumber,
                                locationStore[accountNumber].cursor
                            )}
                    >
                        get more...
                    </button>
                </ul>
            `;

            let devices = locationId => html`
                <ul>
                    <li>
                        <h4>Devices</h4>
                    </li>
                    ${deviceStore[locationId].list.map(
                        ({ name, unitAddress: { did } }) =>
                            html`
                                <li>
                                    ${name} (${did}) ${datasourceStore[
                                        locationId + did
                                    ]
                                        ? datasources(locationId, did)
                                        : html`
                                                <button
                                                    @click=${() =>
                                                        getDataSources(
                                                            locationId,
                                                            did
                                                        )}
                                                >
                                                    Get datasources
                                                </button>
                                          `}
                                </li>
                            `
                    )}
                    <li>
                        <button
                            @click=${() =>
                                getDevices(
                                    locationId,
                                    deviceStore[locationId].cursor
                                )}
                        >
                            get more...
                        </button>
                    </li>
                </ul>
            `;

            let datasources = (locationId, did) => html`
                <ul>
                    <li>
                        <h5>Data sources</h5>
                    </li>
                    ${datasourceStore[locationId + did].map(
                        ({ variableName, siUnit }) =>
                            html`
                                <li>
                                    ${variableName} (${siUnit})
                                </li>
                            `
                    )}
                </ul>
            `;

            let main = () => accounts();

            let getAccounts = async () => {
                let response = await graphql(`
                    query {
                        accounts {
                            accountName
                            accountNumber
                        }
                    }
                `);
                accountList = response.data.accounts;
                render(main(), document.body);
            };

            let getLocations = async (accountNumber, after) => {
                let response = await graphql(
                    `
                        query($after: String, $search: String) {
                            locations(
                                first: 10
                                after: $after
                                search: $search
                            ) {
                                cursor
                                list {
                                    name
                                    locationId
                                }
                            }
                        }
                    `,
                    { after, search: accountNumber }
                );

                if (!after) locationStore[accountNumber] = { list: [] };

                locationStore[accountNumber].list.push(
                    ...response.data.locations.list
                );
                locationStore[accountNumber].cursor =
                    response.data.locations.cursor;
                render(main(), document.body);
            };

            let getDevices = async (locationId, after) => {
                let response = await graphql(
                    `
                        query($locationId: String!, $after: String) {
                            location(locationId: $locationId) {
                                units(first: 10, after: $after) {
                                    cursor
                                    list {
                                        name
                                        unitAddress {
                                            did
                                        }
                                    }
                                }
                            }
                        }
                    `,
                    { locationId, after }
                );

                if (!after) deviceStore[locationId] = { list: [] };

                deviceStore[locationId].list.push(
                    ...response.data.location.units.list
                );
                deviceStore[locationId].cursor =
                    response.data.location.units.cursor;
                render(main(), document.body);
            };

            let getDataSources = async (locationId, did) => {
                let response = await graphql(
                    `
                        query($locationId: String!, $did: String!) {
                            location(locationId: $locationId) {
                                unit(did: $did) {
                                    dataSources {
                                        variableName
                                        siUnit
                                    }
                                }
                            }
                        }
                    `,
                    { locationId, did }
                );

                datasourceStore[locationId + did] =
                    response.data.location.unit.dataSources;
                render(main(), document.body);
            };

            let validSessionId = async () => {
                let res = await fetch(`https://${host}/login`, {
                    method: "POST",
                    body: JSON.stringify({ sessionId })
                });
                if (!res.ok) throw res;
            };

            let graphql = (query, variables) => {
                return fetch(`https://${host}/graphql`, {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        Authorization: `bearer ${sessionId}`
                    },
                    body: JSON.stringify({
                        query,
                        variables: variables || {}
                    })
                }).then(r => r.json());
            };

            let getSessionId = e => {
                let elements = e.target.elements;
                e.preventDefault();
                fetch(`https://${elements["hostname"].value}/login`, {
                    method: "POST",
                    body: JSON.stringify({
                        username: elements["user"].value,
                        password: elements["pass"].value
                    })
                })
                    .then(res => res.json())
                    .then(res => {
                        sessionId = res.sessionId;
                        sessionStorage.setItem("sessionId", sessionId);
                        sessionStorage.setItem(
                            "host",
                            elements["hostname"].value
                        );
                    })
                    .then(validSessionId(sessionId))
                    .then(() => {
                        render(main(), document.body);
                    })
                    .catch(e => {
                        console.error(e);
                    });
            };

            validSessionId()
                .then(() => render(main(), document.body))
                .catch(() => render(login(), document.body));
        </script>
    </head>
    <body></body>
</html>
Back to top