# 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
  }
}
```
