diff --git a/iot/beta-features/gateway/README.md b/iot/beta-features/gateway/README.md
deleted file mode 100644
index 349b47496b..0000000000
--- a/iot/beta-features/gateway/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-# Google Cloud IoT Core NodeJS Gateway sample
-
-This sample app demonstrates sending telemetry data on behalf of a device using the Cloud IoT Core gateways.
-
-# Setup
-
-Run the following command to install the library dependencies for NodeJS:
-
- npm install
-
-# Running the sample
-
- Commands:
- createGateway
- listGateways
- bindDeviceToGateway
- unbindDeviceFromGateway
- listDevicesForGateway
-
- listen Listen for config messages on a gateway and device
- relayData Sends data on behalf of a device.
-
- Options:
- --projectId, -p The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT
- environment variables. [string]
- --serviceAccount, -s The path to your service credentials JSON. [string]
- --cloudRegion, -c [string] [default: "us-central1"]
- --help Show help [boolean]
-
- Examples:
- node hub.js relayData my-device my-registry "test"
-
- For more information, see https://cloud.google.com/iot-core/docs
-
-# Notes
-
-By default, gateways use the "Association only" method for authentication, which means the device does not have to store its own JWT. For other authentication methods, check [here for more information](https://cloud.google.com/iot/docs/how-tos/gateways/manage-gateways#authentication_methods).
\ No newline at end of file
diff --git a/iot/beta-features/gateway/gateway.js b/iot/beta-features/gateway/gateway.js
deleted file mode 100644
index 75cf42594e..0000000000
--- a/iot/beta-features/gateway/gateway.js
+++ /dev/null
@@ -1,1155 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/* eslint-disable prefer-destructuring */
-
-'use strict';
-
-// [START iot_gateway_include]
-const fs = require('fs');
-const {google} = require('googleapis');
-const jwt = require('jsonwebtoken');
-const mqtt = require('mqtt');
-// [END iot_gateway_include]
-
-// [START iot_gateway_client_config]
-const API_VERSION = 'v1';
-const DISCOVERY_API = 'https://cloudiot.googleapis.com/$discovery/rest';
-
-// Returns an authorized API client by discovering the Cloud IoT Core API with
-// the provided API key.
-const getClient = async () => {
- const authClient = await google.auth.getClient({
- scopes: ['https://www.googleapis.com/auth/cloud-platform'],
- });
-
- const discoveryUrl = `${DISCOVERY_API}?version=${API_VERSION}`;
-
- google.options({
- auth: authClient,
- });
-
- try {
- return google.discoverAPI(discoveryUrl);
- } catch (err) {
- console.log('Error during API discovery.', err);
- }
-};
-// [END iot_gateway_client_config]
-
-// [START iot_gateway_client_backoff_variables]
-// The initial backoff time after a disconnection occurs, in seconds.
-const MINIMUM_BACKOFF_TIME = 1;
-
-// The maximum backoff time before giving up, in seconds.
-const MAXIMUM_BACKOFF_TIME = 32;
-
-// Whether to wait with exponential backoff before publishing.
-let shouldBackoff = false;
-
-// The current backoff time.
-let backoffTime = 1;
-
-// Whether an asynchronous publish chain is in progress
-let publishChainInProgress = false;
-
-// [END iot_gateway_client_backoff_variables]
-
-// Create a Cloud IoT Core JWT for the given project id, signed with the given
-// private key.
-// [START iot_mqtt_jwt]
-const createJwt = (projectId, privateKeyFile, algorithm) => {
- // Create a JWT to authenticate this device. The device will be disconnected
- // after the token expires, and will have to reconnect with a new token. The
- // audience field should always be set to the GCP project id.
- const token = {
- iat: parseInt(Date.now() / 1000),
- exp: parseInt(Date.now() / 1000) + 20 * 60, // 20 minutes
- aud: projectId,
- };
- const privateKey = fs.readFileSync(privateKeyFile);
- return jwt.sign(token, privateKey, {algorithm: algorithm});
-};
-// [END iot_mqtt_jwt]
-
-// Creates a gateway.
-const createGateway = (
- client,
- projectId,
- cloudRegion,
- registryId,
- gatewayId,
- certificateFile,
- algorithm
-) => {
- // [START create_gateway]
- // const cloudRegion = 'us-central1';
- // const deviceId = 'my-unauth-device';
- // const gatewayId = 'my-gateway';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
- console.log('Creating gateway:', gatewayId);
-
- const certFormat = algorithm === 'ES256' ? 'ES256_PEM' : 'RSA_X509_PEM';
-
- console.log(certFormat);
-
- const createRequest = {
- parent: parentName,
- resource: {
- id: gatewayId,
- credentials: [
- {
- publicKey: {
- format: certFormat,
- key: fs.readFileSync(certificateFile).toString(),
- },
- },
- ],
- gatewayConfig: {
- gatewayType: 'GATEWAY',
- gatewayAuthMethod: 'ASSOCIATION_ONLY',
- },
- },
- };
-
- client.projects.locations.registries.devices.create(
- createRequest,
- (err, res) => {
- if (err) {
- console.log('Could not create device');
- console.log(err);
- } else {
- console.log('Created device');
- console.log(res.data);
- }
- }
- );
- // [END create_gateway]
-};
-
-// Creates a device to bind to a gateway.
-const createDeviceForGateway = async (
- client,
- projectId,
- cloudRegion,
- registryId,
- deviceId
-) => {
- // [START create_device]
- // const cloudRegion = 'us-central1';
- // const deviceId = 'my-unauth-device';
- // const gatewayId = 'my-gateway';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
- const getRequest = {
- name: `${parentName}/devices/${deviceId}`,
- };
-
- let exists = false;
- let device = {};
- try {
- const {data} = await client.projects.locations.registries.devices.get(
- getRequest
- );
- console.log('Device exists');
- device = data;
- exists = true;
- } catch (err) {
- // Device not found
- console.log('Error while getting device', err);
- }
-
- if (exists) {
- return device;
- } else {
- console.log('Creating device:', deviceId);
-
- const createRequest = {
- parent: parentName,
- resource: {
- id: deviceId,
- gatewayConfig: {
- gatewayType: 'NON_GATEWAY',
- gatewayAuthMethod: 'ASSOCIATION_ONLY',
- },
- },
- };
-
- try {
- const {data} = await client.projects.locations.registries.devices.create(
- createRequest
- );
- console.log('Created device');
- device = data;
- console.log(device);
- return device;
- } catch (err) {
- console.log('Could not create device');
- console.log(err);
- }
- }
- // [END create_device]
-};
-
-// Binds a device to a gateway so that it can be attached.
-const bindDeviceToGateway = async (
- client,
- projectId,
- cloudRegion,
- registryId,
- deviceId,
- gatewayId
-) => {
- // [START bind_device_to_gateway]
- // const cloudRegion = 'us-central1';
- // const deviceId = 'my-unauth-device';
- // const gatewayId = 'my-gateway';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- const device = await createDeviceForGateway(
- client,
- projectId,
- cloudRegion,
- registryId,
- deviceId,
- gatewayId
- );
-
- console.log(`Binding device: ${JSON.stringify(device.id)}`);
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
-
- const bindRequest = {
- parent: parentName,
- deviceId: device.id,
- gatewayId: gatewayId,
- };
-
- try {
- await client.projects.locations.registries.bindDeviceToGateway(bindRequest);
- console.log('Bound device to', gatewayId);
- } catch (err) {
- console.log('Could not bind device', err);
- }
- // [END bind_device_to_gateway]
-};
-
-// Unbinds a device from a gateway.
-const unbindDeviceFromGateway = async (
- client,
- projectId,
- cloudRegion,
- registryId,
- deviceId,
- gatewayId
-) => {
- // [START unbind_device_to_gateway]
- // const cloudRegion = 'us-central1';
- // const deviceId = 'my-unauth-device';
- // const gatewayId = 'my-gateway';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- console.log(`Unbinding device: ${deviceId}`);
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
-
- const unbindRequest = {
- parent: parentName,
- deviceId: deviceId,
- gatewayId: gatewayId,
- };
-
- try {
- await client.projects.locations.registries.unbindDeviceFromGateway(
- unbindRequest
- );
- console.log('Device no longer bound.');
- } catch (err) {
- console.log('Could not unbind device', err);
- }
- // [END unbind_device_to_gateway]
-};
-
-// Unbinds the given device from all gateways
-const unbindDeviceFromAllGateways = async (
- client,
- projectId,
- cloudRegion,
- registryId,
- deviceId
-) => {
- const parentName = `projects/${projectId}/locations/${cloudRegion}`;
- const registryName = `${parentName}/registries/${registryId}`;
- const request = {
- name: `${registryName}/devices/${deviceId}`,
- };
-
- // get information about this device
- let device;
- try {
- const {data} = await client.projects.locations.registries.devices.get(
- request
- );
- device = data;
- } catch (err) {
- console.error('Could not get device', err);
- return;
- }
-
- if (device) {
- const isGateway = device.gatewayConfig.gatewayType === 'GATEWAY';
-
- if (!isGateway) {
- const listGatewaysForDeviceRequest = {
- parent: registryName,
- 'gatewayListOptions.associationsDeviceId': deviceId,
- };
-
- // get list of all gateways this non-gateway device is bound to
- let gateways = [];
- try {
- const {data} = await client.projects.locations.registries.devices.list(
- listGatewaysForDeviceRequest
- );
-
- if (data.devices && data.devices.length > 0) {
- gateways = data.devices;
- }
- } catch (err) {
- console.error('Could not list gateways', err);
- return;
- }
-
- const promises = gateways.map(gateway => {
- const unbindRequest = {
- parent: registryName,
- deviceId: device.id,
- gatewayId: gateway.id,
- };
-
- // for each gateway, make the call to unbind it
- return client.projects.locations.registries.unbindDeviceFromGateway(
- unbindRequest
- );
- });
-
- await Promise.all(promises);
- }
- }
-};
-
-const unbindAllDevices = async (client, projectId, cloudRegion, registryId) => {
- const parentName = `projects/${projectId}/locations/${cloudRegion}`;
- const registryName = `${parentName}/registries/${registryId}`;
- const request = {
- parent: registryName,
- };
-
- // get information about this device
- let devices;
- try {
- const {data} = await client.projects.locations.registries.devices.list(
- request
- );
-
- if (!data) {
- return;
- }
-
- devices = data.devices;
- } catch (err) {
- console.error('Could not list devices', err);
- return;
- }
-
- if (devices && devices.length > 0) {
- const promises = devices.map(device => {
- if (device) {
- const isGateway =
- device.gatewayConfig &&
- device.gatewayConfig.gatewayType === 'GATEWAY';
-
- if (!isGateway) {
- return unbindDeviceFromAllGateways(
- client,
- projectId,
- cloudRegion,
- registryId,
- device.id
- );
- }
- }
- });
-
- await Promise.all(promises);
- }
-};
-
-// Lists gateways in a registry.
-const listGateways = async (client, projectId, cloudRegion, registryId) => {
- // [START list_gateways]
- // const cloudRegion = 'us-central1';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
- const request = {
- parent: parentName,
- fieldMask: 'config,gatewayConfig',
- };
-
- let devices;
- try {
- const {data} = await client.projects.locations.registries.devices.list(
- request
- );
- devices = data.devices;
- } catch (err) {
- console.log('Could not list devices');
- console.log(err);
- return;
- }
-
- console.log('Current gateways in registry:');
- devices.forEach(device => {
- if (
- device.gatewayConfig !== undefined &&
- device.gatewayConfig.gatewayType === 'GATEWAY'
- ) {
- console.log('----\n', device);
- } else {
- console.log('\t', device);
- }
- });
- // [END list_gateways]
-};
-
-// Lists devices bound to a gateway.
-const listDevicesForGateway = async (
- client,
- projectId,
- cloudRegion,
- registryId,
- gatewayId
-) => {
- // [START list_devices_for_gateway]
- // const cloudRegion = 'us-central1';
- // const gatewayId = 'my-gateway';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
- const request = {
- parent: parentName,
- 'gatewayListOptions.associationsGatewayId': gatewayId,
- };
-
- let devices;
- try {
- const {data} = await client.projects.locations.registries.devices.list(
- request
- );
- devices = data.devices;
- } catch (err) {
- console.log('Could not list devices');
- console.log(err);
- return;
- }
-
- console.log('Current devices bound to gateway: ', gatewayId);
- if (devices && devices.length > 0) {
- devices.forEach(device => {
- console.log(`\tDevice: ${device.numId} : ${device.id}`);
- });
- } else {
- console.log('No devices bound to this gateway.');
- }
- // [END list_devices_for_gateway]
-};
-
-// Lists gateways a given device is bound to.
-const listGatewaysForDevice = async (
- client,
- projectId,
- cloudRegion,
- registryId,
- deviceId
-) => {
- // [START list_gateways_for_device]
- // const cloudRegion = 'us-central1';
- // const deviceId = 'my-device';
- // const projectId = 'adjective-noun-123';
- // const registryId = 'my-registry';
- const parentName = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}`;
- const request = {
- parent: parentName,
- 'gatewayListOptions.associationsDeviceId': deviceId,
- };
-
- let devices;
- try {
- const {data} = await client.projects.locations.registries.devices.list(
- request
- );
- devices = data.devices;
- } catch (err) {
- console.log('Could not list gateways for device');
- console.log(err);
- return;
- }
-
- console.log('Current gateways for device:', deviceId);
- if (devices && devices.length > 0) {
- devices.forEach(gateway => {
- console.log(`\tDevice: ${gateway.numId} : ${gateway.id}`);
- });
- } else {
- console.log('No gateways associated with this device.');
- }
- // [END list_gateways_for_device]
-};
-
-// Attaches a device to a gateway.
-const attachDevice = async (deviceId, client) => {
- // [START attach_device]
- // const deviceId = 'my-unauth-device';
- const attachTopic = `/devices/${deviceId}/attach`;
- console.log(`Attaching: ${attachTopic}`);
- const attachPayload = '{}';
-
- try {
- await client.publish(attachTopic, attachPayload, {qos: 1});
-
- shouldBackoff = false;
- backoffTime = MINIMUM_BACKOFF_TIME;
- } catch (err) {
- console.log(err);
- }
- // [END attach_device]
-};
-
-// Detaches a device from a gateway.
-const detachDevice = async (deviceId, client) => {
- // [START detach_device]
- const detachTopic = `/devices/${deviceId}/detach`;
- console.log(`Detaching: ${detachTopic}`);
- const detachPayload = '{}';
-
- try {
- await client.publish(detachTopic, detachPayload, {qos: 1});
-
- shouldBackoff = false;
- backoffTime = MINIMUM_BACKOFF_TIME;
- } catch (err) {
- console.log(err);
- }
- // [END detach_device]
-};
-
-// Listen for configuration messages on a gateway and bound device.
-const listenForConfigMessages = (
- gatewayId,
- deviceId,
- registryId,
- projectId,
- region,
- algorithm,
- privateKeyFile,
- mqttBridgeHostname,
- mqttBridgePort,
- clientDuration
-) => {
- // [START listen_for_config_messages]
- // const parentName = `projects/${projectId}/locations/${region}`;
- // const registryName = `${parentName}/registries/${registryId}`;
-
- const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${gatewayId}`;
- console.log(mqttClientId);
- const connectionArgs = {
- host: mqttBridgeHostname,
- port: mqttBridgePort,
- clientId: mqttClientId,
- username: 'unused',
- password: createJwt(projectId, privateKeyFile, algorithm),
- protocol: 'mqtts',
- qos: 1,
- secureProtocol: 'TLSv1_2_method',
- };
-
- // Create a client, and connect to the Google MQTT bridge.
- const client = mqtt.connect(connectionArgs);
-
- client.on('connect', success => {
- if (!success) {
- console.log('Client not connected...');
- } else {
- console.log('Client connected: Gateway is listening, attaching device');
- attachDevice(deviceId, client);
-
- setTimeout(() => {
- // Subscribe to any configuration topics.
- client.subscribe(`/devices/${gatewayId}/config`, {qos: 1});
- client.subscribe(`/devices/${deviceId}/config`, {qos: 1});
-
- setTimeout(() => {
- detachDevice(deviceId, client);
- console.log('Closing connection to MQTT. Goodbye!');
- client.end(true);
- }, clientDuration); // Safely detach device and close connection.
- }, 5000);
- }
- });
-
- client.on('close', () => {
- console.log('Connection closed');
- shouldBackoff = true;
- });
-
- client.on('error', err => {
- console.log('error', err);
- });
-
- client.on('message', (topic, message) => {
- const decodedMessage = Buffer.from(message, 'base64').toString('ascii');
-
- if (topic === `/devices/${gatewayId}/errors`) {
- console.log(`message received on error topic: ${decodedMessage}`);
- } else {
- console.log(`message received on topic ${topic}: ${decodedMessage}`);
- }
- });
-
- client.on('packetsend', () => {
- // Note: logging packet send is very verbose
- });
- // [END listen_for_config_messages]
-};
-
-// Listen for error messages on a gateway.
-const listenForErrorMessages = (
- gatewayId,
- registryId,
- projectId,
- region,
- algorithm,
- privateKeyFile,
- mqttBridgeHostname,
- mqttBridgePort,
- clientDuration,
- deviceId
-) => {
- // [START listen_for_error_messages]
- // const parentName = `projects/${projectId}/locations/${region}`;
- // const registryName = `${parentName}/registries/${registryId}`;
-
- const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${gatewayId}`;
- console.log(mqttClientId);
- const connectionArgs = {
- host: mqttBridgeHostname,
- port: mqttBridgePort,
- clientId: mqttClientId,
- username: 'unused',
- password: createJwt(projectId, privateKeyFile, algorithm),
- protocol: 'mqtts',
- qos: 1,
- secureProtocol: 'TLSv1_2_method',
- };
-
- // Create a client, and connect to the Google MQTT bridge.
- const client = mqtt.connect(connectionArgs);
-
- client.on('connect', success => {
- if (!success) {
- console.log('Client not connected...');
- } else {
- setTimeout(() => {
- // Subscribe to gateway error topic.
- client.subscribe(`/devices/${gatewayId}/errors`, {qos: 0});
-
- attachDevice(deviceId, client);
-
- setTimeout(() => {
- console.log('Closing connection to MQTT. Goodbye!');
- client.end(true);
- }, clientDuration); // Safely detach device and close connection.
- }, 5000);
- }
- });
-
- client.on('close', () => {
- console.log('Connection closed');
- shouldBackoff = true;
- });
-
- client.on('error', err => {
- console.log('error', err);
- });
-
- client.on('message', (topic, message) => {
- const decodedMessage = Buffer.from(message, 'base64').toString('ascii');
-
- console.log(`message received on error topic ${topic}: ${decodedMessage}`);
- });
-
- client.on('packetsend', () => {
- // Note: logging packet send is very verbose
- });
- // [END listen_for_error_messages]
-};
-
-// Sends telemetry on behalf of a device.
-const sendDataFromBoundDevice = (
- gatewayId,
- deviceId,
- registryId,
- projectId,
- region,
- algorithm,
- privateKeyFile,
- mqttBridgeHostname,
- mqttBridgePort,
- numMessages,
- tokenExpMins
-) => {
- // [START iot_send_delegate_data]
- // const parentName = `projects/${projectId}/locations/${region}`;
- // const registryName = `${parentName}/registries/${registryId}`;
- // const binaryData = Buffer.from(data).toString('base64');
- // const request = {
- // name: `${registryName}/devices/${deviceId}`,
- // binaryData: binaryData
- // };
-
- const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${gatewayId}`;
- console.log(`MQTT client id: ${mqttClientId}`);
- const connectionArgs = {
- host: mqttBridgeHostname,
- port: mqttBridgePort,
- clientId: mqttClientId,
- username: 'unused',
- password: createJwt(projectId, privateKeyFile, algorithm),
- protocol: 'mqtts',
- qos: 1,
- secureProtocol: 'TLSv1_2_method',
- };
-
- // Create a client, and connect to the Google MQTT bridge.
- const iatTime = parseInt(Date.now() / 1000);
- const client = mqtt.connect(connectionArgs);
-
- client.on('connect', success => {
- if (!success) {
- console.log('Client not connected...');
- } else if (!publishChainInProgress) {
- console.log('Client connected: Attaching device');
- attachDevice(deviceId, client);
- setTimeout(() => {
- console.log('Client connected: Gateway is ready to relay');
- publishAsync(
- client,
- iatTime,
- tokenExpMins,
- 0,
- numMessages,
- registryId,
- deviceId,
- gatewayId,
- connectionArgs,
- projectId,
- privateKeyFile,
- algorithm
- );
- }, 5000);
- }
- });
-
- client.on('close', () => {
- console.log('Connection closed');
- shouldBackoff = true;
- });
-
- client.on('error', err => {
- console.log('error', err);
- });
-
- client.on('message', (topic, message) => {
- console.log(
- 'message received: ',
- Buffer.from(message, 'base64').toString('ascii')
- );
- });
-
- client.on('packetsend', () => {
- // Note: logging packet send is very verbose
- });
- // [END iot_send_delegate_data]
-};
-
-// Publish numMessages messages asynchronously, starting from message
-// messagesSent.
-const publishAsync = (
- client,
- iatTime,
- tokenExpMins,
- messagesSent,
- numMessages,
- registryId,
- deviceId,
- gatewayId,
- connectionArgs,
- projectId,
- privateKeyFile,
- algorithm
-) => {
- // [START iot_mqtt_publish]
- // If we have published enough messages or backed off too many times, stop.
- if (messagesSent > numMessages || backoffTime >= MAXIMUM_BACKOFF_TIME) {
- if (backoffTime >= MAXIMUM_BACKOFF_TIME) {
- console.log('Backoff time is too high. Giving up.');
- }
- if (messagesSent >= numMessages) {
- detachDevice(deviceId, client);
- }
- console.log('Closing connection to MQTT. Goodbye!');
- client.end();
- publishChainInProgress = false;
- return;
- }
-
- // Publish and schedule the next publish.
- publishChainInProgress = true;
- let publishDelayMs = 0;
- if (shouldBackoff) {
- publishDelayMs = 1000 * (backoffTime + Math.random());
- backoffTime *= 2;
- console.log(`Backing off for ${publishDelayMs}ms before publishing.`);
- }
- let mqttTopic = `/devices/${gatewayId}/state`;
- let payload = `${registryId}/${gatewayId}-connected-${new Date().getTime()}`;
- console.log(`Publishing message ${messagesSent}/${numMessages}`);
- if (messagesSent > 0) {
- mqttTopic = `/devices/${deviceId}/state`;
- payload = `${registryId}/${deviceId}-payload-${messagesSent}`;
- }
-
- setTimeout(() => {
- // Publish "payload" to the MQTT topic. qos=1 means at least once delivery.
- // Cloud IoT Core also supports qos=0 for at most once delivery.
- console.log(`Publishing message: ${payload} to ${mqttTopic}`);
- client.publish(mqttTopic, payload, {qos: 1}, err => {
- if (!err) {
- shouldBackoff = false;
- backoffTime = MINIMUM_BACKOFF_TIME;
- }
- });
-
- const schedulePublishDelayMs = 5000; // messageType === 'events' ? 1000 : 2000;
- setTimeout(() => {
- // [START iot_mqtt_jwt_refresh]
- const secsFromIssue = parseInt(Date.now() / 1000) - iatTime;
- if (secsFromIssue > tokenExpMins * 60) {
- iatTime = parseInt(Date.now() / 1000);
- console.log(`\tRefreshing token after ${secsFromIssue} seconds.`);
-
- client.end();
- connectionArgs.password = createJwt(
- projectId,
- privateKeyFile,
- algorithm
- );
- client = mqtt.connect(connectionArgs);
- }
- // [END iot_mqtt_jwt_refresh]
- publishAsync(
- client,
- iatTime,
- tokenExpMins,
- messagesSent + 1,
- numMessages,
- registryId,
- deviceId,
- gatewayId
- );
- }, schedulePublishDelayMs);
- }, publishDelayMs);
- // [END iot_mqtt_publish]
-};
-
-let argv = require(`yargs`) // eslint-disable-line
- .demandCommand(1, 'You need at least one command before moving on')
- .options({
- algorithm: {
- default: 'RS256',
- description: 'Encryption algorithm to generate the JWT.',
- requiresArg: true,
- demandOption: true,
- choices: ['RS256', 'ES256'],
- type: 'string',
- },
- clientDuration: {
- default: 60000,
- description: 'Duration in milliseconds for MQTT client to run',
- requiresArg: true,
- type: 'number',
- },
- cloudRegion: {
- alias: 'c',
- default: 'us-central1',
- requiresArg: true,
- type: 'string',
- },
- deviceId: {
- description: 'Cloud IoT device ID.',
- requiresArg: false,
- demandOption: false,
- type: 'string',
- },
- gatewayId: {
- description: 'Cloud IoT gateway ID.',
- requiresArg: false,
- demandOption: false,
- type: 'string',
- },
- mqttBridgePort: {
- default: 8883,
- description: 'MQTT bridge port.',
- requiresArg: true,
- type: 'number',
- },
- mqttBridgeHostname: {
- default: 'mqtt.googleapis.com',
- description: 'MQTT bridge hostname.',
- requiresArg: true,
- type: 'string',
- },
- privateKeyFile: {
- description: 'Path to private key file.',
- requiresArg: true,
- type: 'string',
- },
- projectId: {
- alias: 'p',
- default: process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT,
- description:
- 'The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variables.',
- requiresArg: true,
- type: 'string',
- },
- serviceAccount: {
- alias: 's',
- default: process.env.GOOGLE_APPLICATION_CREDENTIALS,
- description: 'The path to your service credentials JSON.',
- requiresArg: true,
- type: 'string',
- },
- tokenExpMins: {
- default: 20,
- description: 'Minutes to JWT token expiration.',
- requiresArg: true,
- type: 'number',
- },
- })
-
- .command(
- `createGateway `,
- `Creates a gateway`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await createGateway(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId,
- opts.gatewayId,
- opts.publicKeyFile,
- opts.algorithm
- );
- }
- )
- .command(
- `listGateways `,
- `Lists gateways in a registry.`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await listGateways(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId
- );
- }
- )
- .command(
- `bindDeviceToGateway `,
- `Binds a device to a gateway`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await bindDeviceToGateway(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId,
- opts.deviceId,
- opts.gatewayId
- );
- }
- )
- .command(
- `unbindDeviceFromGateway `,
- `Unbinds a device from a gateway`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await unbindDeviceFromGateway(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId,
- opts.deviceId,
- opts.gatewayId
- );
- }
- )
- .command(
- `unbindDeviceFromAllGateways `,
- `Unbinds a device from all gateways`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await unbindDeviceFromAllGateways(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId,
- opts.deviceId
- );
- }
- )
- .command(
- `unbindAllDevices `,
- `Unbinds all devices in a given registry. Mainly for clearing registries`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await unbindAllDevices(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId
- );
- }
- )
- .command(
- `listDevicesForGateway `,
- `Lists devices in a gateway.`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await listDevicesForGateway(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId,
- opts.gatewayId
- );
- }
- )
- .command(
- `listGatewaysForDevice `,
- `Lists gateways for a given device.`,
- {},
- async opts => {
- const client = await getClient(opts.serviceAccount);
- await listGatewaysForDevice(
- client,
- opts.projectId,
- opts.cloudRegion,
- opts.registryId,
- opts.deviceId
- );
- }
- )
- .command(
- `listen `,
- `Listens for configuration changes on a gateway and bound device.`,
- {},
- opts => {
- listenForConfigMessages(
- opts.gatewayId,
- opts.deviceId,
- opts.registryId,
- opts.projectId,
- opts.cloudRegion,
- opts.algorithm,
- opts.privateKeyFile,
- opts.mqttBridgeHostname,
- opts.mqttBridgePort,
- opts.clientDuration
- );
- }
- )
- .command(
- `listenForErrors `,
- `Listens for error messages on a gateway.`,
- {},
- opts => {
- listenForErrorMessages(
- opts.gatewayId,
- opts.registryId,
- opts.projectId,
- opts.cloudRegion,
- opts.algorithm,
- opts.privateKeyFile,
- opts.mqttBridgeHostname,
- opts.mqttBridgePort,
- opts.clientDuration,
- opts.deviceId
- );
- }
- )
- .command(
- `relayData `,
- `Sends data on behalf of a bound device.`,
- {
- numMessages: {
- default: 5,
- description: 'Number of messages to publish.',
- requiresArg: true,
- type: 'number',
- },
- },
- opts => {
- sendDataFromBoundDevice(
- opts.gatewayId,
- opts.deviceId,
- opts.registryId,
- opts.projectId,
- opts.cloudRegion,
- opts.algorithm,
- opts.privateKeyFile,
- opts.mqttBridgeHostname,
- opts.mqttBridgePort,
- opts.numMessages,
- opts.tokenExpMins
- );
- }
- )
- .example(`node $0 relayData my-device my-registry "test"`)
- .wrap(120)
- .recommendCommands()
- .epilogue(`For more information, see https://cloud.google.com/iot-core/docs`)
- .help()
- .strict().argv;
diff --git a/iot/beta-features/gateway/gateway.test.js b/iot/beta-features/gateway/gateway.test.js
deleted file mode 100644
index 1c742f154b..0000000000
--- a/iot/beta-features/gateway/gateway.test.js
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-'use strict';
-
-const path = require('path');
-const {PubSub} = require('@google-cloud/pubsub');
-const assert = require('assert');
-const tools = require('@google-cloud/nodejs-repo-tools');
-const uuid = require('uuid');
-
-const cmd = 'node gateway.js';
-const topicName = `nodejs-docs-samples-test-iot-${uuid.v4()}`;
-const registryName = `nodejs-test-registry-iot-${uuid.v4()}`;
-
-const helper = 'node manager.js';
-const cwdHelper = path.join(__dirname, '../../manager');
-const installDeps = 'npm install';
-const publicKeyParam = process.env.NODEJS_IOT_RSA_PUBLIC_CERT;
-const privateKeyParam = process.env.NODEJS_IOT_RSA_PRIVATE_KEY;
-
-const pubsub = new PubSub();
-
-before(async () => {
- tools.checkCredentials();
- const [topic] = await pubsub.createTopic(topicName);
- console.log(`Topic ${topic.name} created.`);
-
- await tools.runAsync(installDeps, cwdHelper);
- await tools.runAsync(`${helper} setupIotTopic ${topicName}`, cwdHelper);
- await tools.runAsync(
- `${helper} createRegistry ${registryName} ${topicName}`,
- cwdHelper
- );
- console.log(`Registry ${registryName} created`);
-});
-
-after(async () => {
- await tools.runAsync(`${helper} deleteRegistry ${registryName}`, cwdHelper);
- console.log(`Registry ${registryName} was deleted`);
-
- const topic = pubsub.topic(topicName);
- await topic.delete();
- console.log(`Topic ${topic.name} deleted.`);
-});
-
-it('should create a new gateway', async () => {
- // create gateway
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- const gatewayOut = await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- ); // test no error on create gateway
- assert.strictEqual(new RegExp('Created device').test(gatewayOut), true);
-
- // delete gateway with deleteDevice
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should list gateways', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- // look for output in list gateway
- const gateways = await tools.runAsync(`${cmd} listGateways ${registryName}`);
- assert.strictEqual(new RegExp(`${gatewayId}`).test(gateways), true);
-
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should bind existing device to gateway', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- // create device
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${helper} createRsa256Device ${deviceId} ${registryName} ${publicKeyParam}`,
- cwdHelper
- );
-
- // bind device to gateway
- const bind = await tools.runAsync(
- `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
- );
-
- assert.strictEqual(new RegExp('Device exists').test(bind), true);
- assert.strictEqual(new RegExp('Bound device').test(bind), true);
- assert.strictEqual(new RegExp('Could not bind device').test(bind), false);
-
- // test unbind
- const unbind = await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- assert.strictEqual(new RegExp('Device no longer bound').test(unbind), true);
-
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should bind new device to gateway', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- // binding a non-existing device should create it
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- const bind = await tools.runAsync(
- `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
- );
-
- assert.strictEqual(new RegExp('Created device').test(bind), true);
- assert.strictEqual(new RegExp('Bound device').test(bind), true);
- assert.strictEqual(new RegExp('Could not bind device').test(bind), false);
-
- // unbind and delete device and gateway
- const unbind = await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- assert.strictEqual(new RegExp('Device no longer bound').test(unbind), true);
-
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should list devices bound to gateway', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- // binding a non-existing device should create it
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
- );
-
- const devices = await tools.runAsync(
- `${cmd} listDevicesForGateway ${registryName} ${gatewayId}`
- );
-
- assert.strictEqual(new RegExp(deviceId).test(devices), true);
- assert.strictEqual(new RegExp('No devices bound').test(devices), false);
- // cleanup
- await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should list gateways for bound device', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- // binding a non-existing device should create it
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
- );
-
- const devices = await tools.runAsync(
- `${cmd} listGatewaysForDevice ${registryName} ${deviceId}`
- );
-
- assert.strictEqual(new RegExp(gatewayId).test(devices), true);
- assert.strictEqual(
- new RegExp('No gateways associated with this device').test(devices),
- false
- );
-
- // cleanup
- await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should listen for bound device config message', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
- );
-
- // listen for configuration changes
- const out = await tools.runAsync(
- `${cmd} listen ${deviceId} ${gatewayId} ${registryName} ${privateKeyParam} --clientDuration=30000`
- );
-
- assert.strictEqual(new RegExp('message received').test(out), true);
-
- // cleanup
- await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should listen for error topic messages', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- // create a device but don't associate it with the gateway
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${helper} createRsa256Device ${deviceId} ${registryName} ${publicKeyParam}`,
- cwdHelper
- );
-
- // check error topic contains error of attaching a device that is not bound
- const out = await tools.runAsync(
- `${cmd} listenForErrors ${gatewayId} ${registryName} ${deviceId} ${privateKeyParam} --clientDuration=30000`
- );
-
- assert.strictEqual(
- new RegExp(`DeviceId ${deviceId} is not associated with Gateway`).test(out),
- true
- );
-
- // cleanup
- await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
-
-it('should send data from bound device', async () => {
- const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} createGateway ${registryName} ${gatewayId} RS256 ${publicKeyParam}`
- );
-
- const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
- await tools.runAsync(
- `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
- );
-
- // relay telemetry on behalf of device
- const out = await tools.runAsync(
- `${cmd} relayData ${deviceId} ${gatewayId} ${registryName} ${privateKeyParam} --numMessages=5`
- );
-
- assert.strictEqual(new RegExp('Publishing message 5/5').test(out), true);
- assert.strictEqual(new RegExp('Error: Connection refused').test(out), false);
-
- await tools.runAsync(
- `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
- );
- await tools.runAsync(
- `${helper} deleteDevice ${gatewayId} ${registryName}`,
- cwdHelper
- );
- await tools.runAsync(
- `${helper} deleteDevice ${deviceId} ${registryName}`,
- cwdHelper
- );
-});
diff --git a/iot/beta-features/gateway/package.json b/iot/beta-features/gateway/package.json
deleted file mode 100644
index 1d820d7a88..0000000000
--- a/iot/beta-features/gateway/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "name": "nodejs-docs-samples-iot-manager",
- "version": "0.0.1",
- "description": "Example of Cloud IoT Core gateways feature",
- "main": "manager.js",
- "license": "Apache-2.0",
- "author": "Google LLC",
- "repository": {
- "type": "git",
- "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
- },
- "engines": {
- "node": ">=8.0.0"
- },
- "scripts": {
- "test": "repo-tools test install --cmd=npm -- run unit-test",
- "unit-test": "mocha *.test.js --timeout=600000"
- },
- "dependencies": {
- "googleapis": "^45.0.0",
- "jsonwebtoken": "^8.3.0",
- "mqtt": "^3.0.0",
- "yargs": "^15.0.0"
- },
- "devDependencies": {
- "@google-cloud/nodejs-repo-tools": "^3.3.0",
- "mocha": "^6.0.0",
- "@google-cloud/pubsub": "^1.0.0",
- "uuid": "^3.1.0"
- },
- "cloud-repo-tools": {
- "requiresKeyFile": true,
- "requiresProjectId": true
- }
-}
diff --git a/iot/beta-features/gateway/resources/README.md b/iot/beta-features/gateway/resources/README.md
deleted file mode 100644
index 29a1f453ee..0000000000
--- a/iot/beta-features/gateway/resources/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Test public certificate files
-
-The certificates in this folder are only provided for testing and should not be
-used for registering or connecting your devices.