Skip to content
Stand with Ukraine flag

Google Cloud Pub/Sub Integration

Google Cloud Pub/Sub is a fully managed publish/subscribe messaging service. The ThingsBoard Pub/Sub integration pulls messages from a GCP pull subscription, decodes them via an uplink converter, and stores telemetry and attributes in ThingsBoard.

Before creating the integration in ThingsBoard, prepare the following in the Google Cloud Console.

  1. Open your GCP project and navigate to APIs & Services ⇾ Library.
  2. Search for Cloud Pub/Sub API and click Enable if not already enabled.
  1. Go to Pub/Sub ⇾ Topics and click Create topic.
  2. Enter a Topic ID (e.g. tb-uplink) and click Create.
  3. Open the new topic and click Create subscription in the Subscriptions tab.
  4. Enter a Subscription ID (e.g. tb-uplink-sub), keep Delivery type set to Pull, and click Create.

ThingsBoard authenticates to GCP using a service account key. The account needs at least the Pub/Sub Subscriber role to receive uplink messages.

  1. Go to IAM & Admin ⇾ Service accounts and click Create service account.
  2. Enter a name (e.g. thingsboard-pubsub) and click Create and continue.
  3. Assign the role Pub/Sub Subscriber and click Done.
  4. Open the created service account, go to the Keys tab, and click Add key ⇾ Create new key.
  5. Select JSON and click Create. Save the downloaded key file securely.

The uplink converter decodes incoming Pub/Sub messages and maps them to the ThingsBoard data model. Pub/Sub uses a generic uplink converter.

The decoder function receives:

  • payload — the raw Pub/Sub message data as a UTF-8 byte array
  • metadataintegrationName and any key-value pairs configured in the integration’s Metadata settings

Sample payload:

{
"deviceName": "Sensor A1",
"deviceType": "thermostat",
"temperature": 23.5,
"humidity": 60
}

The decoder function used in this tutorial:

// Decode an uplink message from a buffer
// payload - array of bytes
// metadata - key/value object
/** Decoder **/
// decode payload to JSON
var data = decodeToJson(payload);
// --- Device name and type ---
var deviceName = data.deviceName != null ? data.deviceName : 'Unknown Device';
var deviceType = data.deviceType != null ? data.deviceType : 'default';
// var customerName = 'Customer C';
// var groupName = 'thermostat devices';
// use assetName and assetType instead of deviceName and deviceType
// to automatically create assets instead of devices.
// var assetName = 'Asset A';
// var assetType = 'building';
// --- Timestamp parsing ---
var timestamp = -1;
if (data.ts != null) {
timestamp = data.ts;
} else if (data.timestamp != null) {
timestamp = new Date(data.timestamp).getTime();
}
if (timestamp == -1) {
timestamp = Date.now();
}
// --- Telemetry and attributes ---
var telemetry = {};
var attributes = {
model: 'Model A',
serialNumber: 'SN111',
integrationName: metadata['integrationName'],
};
// Keys to exclude from telemetry (already used or non-telemetry fields)
var excludeFromTelemetryList = ["deviceName", "deviceType", "ts", "timestamp"];
// Parse all remaining JSON fields as telemetry
telemetry.putAll(toFlatMap(data, excludeFromTelemetryList, true));
// Result object with device attributes/telemetry data
var result = {
deviceName: deviceName,
deviceType: deviceType,
// customerName: customerName,
// groupName: groupName,
// assetName: assetName,
// assetType: assetType,
attributes: attributes,
telemetry: {
ts: timestamp,
values: telemetry
}
};
/** Helper functions 'decodeToString', 'decodeToJson' and 'toFlatMap' are already built-in **/
return result;

