> For the complete documentation index, see [llms.txt](https://docs.datacake.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.datacake.de/cake-red/datacake-nodes/datacake-nodes.md).

# Datacake Nodes

## Datacake Nodes

Complete reference for Node-RED nodes that integrate with the Datacake IoT Platform via GraphQL API.

### Configuration

#### Datacake GraphQL Config

Configuration node that stores your Datacake API credentials securely.

**Settings**

* **Name** - Optional descriptive name for this configuration
* **Workspace UUID** - Your Datacake workspace UUID (found in workspace settings)
* **Workspace Token** - Your Datacake API token (generated in workspace settings under "API Tokens")

**How to Get Your Credentials**

1. Log in to [Datacake](https://app.datacake.de)
2. Navigate to **Workspace Settings**
3. Find your **Workspace UUID** in the workspace information section
4. Go to **API Tokens** and create a new token with appropriate permissions
5. Copy the token (starts with `dctkn_...`)

***

## Data Query Nodes

### Device

Fetches complete device data including all measurements from a specific Datacake device.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Device** - Select the device from your workspace (loaded dynamically)

**Input**

* `msg.payload` - Any input triggers the query

**Output**

* `msg.payload` - Flattened object containing:
  * Device information (`id`, `serialNumber`, `verboseName`, `location`, `online`, `lastHeard`)
  * All measurements as top-level properties
  * Metadata for each measurement (field type, unit, etc.)

**Example Output**

```json
{
  "id": "device-uuid",
  "serialNumber": "ABC123",
  "verboseName": "Office Sensor",
  "online": true,
  "lastHeard": "2025-10-08T10:30:00.000Z",
  "TEMPERATURE": 22.5,
  "TEMPERATURE_metadata": {
    "id": "field-uuid",
    "type": "FLOAT",
    "unit": "°C"
  },
  "HUMIDITY": 55.0,
  "HUMIDITY_metadata": {
    "id": "field-uuid",
    "type": "FLOAT",
    "unit": "%"
  }
}
```

**Use Cases**

* Real-time device monitoring dashboards
* Device status checks in flows
* Automated alerting based on sensor readings
* Data logging to databases

***

### Field

Fetches specific field values from one or multiple devices. More efficient than the Device node when you only need specific measurements.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Fields** - Add multiple device/field combinations
  * Select device from dropdown
  * Select field from device's available fields
  * Add more combinations with the "Add" button

**Input**

* `msg.payload` - Any input triggers the query

**Output**

**Single Field:**

```json
25.4
```

**Multiple Fields:**

```json
[
  {
    "deviceName": "Office Sensor",
    "fieldName": "TEMPERATURE",
    "value": 25.4
  },
  {
    "deviceName": "Warehouse Sensor",
    "fieldName": "HUMIDITY",
    "value": 68.2
  }
]
```

**Use Cases**

* Monitor specific sensors across multiple locations
* Build custom dashboards with only needed data
* Reduce data overhead for specific measurements
* Track individual field values over time

***

### History

Retrieves historical time series data with flexible time range configuration and automatic resolution optimization.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Device** - Select the device
* **Fields** - Multi-select specific fields to query
* **Time Mode** - Choose how to specify the time range:
  * **Preset** - Quick selections (Last 1h, 6h, 24h, 7d, 30d, 90d)
  * **Dynamic** - Calculate ranges relative to current time or `msg.timestamp`
  * **Fixed** - Specify exact start and end dates
* **Use Incoming Timestamp** - Calculate dynamic ranges from `msg.timestamp`
* **Resolution** - Data bucketing:
  * **Auto** - Automatic optimization based on time range (recommended)
  * **Manual** - Choose specific (1m, 5m, 15m, 1h, 6h, 1d) or custom

**Dynamic Time Range Examples**

* **Last 24 hours:** Start: "Now -24 hours", End: "Now +0 hours"
* **Yesterday:** Start: "Now -2 days", End: "Now -1 days"
* **From incoming timestamp:** Enable "Use Incoming Timestamp", Start: "msg.timestamp -1 hours", End: "msg.timestamp +0 hours"

**Input**

* `msg.payload` - Any input triggers the query
* `msg.timestamp` (optional) - Base time for dynamic ranges when "Use Incoming Timestamp" is enabled

**Output**

```json
{
  "device": {
    "id": "device-uuid",
    "verboseName": "Office Sensor",
    "serialNumber": "ABC123"
  },
  "timeRange": {
    "start": "2025-02-22T00:00:00.000Z",
    "end": "2025-02-23T00:00:00.000Z"
  },
  "resolution": "15m",
  "fields": ["TEMPERATURE", "HUMIDITY"],
  "data": {
    "TEMPERATURE": [
      {"time": "2025-02-22T00:00:00Z", "TEMPERATURE": 22.5},
      {"time": "2025-02-22T00:15:00Z", "TEMPERATURE": 22.7}
    ],
    "HUMIDITY": [
      {"time": "2025-02-22T00:00:00Z", "HUMIDITY": 55.2},
      {"time": "2025-02-22T00:15:00Z", "HUMIDITY": 55.8}
    ]
  }
}
```

**Performance Guidelines**

* **Short ranges (<1h):** Use 1m or 5m resolution
* **Medium ranges (1h-24h):** Use 15m or 1h resolution
* **Long ranges (7-30 days):** Use 6h or 1d resolution
* **Very long ranges (>30 days):** Always use 1d resolution

⚠️ **Important:** Never use raw data (no resolution) for ranges > 7 days to avoid performance issues.

**Use Cases**

* Time series analysis and trend visualization
* Generate historical reports
* Compare data across time periods
* Export data for external analytics tools
* Calculate statistics over custom time windows

***

### Consumption

Calculates consumption statistics for meter and counter devices (energy, water, gas, people counters, etc.) using the GraphQL `change()` operation.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Device** - Select the meter/counter device
* **Field** - Select the cumulative meter field (numeric fields recommended)
* **Timeframes** - Choose which periods to calculate:
  * Today, Yesterday
  * This Week, Last Week
  * This Month, Last Month
  * Last 7 Days, Last 30 Days
  * This Year, Last Year
* **Current Reading** - Include the total cumulative meter value
* **Monthly Breakdown** - Include last 12 months with month-over-month changes
* **Timezone** - Set timezone for accurate day/week/month boundaries (default: UTC)

**Input**

* `msg.payload` - Any input triggers the query
* `msg.deviceId` (optional) - Override the configured device ID
* `msg.fieldName` (optional) - Override the configured field name
* `msg.timeframePresets` (optional) - Override timeframes, e.g., `['today', 'yesterday']`
* `msg.includeMonthlyBreakdown` (optional) - Override monthly breakdown setting

**Output**

```json
{
  "device": {
    "id": "device-uuid",
    "verboseName": "Main Building Energy Meter",
    "online": true,
    "lastHeard": "2025-10-08T10:30:00.000Z"
  },
  "fieldName": "ACTIVE_ENERGY_IMPORT_T1_KWH",
  "timezone": "Europe/Berlin",
  "currentReading": 31823.075,
  "consumption": {
    "today": 6.399,
    "yesterday": 92.264,
    "thisWeek": 166.746,
    "lastWeek": 234.123,
    "thisMonth": 364.409,
    "lastMonth": 914.303
  },
  "comparisons": {
    "todayVsYesterday": {
      "today": 6.399,
      "yesterday": 92.264,
      "change": "-93.06%",
      "changeValue": -85.865
    },
    "thisWeekVsLastWeek": {
      "thisWeek": 166.746,
      "lastWeek": 234.123,
      "change": "-28.78%",
      "changeValue": -67.377
    },
    "thisMonthVsLastMonth": {
      "thisMonth": 364.409,
      "lastMonth": 914.303,
      "change": "-60.15%",
      "changeValue": -549.894
    }
  },
  "monthlyBreakdown": [
    {
      "month": "November 2024",
      "monthShort": "Nov 2024",
      "timestamp": "2024-11-01T00:00:00Z",
      "meterReading": 29850.5,
      "consumption": 850.5,
      "change": -50.2,
      "changePercent": "-5.57%",
      "trend": "decreasing"
    }
  ],
  "monthlyStats": {
    "totalMonths": 12,
    "averageConsumption": "875.45",
    "highestMonth": {
      "month": "January 2025",
      "consumption": 1050.2
    },
    "lowestMonth": {
      "month": "July 2024",
      "consumption": 720.5
    },
    "trend": "stable"
  },
  "timestamp": "2025-10-08T10:30:00.000Z"
}
```

**Supported Device Types**

* ⚡ **Energy Meters** - Track kWh consumption
* 💧 **Water Meters** - Monitor water usage in m³
* 🔥 **Gas Meters** - Measure gas consumption
* 🌡️ **Heating Meters** - Track thermal energy
* 👥 **People Counters** - Count visitors/entries
* 🚗 **Vehicle Counters** - Track traffic
* 📦 **Production Counters** - Monitor manufacturing output

**Use Cases**

* Energy management and cost tracking
* Water leak detection via consumption patterns
* Foot traffic analysis for retail/office spaces
* Billing period consumption calculations
* Efficiency analysis and trend monitoring
* Automated consumption reports and alerts

***

### Semantic

Queries devices by semantic field types across your entire workspace. Supports querying multiple semantics in parallel.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Semantics** - Add one or more semantic types:
  * **Numeric:** TEMPERATURE, HUMIDITY, CO2, BATTERY, SIGNAL, SNR, AMBIENT\_LIGHT, AIR\_POLLUTION, ENERGY\_CONSUMPTION, FILL\_LEVEL, LOUDNESS, PEOPLE\_COUNT, POWER, SOIL\_MOISTURE, VOC, WATER\_CONSUMPTION, WATER\_DEPTH
  * **Boolean:** MOTION\_DETECTED, WINDOW\_OPENED
* **Tags** (Optional) - Filter to devices with specific tags

**Input**

* `msg.payload` - Any input triggers the query

**Output**

Returns an array with one object per configured semantic:

```json
[
  {
    "semantic": "TEMPERATURE",
    "semanticType": "NUMERIC",
    "tags": ["Floor-1"],
    "aggregated": {
      "total": 25,
      "average": 22.5,
      "maximum": 28.3,
      "maximumDevice": {
        "id": "device-uuid-2",
        "name": "Sensor 2",
        "serialNumber": "DEF456"
      },
      "minimum": 18.7,
      "minimumDevice": {
        "id": "device-uuid-3",
        "name": "Sensor 3",
        "serialNumber": "GHI789"
      }
    },
    "devices": [
      {
        "id": "device-uuid-1",
        "name": "Sensor 1",
        "serialNumber": "ABC123",
        "value": 22.5
      }
    ]
  },
  {
    "semantic": "MOTION_DETECTED",
    "semanticType": "BOOLEAN",
    "tags": [],
    "aggregated": {
      "trueCount": 12,
      "falseCount": 8,
      "total": 20
    },
    "devices": [
      {
        "id": "device-uuid-5",
        "name": "Motion Sensor 1",
        "serialNumber": "XYZ789",
        "value": true
      }
    ]
  }
]
```

**Performance**

* Multiple semantics are fetched **in parallel** for optimal speed
* Each semantic query is independent
* Failed queries for individual semantics won't block others

**Use Cases**

* Multi-metric dashboards (temperature, humidity, CO2 simultaneously)
* Environmental monitoring across all devices
* Fleet health overview (battery, signal, temperature)
* Data aggregation for analytics

***

### Product Stats

Calculates min, max, and average statistics for selected fields across all devices in a Datacake product.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Product** - Select the product
* **Fields** - Check the fields you want statistics for
* **Tags Match** - Choose "Match ANY tag" or "Match ALL tags"
* **Filter Tags** - (Optional) Select tags to filter devices

**Input**

* `msg.payload` - Any input triggers the query

**Output**

```json
{
  "TEMPERATURE": {
    "min": 18.5,
    "max": 28.3,
    "avg": 22.7,
    "count": 15,
    "minDevice": {
      "id": "device-uuid-1",
      "name": "Sensor 1"
    },
    "maxDevice": {
      "id": "device-uuid-5",
      "name": "Sensor 5"
    }
  },
  "BATTERY": {
    "min": 3.1,
    "max": 4.2,
    "avg": 3.8,
    "count": 15,
    "minDevice": {
      "id": "device-uuid-3",
      "name": "Sensor 3"
    },
    "maxDevice": {
      "id": "device-uuid-7",
      "name": "Sensor 7"
    }
  }
}
```

**Use Cases**

* Product-wide performance monitoring
* Identify devices with extreme values
* Quality assurance across product fleet
* Environmental condition monitoring

***

### Fleet Health

Provides workspace-wide fleet health statistics and overview metrics.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Tags** (Optional) - Filter to specific device groups
* **Include battery statistics** - Add battery health metrics (default: enabled)
* **Include signal & SNR statistics** - Add signal strength metrics (default: enabled)
* **Include device lists** - Add detailed device arrays (slower, default: disabled)

**Input**

* `msg.payload` - Any input triggers the query

**Output (Compact Mode)**

```json
{
  "workspace": {
    "name": "My Workspace",
    "allTags": ["Floor-1", "Floor-2", "Building-A"]
  },
  "filters": {
    "tags": []
  },
  "fleet": {
    "total": 150,
    "online": 142,
    "offline": 8,
    "onlinePercentage": 94.67
  },
  "battery": {
    "devicesWithBattery": 130,
    "average": 87.5,
    "minimum": 12.3,
    "maximum": 100,
    "lowBatteryCount": 5,
    "lowBatteryPercentage": 3.85
  },
  "signal": {
    "devicesWithSignal": 145,
    "average": -85.3,
    "minimum": -112.5,
    "maximum": -45.0,
    "weakSignalCount": 8,
    "weakSignalPercentage": 5.52
  },
  "snr": {
    "devicesWithSNR": 145,
    "average": 8.7,
    "minimum": -2.5,
    "maximum": 12.3
  },
  "timestamp": "2025-01-15T10:30:00.000Z"
}
```

**Performance Notes**

* Compact mode (without device lists) is very fast (\~200-300ms)
* Including device lists adds overhead proportional to device count
* Battery and signal statistics only query relevant devices

**Use Cases**

* Dashboard KPI widgets showing fleet health
* Alerting on high offline counts or low battery devices
* Monitoring workspace health over time
* Automated status reports
* Tag-based fleet segmentation analysis

***

## Control Nodes

### Downlink

Sends pre-configured LoRaWAN downlink commands to Datacake devices for remote configuration and control.

**Configuration**

* **Config** - Select your Datacake GraphQL Config node
* **Device** - Search and select the target device
  * Search by device name or serial number
  * Paginated results (20 devices per page)
  * Works efficiently with large workspaces
* **Downlink** - Select the downlink command (loaded from device's product)

**Input**

* `msg.payload` - Any input triggers the downlink

**Output**

```json
{
  "ok": true,
  "device": {
    "id": "device-uuid",
    "name": "My Device"
  },
  "downlink": {
    "id": "downlink-uuid",
    "name": "Set timebase to 30 minutes"
  },
  "timestamp": "2025-10-08T12:34:56.789Z"
}
```

**Important Notes**

* Downlinks must be pre-configured in the device's product on Datacake
* LoRaWAN downlinks are queued and sent on the next device uplink
* Success response means the downlink was queued successfully
* If a device has no downlinks, the dropdown shows "No downlinks available"

**Use Cases**

* Remote device configuration (reporting intervals, measurement settings)
* Trigger device actions (LED control, relay switching, calibration)
* Emergency commands (reset, reboot, alarm triggers)
* Scheduled configuration changes (off-peak hours adjustments)
* Conditional downlinks based on sensor readings or events

***

### Device Post

Sends data to a Datacake device using the HTTP API endpoint.

**Configuration**

* **Name** - Optional node name
* **API URL** - The Datacake device API URL (format: `https://api.datacake.co/integrations/api/...`)
* **Serial Number** - Optional serial number (can be set in message)

**Input**

* `msg.payload` - The data to send (object or primitive)
* `msg.apiUrl` (optional) - Override the configured API URL
* `msg.serialNumber` (optional) - Override the configured serial number

**Output**

* `msg.payload` - Response from Datacake API
* `msg.statusCode` - HTTP status code
* `msg.error` (if failed) - Error message

**Data Formatting**

* **If payload is an object:** Properties are included at top level
* **If payload is not an object:** Encapsulated in a `user_data` field

**Example Payload Format**

```json
{
  "device": "your-serial-number",
  "temperature": 23.5,
  "humidity": 45
}
```

**Use Cases**

* Send sensor data from external sources to Datacake
* Forward data from third-party integrations
* Manual data injection for testing
* Bridge data from other platforms

***

## Advanced Nodes

### Raw GraphQL

Execute custom GraphQL queries with full control. For advanced users who need queries not covered by other nodes.

**Configuration**

* **API Token** - Your Datacake API token (direct input, no config node needed)
* **GraphQL Query** - The complete query
* **Variables** - Choose how to provide variables:
  * **None** - No variables
  * **From msg.variables** - Dynamic from message
  * **JSON** - Static JSON defined in node

**Input**

* `msg.payload` - Any input triggers the query
* `msg.variables` (optional) - Query variables when using "From msg.variables" mode

**Output**

* `msg.payload` - The `data` field from GraphQL response
* `msg.graphql` - Metadata including query, variables, and full response

**Example Query**

```graphql
query GetDevice($deviceId: String!) {
  device(deviceId: $deviceId) {
    id
    verboseName
    online
    currentMeasurements {
      field {
        fieldName
        unit
      }
      value
    }
  }
}
```

**Rate Limiting**

⚠️ **Important:** This node enforces a 1-second minimum interval between requests to protect against accidental API abuse. Requests that come in faster will be ignored with a warning.

**Use Cases**

* Custom queries not covered by pre-built nodes
* Cross-workspace queries with different tokens
* Prototyping and testing new queries
* Advanced filtering and complex nested queries
* Batch operations
* Power user workflows

***

## Examples

#### Monitor Device and Send Alert

```
[Inject: Every 5 minutes]
  ↓
[Datacake GraphQL Device]
  ↓
[Function: Check temperature]
  if (msg.payload.TEMPERATURE > 30) {
    msg.alert = true;
    msg.payload = {
      device: msg.payload.verboseName,
      temperature: msg.payload.TEMPERATURE
    };
    return msg;
  }
  return null;
  ↓
[Email/SMS Alert]
```

#### Daily Energy Report

```
[Inject: Daily at 8 AM]
  ↓
[Datacake GraphQL Consumption]
  ↓
[Function: Format report]
  msg.payload = {
    to: 'manager@company.com',
    subject: 'Daily Energy Report',
    text: `Yesterday's consumption: ${msg.payload.consumption.yesterday} kWh
           Change vs previous day: ${msg.payload.comparisons.todayVsYesterday.change}`
  };
  return msg;
  ↓
[Email Node]
```

#### Fleet Health Dashboard

```
[Inject: Every minute]
  ↓
[Datacake GraphQL Fleet Health]
  ↓
[Function: Extract KPIs]
  msg.onlinePercent = msg.payload.fleet.onlinePercentage;
  msg.avgBattery = msg.payload.battery.average;
  msg.lowBatteryCount = msg.payload.battery.lowBatteryCount;
  return msg;
  ↓
[Dashboard Gauges]
```

#### Historical Data Export

```
[Inject: Monthly]
  ↓
[Datacake GraphQL History]
  Fixed Range: First to last day of previous month
  Resolution: 1h
  ↓
[Function: Convert to CSV]
  ↓
[File Write: monthly-data.csv]
```

***

### Tips & Best Practices

#### Performance

1. **Use specific nodes** instead of Raw GraphQL when possible
2. **Enable "Auto" resolution** for History node for optimal performance
3. **Use compact mode** in Fleet Health for faster responses
4. **Group field queries** - Field node groups by device automatically
5. **Cache frequently accessed data** in flow or global context

#### Error Handling

1. **Always use catch nodes** to handle API errors
2. **Check online status** before sending downlinks
3. **Validate field existence** before querying
4. **Handle rate limits** gracefully
5. **Log errors** for debugging

#### Security

1. **Never expose tokens** in flows or debug nodes
2. **Use configuration nodes** for credentials
3. **Limit API token permissions** to what's needed
4. **Rotate tokens** periodically
5. **Monitor API usage** in Datacake dashboard

#### Cost Optimization

1. **Poll less frequently** when real-time data isn't needed
2. **Use Field node** instead of Device node for specific data
3. **Aggregate queries** when possible (Semantic, Product Stats)
4. **Cache data** to reduce API calls
5. **Use appropriate time ranges** for historical queries

***

### Troubleshooting

#### Common Issues

**"Missing configuration" error**

* Ensure Datacake GraphQL Config node is properly configured
* Check that Workspace UUID and Token are entered correctly

**"Device ID not configured" error**

* Select a device from the dropdown in the node configuration
* Refresh the Node-RED editor if devices don't load

**"No data retrieved" warning**

* Check if device is online and has recent data
* Verify field names exist on the device
* Check API token permissions

**Downlink not working**

* Ensure device has downlinks configured in its product
* Check that device is LoRaWAN and supports downlinks
* Verify downlink is queued (check Datacake web interface)
* Wait for next uplink for downlink to be sent

**Historical data empty**

* Verify time range is correct
* Check that fields have data in the specified time range
* Try a different resolution

***

### Resources

* [Datacake API Documentation](https://docs.datacake.de)
* [Node-RED Documentation](https://nodered.org/docs)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.datacake.de/cake-red/datacake-nodes/datacake-nodes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
