# Using GraphQL

In this tutorial we will show you how you can use the powerful GraphQL API to access historical and current device data with Datacake.

## GraphQL Requests

### HTTP

You can use a cURL Command to call the GraphQL Library directly.

```graphql
curl \
-X GET \
-H "Content-Type: application/json" \
-H "Authorization: Token 1234567yourtoken1234567" \
--data '{"query": "query { allDevices(inWorkspace:\"dc578994-your-workspace-84221d0\") { currentMeasurements(allActiveFields: true) { value field { verboseFieldName fieldName } } } }"}' \
https://api.datacake.co/graphql/
```

## Libraries

### Datacake Python Wrapper

Datacake official Python GraphQL wrapper:

{% embed url="<https://github.com/datacake/python-datacake-api-wrapper>" %}

### iOS

You can use the Apollo GraphQL Library in your iOS / Swift Applications:

{% embed url="<https://github.com/apollographql/apollo-ios>" %}

### Node-RED

You can use a function node in Node-RED and create a custom GraphlQL query that forwards data directly into Node-RED as a parsed JSON-Object.

```graphql
// Datacake API Token and Workspace
var token = "123456mytoken123456";
var workspace = "1234myworkspace1234";

// GraphQL API URL
msg.url = "https://api.datacake.co/graphql";

// GraphQL Header
msg.headers = {
    "Authorization": "Token "+token,
    "Content-Type": "application/json"
};

// GraphQL Query
var query = `query {
  allDevices(inWorkspace:${workspace}) {
    id
    serialNumber
    verboseName
    currentMeasurements(allActiveFields: true) {
      field {
        fieldName
        verboseFieldName
      }
      value
    }
  }
}`;

msg.payload = {"query": query};
msg.body = {"query": query};

return msg;
```

#### Node-RED Flow Export

Copy the following Node-RED Flow of a working Datacake GraphQL Example and paste this into your Node-RED using "Import" function.

{% embed url="<https://gist.github.com/simmikolon/4a188e7347c90cfb3799ac3f8064496f>" %}

## Workspaces

### List of Workspaces

```graphql
query {
  allWorkspaces {
    id
    name
  }
}
```

### List of Devices

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    id
    verboseName
  }
}
```

## Current Measurements

### All Devices in Workspace

You can use the `currentMeasurements` option to have all the last recorded measurements of one or more devices returned.

Use the `allActiveFields` option as follows to return only those fields that are active in the database.

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    currentMeasurements(allActiveFields: true) {
      value
      modified
      field {
        verboseFieldName
        fieldName
      }
    }
  }
}
```

#### Specific Fields only

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    currentMeasurements(fieldNames:["BATTERY"]) {
      value
      modified
      field {
        verboseFieldName
        fieldName
      }
    }
  }
}
```

#### Single Fields only

Instead of providing an Array of Field Identifiers you can use the `currentMeasurement` Option to Query a specific field only.

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    currentMeasurement(fieldName:"BATTERY") {
      value
      modified
      field {
        verboseFieldName
        fieldName
      }
    }
  }
}
```

### Specific Device

The above examples are using the `allDevices` Option to query all devices in a given Workspace. If you just want to access data from a specific device only, you can use the `device` Option.

```graphql
device(deviceId:"faf34567-5f13-4536-b3f3-a4a1e245ab2a")
```

Use this as in the following example query:

```graphql
query {
  device(deviceId:"faf34567-5f13-4536-b3f3-a4a1e245ab2a") {
    currentMeasurements(allActiveFields: true) {
      value
      modified
      field {
        verboseFieldName
        fieldName
      }
    }
  }
}
```

### Working with Strings

If your fields in database store a `String`-type value you have to add the `valueString` option to return the corresponding value.

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    currentMeasurements(allActiveFields: true) {
      valueString
      modified
      field {
        verboseFieldName
        fieldName
      }
    }
  }
}
```

### Working with Maximum, Average

```graphql
maximum(timeRangeStart:"2021-04-16T00:00", timeRangeEnd:"2021-04-17T00:00")
average(timeRangeStart:"2021-04-16T00:00", timeRangeEnd:"2021-04-17T00:00")
change(average(timeRangeStart:"2021-04-16T00:00", timeRangeEnd:"2021-04-17T00:00")
```

```graphql
query {
  device(deviceId:"faf34567-5f13-4536-b3f3-a4a1e245ab2a") {
    currentMeasurements(allActiveFields: true) {
      value
      maximum(timeRangeStart:"2021-04-16T00:00", timeRangeEnd:"2021-04-17T00:00")
      field {
        verboseFieldName
        fieldName
      }
    }
  }
}
```

So will look like

```graphql
{
  "data": {
    "device": {
      "currentMeasurements": [
        {
          "value": 3.067,
          "average": 3.06697222222223,
          "maximum": 3.069,
          "change": 0,
          "modified": "2021-04-17T12:58:30.554976+00:00",
          "field": {
            "verboseFieldName": "Battery",
            "fieldName": "BATTERY"
          }
        }
      ]
    }
  }
}
```

## Historical Data

### From all Devices in Workspace

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    history(
      fields:["BATTERY"], 
      timerangestart:"2021-04-16T00:00", 
      timerangeend:"2021-04-17T00:00", 
      resolution:"120m"
    )
  }
}
```

* `fields`: Set of fields, has to be identifier of database field.
* `timerangestart`: Starting of time frame, has to be before `timerangeend`.
* `timerangeend`: End of time frame, should never be in the future.
* `resultion`: Quantisation-Factor, see below.

### From a Specific Device

```graphql
query {
  device(deviceId:"faf34567-5f13-4536-b3f3-a4a1e245ab2a") {
    history(fields:["BATTERY"], timerangestart:"2021-04-16T00:00", timerangeend:"2021-04-17T00:00", resolution:"raw") 
  }
}
```

Fields have to be Identifier:

```graphql
fields:["BATTERY"]
```

### Multiple Fields

```graphql
query {
  device(deviceId:"702d77a7-a292-476a-a546-d5dde80e6f5d") {
    history(fields:["HUM_SHT", "TEMPC_SHT"], timerangestart:"2023-12-16T00:00", timerangeend:"2023-12-17T00:00", resolution:"30 minutes") 
  }
}
```

### Working with Resolution

One of the options for the history settings is an option called resolution. This gives you two options:

* `raw` - Raw Data Export. Data will be exported as stored in the database
* `X minutes` - Quantisation in X Minutes - Data will be combined into timerange-chunks of given value.
* Other valid values are: `X hours`

{% hint style="info" %}
The operation for quantisation is an **average**. You cannot change this right now.
{% endhint %}

#### Raw Data Export

```graphql
query {
  device(deviceId:"faf34567-5f13-4536-b3f3-a4a1e245ab2a") {
    history(
      fields:["BATTERY"], 
      timerangestart:"2021-04-16T00:00", 
      timerangeend:"2021-04-17T00:00", 
      resolution:"raw"
      ) 
  }
}
```

#### Quantisation

```graphql
query {
  device(deviceId:"faf34567-5f13-4536-b3f3-a4a1e245ab2a") {
    history(
      fields:["BATTERY"], 
      timerangestart:"2021-04-16T00:00", 
      timerangeend:"2021-04-17T00:00", 
      resolution:"20m"
      ) 
  }
}
```

## Devices

### Metadata

The following snippet works for both `allDevices` and specific `device` Options.

```graphql
query {
  allDevices(inWorkspace:"f6331019-8978-4a86-b1bc-3522546f67d5") {
    location
    lastHeard
    claimed
    claimCode
    tags
    serialNumber
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.datacake.de/api/graphql-api/using-graphql.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