To adapt this converter to your device:

  • Different device name / type fields — replace data.deviceName and data.deviceType with the field names your device actually sends (e.g. data.id, data.sensorType).
  • Timestamp — if your payload includes a Unix millisecond timestamp, name the field ts; for an ISO 8601 string, name it timestamp. If neither is present, the converter falls back to the server receive time automatically.
  • Telemetry fields — all JSON fields not listed in excludeFromTelemetryList are mapped to telemetry automatically via toFlatMap. To exclude additional non-telemetry fields (e.g. a firmware version you want as an attribute), add their names to the exclude list.
  • Static attributes — replace model and serialNumber in the attributes object with the actual device properties from your payload or hard-coded values; remove the entries if not needed.
  • Assets instead of devices — uncomment assetName / assetType and comment out deviceName / deviceType to provision assets instead of devices.
  • Customer or group assignment — uncomment customerName or groupName and set the appropriate values to assign the device to a customer or device group.
  1. Go to Integrations center ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Set Integration type to Pub/Sub.
    • Enable integration and Allow create devices or assets are on by default.
    • Click Next.
  3. Uplink data converter:
    • Click Create new, enter a name, paste the decoder function from above, and click Add.
    • Alternatively, click Select existing to reuse a previously created converter.
    • Click Next.
  4. Connection:
    • Project ID — your GCP project ID (e.g. my-gcp-project).
    • Subscription ID — the pull subscription name (e.g. tb-uplink-sub).
    • Service account key — upload the JSON key file via Browse file, or click Use Secret storage to reference a stored secret.
    • See Connection settings for a full description of each parameter.
    • Click Add to save the integration.
Project ID

Your Google Cloud project ID. Found in the project selector dropdown in the GCP Console or on the Project info card on the dashboard.

Subscription ID

The pull subscription name on the uplink topic (e.g. tb-uplink-sub). The subscription must exist in GCP before the integration is created. ThingsBoard reads messages through this subscription — it is already bound to the topic in GCP.

Service account key

The GCP service account key JSON file. The account must have at least roles/pubsub.subscriber on the uplink subscription. Upload the file using Browse file, or store it in ThingsBoard Secret storage and reference it via Use Secret storage.

Execute remotely

When enabled, ThingsBoard generates an Integration key and Integration secret that allow the integration to run as a separate process outside the ThingsBoard cluster — useful when access to GCP is restricted to a specific network. See Remote Integration.

Advanced settings
ParameterDescription
DescriptionOptional text description for the integration.
MetadataKey-value pairs injected into every uplink message as integrationMetadata in the converter script.

Publish a test message to the uplink topic using the gcloud CLI or the GCP Console.

Terminal window
gcloud pubsub topics publish tb-uplink \
--message='{"deviceName":"Sensor A1","deviceType":"thermostat","temperature":23.5,"humidity":60}' \
--project=my-gcp-project

Check device telemetry — go to Entities ⇾ Devices. The device Sensor A1 is automatically provisioned on the first message. Open it and check the Latest telemetry tab — temperature and humidity should reflect the published values. The Attributes tab shows the client attributes set by the converter: integrationName, model, and serialNumber.

Integration events — go to Integrations center ⇾ Integrations, open the Pub/Sub integration, and check the Events tab. Click in the Message column to inspect the raw payload pulled from the subscription.

Converter events — go to Integrations center ⇾ Data converters, click the uplink converter, and open its Events tab. Click in the respective column to inspect each field:

  • In — the raw payload passed to the converter.
  • Out — the decoded result: deviceName, deviceType, attributes (model, serialNumber, integrationName), and telemetry (temperature, humidity).
  • MetadataintegrationName and pubSubMsgId (the unique message ID assigned by GCP Pub/Sub).

The Pub/Sub integration is uplink-only — it does not have a dedicated downlink converter. To publish messages from ThingsBoard back to a GCP Pub/Sub topic, use the GCP Pub/Sub Rule Node in the rule engine. Configure it with your Project ID, target topic name, and service account key.

Integration status is not Active
  1. Confirm the Project ID and Subscription ID exactly match the values in the GCP Console.
  2. Verify the Service account key JSON is complete and belongs to an active service account.
  3. Check that the service account has roles/pubsub.subscriber on the subscription.
  4. Ensure the Cloud Pub/Sub API is enabled in your GCP project.
Messages are not appearing in ThingsBoard
  1. Check the integration Events tab for errors.
  2. Confirm the pull subscription is attached to the correct topic and has no expiration policy that deactivated it.
  3. Use the Converter Events tab to inspect the raw In payload — verify the uplink converter handles the actual message format.