1
votes

I am using the Google Cloud IoT with Pub/Sub.

I have a device reading sensor data and sending it to a topic in Pub/Sub.

I have a topic cloud function that is triggered by this message and I would like to have the device configuration updated, however I am unable to do so due to the following permission error.

index.js :

/**
 * Triggered from a message on a Cloud Pub/Sub topic.
 *
 * @param {!Object} event The Cloud Functions event.
 * @param {!Function} The callback function.
 */

  var google = require('googleapis');
    //var tt = google.urlshortener('v1');
  //console.log(Object.getOwnPropertyNames(google.getAPIs()));
  var cloudiot = google.cloudiot('v1');

function handleDeviceGet(authClient, name, device_id, err, data) {
    if (err) {
        console.log('Error with get device:', device_id);
        console.log(err);
        return;
    }

    console.log('Got device:', device_id);
    console.log(data);
    console.log(data.config);

    var data2 = JSON.parse(
        Buffer.from(data.config.binaryData, 'base64').toString());
    console.log(data2);
    data2.on = !data2.on;
    console.log(data2);

    var request2 = {
        name: name,
        resource: {
            'versionToUpdate' : data.config.version,
            'binaryData' : Buffer(JSON.stringify(data2)).toString('base64')
        },
        auth: authClient
    };

    console.log('request2' + request2);

    var devices = cloudiot.projects.locations.registries.devices;
    devices.modifyCloudToDeviceConfig(request2, (err, data) => {
        if (err) {
            console.log('Error patching device:', device_id);
            console.log(err);
        } else {
            console.log('Patched device:', device_id);
            console.log(data);
        }
    });
}

const handleAuth = (device_id) => { 
    console.log(device_id);
    return (err, authClient) => {
      const project_id = 'animated-bonsai-195009';
      const cloud_region = 'us-central1';
      const registry_id = 'reg1';

      const name = `projects / ${project_id} /locations / ${cloud_region} /` +
            `registries / ${registry_id} /devices / ${device_id}`;

      if (err) {
          console.log(err);
      }

      if (authClient.createScopedRequired &&
          authClient.createScopedRequired()) {
          authClient = authClient.createScoped(
              ['https://www.googleapis.com/auth/cloud-platforme']);
      }

      var request = {
          name: name,
          auth: authClient
      };

      // Get device version
      var devices = cloudiot.projects.locations.registries.devices;
      devices.get(request, (err, data) =>
                  handleDeviceGet(authClient, name, device_id, err, data));
  }
                                      };

exports.subscribe = (event, callback) => {

  // The Cloud Pub/Sub Message object.
  const pubsubMessage = event.data;

  // We're just going to log the message to prove that
  // it worked.

  var obj = JSON.parse(Buffer.from(pubsubMessage.data, 'base64').toString());

  console.log(Buffer.from(pubsubMessage.data, 'base64').toString());
  console.log(event);
  console.log(Object.getOwnPropertyNames(event));
  console.log(callback);

  let message = {
    "watter": 1
  };
  message = new Buffer(JSON.stringify(message));

  const req = {
        name: event.data.deviceId,
        resource: message
    };
    console.log(obj.deviceId);
  google.auth.getApplicationDefault(handleAuth(obj['deviceId']));

  // Don't forget to call the callback.
  callback();
};

package.json :

{
  "name": "sample-pubsub",
  "version": "0.0.1",
  "dependencies": {
    "googleapis": "25.0.0"
  }
}

Error:

Output Logged error

1
Please copy the text of error messages into the question itself so it's easier to read and search.Doug Stevenson
I copied the useful part: Error: A Not Found error was returned while attempting to retrieve an accesstoken for the Compute Engine built-in service account. This may be because the Compute Engine instance does not have any permission scopes specified.Guillem Xercavins
I am having the same problem with a cloud function: I'm trying to get the defaultCredentials in the Cloud Function environment, but I get the same error message.MartijnvdB

1 Answers

1
votes

A few options:

  • Check that you have enabled API access for the Google Cloud IoT Core API for the project used when creating the Google Cloud Function.
  • Check that you have enabled billing for your project
  • If you are deploying your Google Cloud Functions with gcloud beta functions deploy ... from the folder with your .js and package.json files, you may want to set the environment variables (GCLOUD_PROJECT and GOOGLE_APPLICATION_CREDENTIALS) or use gcloud auth application-default login before deploying in case you have multiple Google Cloud projects and need to enable the API on the configured one.

Update This community tutorial shows you how to do this - note that there have been some updates to Google Cloud Functions that require you to use a newer version of the Node JS client library as is done in the NodeJS sample and as corrected in this PR, note the version of the client library in package.json.